[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [13608] trunk/blender/source/blender/ render/intern/source/occlusion.c:

Brecht Van Lommel brechtvanlommel at pandora.be
Fri Feb 8 16:39:29 CET 2008


Revision: 13608
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=13608
Author:   blendix
Date:     2008-02-08 16:39:29 +0100 (Fri, 08 Feb 2008)

Log Message:
-----------

Render optimization: approximate AO preprocessing is now partially
multithreaded.

Modified Paths:
--------------
    trunk/blender/source/blender/render/intern/source/occlusion.c

Modified: trunk/blender/source/blender/render/intern/source/occlusion.c
===================================================================
--- trunk/blender/source/blender/render/intern/source/occlusion.c	2008-02-08 15:36:39 UTC (rev 13607)
+++ trunk/blender/source/blender/render/intern/source/occlusion.c	2008-02-08 15:39:29 UTC (rev 13608)
@@ -107,9 +107,26 @@
 	float error;
 	float distfac;
 
+	int dothreadedbuild;
+	int totbuildthread;
+
 	OcclusionCache *cache;
 } OcclusionTree;
 
+typedef struct OcclusionThread {
+	Render *re;
+	StrandSurface *mesh;
+	float (*facecol)[3];
+	int begin, end;
+	int thread;
+} OcclusionThread;
+
+typedef struct OcclusionBuildThread {
+	OcclusionTree *tree;
+	int begin, end, depth;
+	OccNode *node;
+} OcclusionBuildThread;
+
 /* ------------------------- Shading --------------------------- */
 
 extern Render R; // meh
@@ -486,18 +503,30 @@
 	count[7]= end - offset[7];
 }
 
-static OccNode *occ_build_recursive(OcclusionTree *tree, int begin, int end, int depth)
+static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, int end, int depth);
+
+static void *exec_occ_build(void *data)
 {
-	OccNode *node, *child, tmpnode;
+	OcclusionBuildThread *othread= (OcclusionBuildThread*)data;
+
+	occ_build_recursive(othread->tree, othread->node, othread->begin, othread->end, othread->depth);
+
+	return 0;
+}
+
+static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, int end, int depth)
+{
+	ListBase threads;
+	OcclusionBuildThread othreads[BLENDER_MAX_THREADS];
+	OccNode *child, tmpnode;
 	OccFace *face;
-	int a, b, offset[TOTCHILD], count[TOTCHILD];
+	int a, b, totthread=0, offset[TOTCHILD], count[TOTCHILD];
 
 	/* keep track of maximum depth for stack */
 	if(depth > tree->maxdepth)
 		tree->maxdepth= depth;
 
 	/* add a new node */
-	node= BLI_memarena_alloc(tree->arena, sizeof(OccNode));
 	node->occlusion= 1.0f;
 
 	/* leaf node with only children */
@@ -512,6 +541,9 @@
 		/* order faces */
 		occ_build_8_split(tree, begin, end, offset, count);
 
+		if(depth == 1 && tree->dothreadedbuild)
+			BLI_init_threads(&threads, exec_occ_build, tree->totbuildthread);
+
 		for(b=0; b<TOTCHILD; b++) {
 			if(count[b] == 0) {
 				node->child[b].node= NULL;
@@ -522,10 +554,31 @@
 				node->childflag |= (1<<b);
 			}
 			else {
-				child= occ_build_recursive(tree, offset[b], offset[b]+count[b], depth+1);
+				if(tree->dothreadedbuild)
+					BLI_lock_thread(LOCK_CUSTOM1);
+
+				child= BLI_memarena_alloc(tree->arena, sizeof(OccNode));
 				node->child[b].node= child;
+
+				if(tree->dothreadedbuild)
+					BLI_unlock_thread(LOCK_CUSTOM1);
+
+				if(depth == 1 && tree->dothreadedbuild) {
+					othreads[totthread].tree= tree;
+					othreads[totthread].node= child;
+					othreads[totthread].begin= offset[b];
+					othreads[totthread].end= offset[b]+count[b];
+					othreads[totthread].depth= depth+1;
+					BLI_insert_thread(&threads, &othreads[totthread]);
+					totthread++;
+				}
+				else
+					occ_build_recursive(tree, child, offset[b], offset[b]+count[b], depth+1);
 			}
 		}
+
+		if(depth == 1 && tree->dothreadedbuild)
+			BLI_end_threads(&threads);
 	}
 
 	/* combine area, position and sh */
@@ -551,8 +604,6 @@
 	/* compute maximum distance from center */
 	node->dco= 0.0f;
 	occ_build_dco(tree, node, node->co, &node->dco);
-
-	return node;
 }
 
 static void occ_build_sh_normalize(OccNode *node)
@@ -630,8 +681,13 @@
 		}
 	}
 
+	/* threads */
+	tree->totbuildthread= (re->r.threads > 1 && totface > 10000)? 8: 1;
+	tree->dothreadedbuild= (tree->totbuildthread > 1);
+
 	/* recurse */
-	tree->root= occ_build_recursive(tree, 0, totface, 1);
+	tree->root= BLI_memarena_alloc(tree->arena, sizeof(OccNode));
+	occ_build_recursive(tree, tree->root, 0, totface, 1);
 
 #if 0
 	if(tree->doindirect) {
@@ -1446,11 +1502,46 @@
 
 /* ------------------------- External Functions --------------------------- */
 
+static void *exec_strandsurface_sample(void *data)
+{
+	OcclusionThread *othread= (OcclusionThread*)data;
+	Render *re= othread->re;
+	StrandSurface *mesh= othread->mesh;
+	float col[3], co[3], n[3], *co1, *co2, *co3, *co4;
+	int a, *face;
+
+	for(a=othread->begin; a<othread->end; a++) {
+		face= mesh->face[a];
+		co1= mesh->co[face[0]];
+		co2= mesh->co[face[1]];
+		co3= mesh->co[face[2]];
+
+		if(face[3]) {
+			co4= mesh->co[face[3]];
+
+			VecLerpf(co, co1, co3, 0.5f);
+			CalcNormFloat4(co1, co2, co3, co4, n);
+		}
+		else {
+			CalcCent3f(co, co1, co2, co3);
+			CalcNormFloat(co1, co2, co3, n);
+		}
+		VecMulf(n, -1.0f);
+
+		sample_occ_tree(re, re->occlusiontree, NULL, co, n, othread->thread, 0, col);
+		VECCOPY(othread->facecol[a], col);
+	}
+
+	return 0;
+}
+
 void make_occ_tree(Render *re)
 {
+	OcclusionThread othreads[BLENDER_MAX_THREADS];
 	StrandSurface *mesh;
-	float col[3], co[3], n[3], *co1, *co2, *co3, *co4;
-	int a, *face, *count;
+	ListBase threads;
+	float col[3], (*facecol)[3];
+	int a, totface, totthread, *face, *count;
 
 	/* ugly, needed for occ_face */
 	R= *re;
@@ -1466,27 +1557,35 @@
 
 		for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) {
 			count= MEM_callocN(sizeof(int)*mesh->totvert, "OcclusionCount");
+			facecol= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceCol");
 
-			for(a=0; a<mesh->totface; a++) {
-				face= mesh->face[a];
-				co1= mesh->co[face[0]];
-				co2= mesh->co[face[1]];
-				co3= mesh->co[face[2]];
+			totthread= (mesh->totface > 10000)? re->r.threads: 1;
+			totface= mesh->totface/totthread;
+			for(a=0; a<totthread; a++) {
+				othreads[a].re= re;
+				othreads[a].facecol= facecol;
+				othreads[a].thread= a;
+				othreads[a].mesh= mesh;
+				othreads[a].begin= a*totface;
+				othreads[a].end= (a == totthread-1)? mesh->totface: (a+1)*totface;
+			}
 
-				if(face[3]) {
-					co4= mesh->co[face[3]];
+			if(totthread == 1) {
+				exec_strandsurface_sample(&othreads[0]);
+			}
+			else {
+				BLI_init_threads(&threads, exec_strandsurface_sample, totthread);
 
-					VecLerpf(co, co1, co3, 0.5f);
-					CalcNormFloat4(co1, co2, co3, co4, n);
-				}
-				else {
-					CalcCent3f(co, co1, co2, co3);
-					CalcNormFloat(co1, co2, co3, n);
-				}
-				VecMulf(n, -1.0f);
+				for(a=0; a<totthread; a++)
+					BLI_insert_thread(&threads, &othreads[a]);
 
-				sample_occ_tree(re, re->occlusiontree, NULL, co, n, 0, 0, col);
+				BLI_end_threads(&threads);
+			}
 
+			for(a=0; a<mesh->totface; a++) {
+				face= mesh->face[a];
+
+				VECCOPY(col, facecol[a]);
 				VECADD(mesh->col[face[0]], mesh->col[face[0]], col);
 				count[face[0]]++;
 				VECADD(mesh->col[face[1]], mesh->col[face[1]], col);
@@ -1505,6 +1604,7 @@
 					VecMulf(mesh->col[a], 1.0f/count[a]);
 
 			MEM_freeN(count);
+			MEM_freeN(facecol);
 		}
 	}
 }





More information about the Bf-blender-cvs mailing list