[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15469] branches/apricot/source: Apricot Branch

Brecht Van Lommel brechtvanlommel at pandora.be
Mon Jul 7 15:58:01 CEST 2008


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. @@




More information about the Bf-blender-cvs mailing list