Revision: 15469 http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15469 Author: blendix Date: 2008-07-07 15:57:29 +0200 (Mon, 07 Jul 2008)
Log Message: ----------- Apricot Branch ============== Some optimizations: * Only Apply mesh deformer if the mesh is actually modified, once per frame, this was done too often before. * GLSL shader binding is now faster, only goes over dynamics inputs instead of all of them, and frees more memory after compiling too. Modified Paths: -------------- branches/apricot/source/blender/gpu/intern/gpu_codegen.c branches/apricot/source/gameengine/Converter/BL_BlenderDataConversion.cpp branches/apricot/source/gameengine/Converter/BL_MeshDeformer.cpp branches/apricot/source/gameengine/Converter/BL_MeshDeformer.h branches/apricot/source/gameengine/Converter/BL_ShapeDeformer.h branches/apricot/source/gameengine/Converter/BL_SkinDeformer.cpp branches/apricot/source/gameengine/Converter/BL_SkinDeformer.h branches/apricot/source/gameengine/Ketsji/KX_Scene.cpp Modified: branches/apricot/source/blender/gpu/intern/gpu_codegen.c =================================================================== --- branches/apricot/source/blender/gpu/intern/gpu_codegen.c 2008-07-07 11:58:09 UTC (rev 15468) +++ branches/apricot/source/blender/gpu/intern/gpu_codegen.c 2008-07-07 13:57:29 UTC (rev 15469) @@ -152,13 +152,14 @@ char attribname[32]; /* attribute name */ int attribfirst; /* this is the first one that is bound */ GPUBuiltin builtin; /* builtin uniform */ + + char shadername[32]; /* name in shader */ } GPUInput; struct GPUPass { struct GPUPass *next, *prev; - ListBase nodes; - int firstbind; + ListBase inputs; struct GPUOutput *output; struct GPUShader *shader; }; @@ -730,92 +731,121 @@ return pass->shader; } -void GPU_pass_bind(GPUPass *pass) +void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes) { + GPUShader *shader = pass->shader; GPUNode *node; - GPUInput *input; - GPUShader *shader = pass->shader; - ListBase *nodes = &pass->nodes; - DynStr *ds; - char *name; + GPUInput *next, *input; + ListBase *inputs = &pass->inputs; + int extract; - if (!shader) + memset(inputs, 0, sizeof(*inputs)); + + if(!shader) return; - /* create textures first, otherwise messes up multitexture state for - * following textures*/ - for (node=nodes->first; node; node=node->next) - for (input=node->inputs.first; input; input=input->next) - if (input->ima) - input->tex = GPU_texture_from_blender(input->ima, input->iuser); - GPU_shader_bind(shader); for (node=nodes->first; node; node=node->next) { - for (input=node->inputs.first; input; input=input->next) { + for (input=node->inputs.first; input; input=next) { + next = input->next; + /* attributes don't need to be bound, they already have * an id that the drawing functions will use */ if(input->source == GPU_SOURCE_ATTRIB || input->source == GPU_SOURCE_BUILTIN) continue; - /* pass samplers and uniforms to opengl */ - if (input->link) - input->tex = NULL; /* input->link->tex; */ - - ds = BLI_dynstr_new(); - if (input->tex) - BLI_dynstr_printf(ds, "samp%d", input->texid); + if (input->ima || input->tex) + snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid); else - BLI_dynstr_printf(ds, "unf%d", input->id); - name = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); + snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id); - if (input->tex) { - if (input->bindtex) { - if(pass->firstbind); - GPU_texture_bind(input->tex, input->texid); - GPU_shader_uniform_texture(shader, name, input->tex); - } + /* pass non-dynamic uniforms to opengl */ + extract = 0; + + if(input->ima || input->tex) { + if (input->bindtex) + extract = 1; } else if (input->arraysize) { - if(pass->firstbind || input->dynamicvec) - GPU_shader_uniform_vector(shader, name, input->type, - input->arraysize, - (input->dynamicvec)? input->dynamicvec: input->vec); + if(input->dynamicvec) + extract = 1; + else + GPU_shader_uniform_vector(shader, input->shadername, input->type, + input->arraysize, input->vec); } else { - if(pass->firstbind || input->dynamicvec) - GPU_shader_uniform_vector(shader, name, input->type, 1, - (input->dynamicvec)? input->dynamicvec: input->vec); + if(input->dynamicvec) + extract = 1; + else + GPU_shader_uniform_vector(shader, input->shadername, input->type, 1, + input->vec); } - MEM_freeN(name); + /* extract nodes */ + if(extract) { + BLI_remlink(&node->inputs, input); + BLI_addtail(inputs, input); + } } } - pass->firstbind = 0; + GPU_shader_unbind(shader); } -void GPU_pass_unbind(GPUPass *pass) +void GPU_pass_bind(GPUPass *pass) { - GPUNode *node; GPUInput *input; GPUShader *shader = pass->shader; - ListBase *nodes = &pass->nodes; + ListBase *inputs = &pass->inputs; if (!shader) return; - for (node=nodes->first; node; node=node->next) { - for (input=node->inputs.first; input; input=input->next) { - if (input->tex) - if(input->bindtex) - GPU_texture_unbind(input->tex); - if (input->link || input->ima) - input->tex = 0; + /* create textures first, otherwise messes up multitexture state for + * following textures*/ + for (input=inputs->first; input; input=input->next) + if (input->ima) + input->tex = GPU_texture_from_blender(input->ima, input->iuser); + + GPU_shader_bind(shader); + + /* pass dynamic inputs to opengl, others were already done */ + for (input=inputs->first; input; input=input->next) { + if(input->ima || input->tex) { + if(input->tex) { + GPU_texture_bind(input->tex, input->texid); + GPU_shader_uniform_texture(shader, input->shadername, input->tex); + } } + else if (input->arraysize) { + GPU_shader_uniform_vector(shader, input->shadername, input->type, + input->arraysize, input->dynamicvec); + } + else { + GPU_shader_uniform_vector(shader, input->shadername, input->type, 1, + input->dynamicvec); + } } +} + +void GPU_pass_unbind(GPUPass *pass) +{ + GPUInput *input; + GPUShader *shader = pass->shader; + ListBase *inputs = &pass->inputs; + + if (!shader) + return; + + for (input=inputs->first; input; input=input->next) { + if (input->tex) + if(input->bindtex) + GPU_texture_unbind(input->tex); + if (input->ima) + input->tex = 0; + } GPU_shader_unbind(shader); } @@ -975,26 +1005,33 @@ BLI_addtail(&node->outputs, output); } -void GPU_node_free(GPUNode *node) +void GPU_inputs_free(ListBase *inputs) { GPUInput *input; - GPUOutput *output; - for (input=node->inputs.first; input; input=input->next) { - if (input->link) { + for(input=inputs->first; input; input=input->next) { + if(input->link) { GPU_node_link_free(input->link); } else if(input->tex && !input->dynamictex) GPU_texture_free(input->tex); } + BLI_freelistN(inputs); +} + +void GPU_node_free(GPUNode *node) +{ + GPUOutput *output; + + GPU_inputs_free(&node->inputs); + for (output=node->outputs.first; output; output=output->next) if (output->link) { output->link->output = NULL; GPU_node_link_free(output->link); } - BLI_freelistN(&node->inputs); BLI_freelistN(&node->outputs); MEM_freeN(node); } @@ -1315,13 +1352,12 @@ /* create pass */ pass = MEM_callocN(sizeof(GPUPass), "GPUPass"); - pass->nodes = *nodes; pass->output = outlink->output; pass->shader = shader; - pass->firstbind = 1; - /* take ownership over nodes */ - memset(nodes, 0, sizeof(*nodes)); + /* extract dynamic inputs and throw away nodes */ + GPU_nodes_extract_dynamic_inputs(pass, nodes); + GPU_nodes_free(nodes); return pass; } @@ -1329,7 +1365,7 @@ void GPU_pass_free(GPUPass *pass) { GPU_shader_free(pass->shader); - GPU_nodes_free(&pass->nodes); + GPU_inputs_free(&pass->inputs); MEM_freeN(pass); } Modified: branches/apricot/source/gameengine/Converter/BL_BlenderDataConversion.cpp =================================================================== --- branches/apricot/source/gameengine/Converter/BL_BlenderDataConversion.cpp 2008-07-07 11:58:09 UTC (rev 15468) +++ branches/apricot/source/gameengine/Converter/BL_BlenderDataConversion.cpp 2008-07-07 13:57:29 UTC (rev 15469) @@ -1681,13 +1681,15 @@ if (bHasArmature) dcont->LoadShapeDrivers(ob->parent); } else if (bHasArmature) { - BL_SkinDeformer *dcont = new BL_SkinDeformer(ob, (BL_SkinMeshObject*)meshobj ); + BL_SkinDeformer *dcont = new BL_SkinDeformer((BL_DeformableGameObject*)gameobj, + ob, (BL_SkinMeshObject*)meshobj); ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; } else if (bHasDvert) { // this case correspond to a mesh that can potentially deform but not with the // object to which it is attached for the moment. A skin mesh was created in // BL_ConvertMesh() so must create a deformer too! - BL_MeshDeformer *dcont = new BL_MeshDeformer(ob, (BL_SkinMeshObject*)meshobj ); + BL_MeshDeformer *dcont = new BL_MeshDeformer((BL_DeformableGameObject*)gameobj, + ob, (BL_SkinMeshObject*)meshobj); ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; } Modified: branches/apricot/source/gameengine/Converter/BL_MeshDeformer.cpp =================================================================== --- branches/apricot/source/gameengine/Converter/BL_MeshDeformer.cpp 2008-07-07 11:58:09 UTC (rev 15468) +++ branches/apricot/source/gameengine/Converter/BL_MeshDeformer.cpp 2008-07-07 13:57:29 UTC (rev 15469) @@ -39,6 +39,7 @@ #endif #include "RAS_IPolygonMaterial.h" +#include "BL_DeformableGameObject.h" #include "BL_MeshDeformer.h" #include "BL_SkinMeshObject.h" #include "DNA_mesh_types.h" @@ -47,7 +48,7 @@ #include "GEN_Map.h" #include "STR_HashedString.h" -bool BL_MeshDeformer::Apply(RAS_IPolyMaterial *mat) +bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*) { size_t i, j, index; vecVertexArray array; @@ -57,23 +58,37 @@ RAS_TexVert *tv; MVert *mvert; - // For each material - array = m_pMeshObject->GetVertexCache(mat); - mvarray = m_pMeshObject->GetMVertCache(mat); - diarray = m_pMeshObject->GetDIndexCache(mat); + // only apply once per frame if the mesh is actually modified + if(m_pMeshObject->MeshModified() && + m_lastDeformUpdate != m_gameobj->GetLastFrame()) { + // For each material + for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); + mit != m_pMeshObject->GetLastMaterial(); ++ mit) { + RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); - // For each array - for (i=0; i<array.size(); i++){ - // For each vertex - for (j=0; j<array[i]->size(); j++){ - tv = &((*array[i])[j]); - index = ((*diarray[i])[j]); + array = m_pMeshObject->GetVertexCache(mat); + mvarray = m_pMeshObject->GetMVertCache(mat); + diarray = m_pMeshObject->GetDIndexCache(mat); - mvert = &(m_bmesh->mvert[((*mvarray[i])[index])]); - tv->SetXYZ(MT_Point3(mvert->co)); + // For each array + for (i=0; i<array.size(); i++){ + // For each vertex + for (j=0; j<array[i]->size(); j++){ + tv = &((*array[i])[j]); + index = ((*diarray[i])[j]); + + mvert = &(m_bmesh->mvert[((*mvarray[i])[index])]); + tv->SetXYZ(MT_Point3(mvert->co)); + } + } } + + m_lastDeformUpdate = m_gameobj->GetLastFrame(); + + return true; } - return true; + + return false; } BL_MeshDeformer::~BL_MeshDeformer() Modified: branches/apricot/source/gameengine/Converter/BL_MeshDeformer.h @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org http://lists.blender.org/mailman/listinfo/bf-blender-cvs