[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [40675] trunk/blender/source/blender/ render/intern: Fix #28728: volume precaching took a long time with many objects, changed

Brecht Van Lommel brechtvanlommel at pandora.be
Wed Sep 28 21:18:30 CEST 2011


Revision: 40675
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=40675
Author:   blendix
Date:     2011-09-28 19:18:29 +0000 (Wed, 28 Sep 2011)
Log Message:
-----------
Fix #28728: volume precaching took a long time with many objects, changed
threading to no longer sleep 50ms for each object, using work queue now.

Also it was showing SSS preprocessing while actually doing Volume precaching,
fixed as well.

Modified Paths:
--------------
    trunk/blender/source/blender/render/intern/include/render_types.h
    trunk/blender/source/blender/render/intern/source/volume_precache.c

Modified: trunk/blender/source/blender/render/intern/include/render_types.h
===================================================================
--- trunk/blender/source/blender/render/intern/include/render_types.h	2011-09-28 19:11:59 UTC (rev 40674)
+++ trunk/blender/source/blender/render/intern/include/render_types.h	2011-09-28 19:18:29 UTC (rev 40675)
@@ -485,7 +485,6 @@
 	int res[3];
 	float bbmin[3];
 	float voxel[3];
-	int working, done;
 	struct Render *re;
 } VolPrecachePart;
 

Modified: trunk/blender/source/blender/render/intern/source/volume_precache.c
===================================================================
--- trunk/blender/source/blender/render/intern/source/volume_precache.c	2011-09-28 19:11:59 UTC (rev 40674)
+++ trunk/blender/source/blender/render/intern/source/volume_precache.c	2011-09-28 19:18:29 UTC (rev 40675)
@@ -477,6 +477,11 @@
 }
 #endif
 
+typedef struct VolPrecacheQueue {
+	ThreadQueue *work;
+	ThreadQueue *done;
+} VolPrecacheQueue;
+
 /* Iterate over the 3d voxel grid, and fill the voxels with scattering information
  *
  * It's stored in memory as 3 big float grids next to each other, one for each RGB channel.
@@ -485,58 +490,65 @@
  */
 static void *vol_precache_part(void *data)
 {
-	VolPrecachePart *pa =  (VolPrecachePart *)data;
-	ObjectInstanceRen *obi = pa->obi;
-	RayObject *tree = pa->tree;
-	ShadeInput *shi = pa->shi;
-	float scatter_col[3] = {0.f, 0.f, 0.f};
-	float co[3], cco[3], view[3];
-	int x, y, z, i;
-	int res[3];
+	VolPrecacheQueue *queue = (VolPrecacheQueue*)data;
+	VolPrecachePart *pa;
 
-	res[0]= pa->res[0];
-	res[1]= pa->res[1];
-	res[2]= pa->res[2];
+	while ((pa = BLI_thread_queue_pop(queue->work))) {
+		ObjectInstanceRen *obi = pa->obi;
+		RayObject *tree = pa->tree;
+		ShadeInput *shi = pa->shi;
+		float scatter_col[3] = {0.f, 0.f, 0.f};
+		float co[3], cco[3], view[3];
+		int x, y, z, i;
+		int res[3];
 
-	for (z= pa->minz; z < pa->maxz; z++) {
-		co[2] = pa->bbmin[2] + (pa->voxel[2] * (z + 0.5f));
-		
-		for (y= pa->miny; y < pa->maxy; y++) {
-			co[1] = pa->bbmin[1] + (pa->voxel[1] * (y + 0.5f));
+		if (pa->re->test_break && pa->re->test_break(pa->re->tbh))
+			break;
+
+		res[0]= pa->res[0];
+		res[1]= pa->res[1];
+		res[2]= pa->res[2];
+
+		for (z= pa->minz; z < pa->maxz; z++) {
+			co[2] = pa->bbmin[2] + (pa->voxel[2] * (z + 0.5f));
 			
-			for (x=pa->minx; x < pa->maxx; x++) {
-				co[0] = pa->bbmin[0] + (pa->voxel[0] * (x + 0.5f));
+			for (y= pa->miny; y < pa->maxy; y++) {
+				co[1] = pa->bbmin[1] + (pa->voxel[1] * (y + 0.5f));
 				
-				if (pa->re->test_break && pa->re->test_break(pa->re->tbh))
-					break;
+				for (x=pa->minx; x < pa->maxx; x++) {
+					co[0] = pa->bbmin[0] + (pa->voxel[0] * (x + 0.5f));
+					
+					if (pa->re->test_break && pa->re->test_break(pa->re->tbh))
+						break;
+					
+					/* convert from world->camera space for shading */
+					mul_v3_m4v3(cco, pa->viewmat, co);
+					
+					i= V_I(x, y, z, res);
+					
+					// don't bother if the point is not inside the volume mesh
+					if (!point_inside_obi(tree, obi, cco)) {
+						obi->volume_precache->data_r[i] = -1.0f;
+						obi->volume_precache->data_g[i] = -1.0f;
+						obi->volume_precache->data_b[i] = -1.0f;
+						continue;
+					}
+					
+					copy_v3_v3(view, cco);
+					normalize_v3(view);
+					vol_get_scattering(shi, scatter_col, cco, view);
 				
-				/* convert from world->camera space for shading */
-				mul_v3_m4v3(cco, pa->viewmat, co);
-				
-				i= V_I(x, y, z, res);
-				
-				// don't bother if the point is not inside the volume mesh
-				if (!point_inside_obi(tree, obi, cco)) {
-					obi->volume_precache->data_r[i] = -1.0f;
-					obi->volume_precache->data_g[i] = -1.0f;
-					obi->volume_precache->data_b[i] = -1.0f;
-					continue;
+					obi->volume_precache->data_r[i] = scatter_col[0];
+					obi->volume_precache->data_g[i] = scatter_col[1];
+					obi->volume_precache->data_b[i] = scatter_col[2];
+					
 				}
-				
-				copy_v3_v3(view, cco);
-				normalize_v3(view);
-				vol_get_scattering(shi, scatter_col, cco, view);
-			
-				obi->volume_precache->data_r[i] = scatter_col[0];
-				obi->volume_precache->data_g[i] = scatter_col[1];
-				obi->volume_precache->data_b[i] = scatter_col[2];
-				
 			}
 		}
+
+		BLI_thread_queue_push(queue->done, pa);
 	}
 	
-	pa->done = 1;
-	
 	return NULL;
 }
 
@@ -602,9 +614,6 @@
 				minz = z * sizez;
 				maxz = minz + sizez;
 				maxz = (maxz>res[2])?res[2]:maxz;
-						
-				pa->done = 0;
-				pa->working = 0;
 				
 				pa->re = re;
 				pa->num = i;
@@ -630,21 +639,6 @@
 	}
 }
 
-static VolPrecachePart *precache_get_new_part(Render *re)
-{
-	VolPrecachePart *pa, *nextpa=NULL;
-	
-	for (pa = re->volume_precache_parts.first; pa; pa=pa->next)
-	{
-		if (pa->done==0 && pa->working==0) {
-			nextpa = pa;
-			break;
-		}
-	}
-
-	return nextpa;
-}
-
 /* calculate resolution from bounding box in world space */
 static int precache_resolution(Render *re, VolumePrecache *vp, ObjectInstanceRen *obi, int res)
 {
@@ -678,14 +672,15 @@
 static void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Material *ma)
 {
 	VolumePrecache *vp;
-	VolPrecachePart *nextpa, *pa;
+	VolPrecachePart *pa;
 	RayObject *tree;
 	ShadeInput shi;
 	ListBase threads;
+	VolPrecacheQueue queue;
 	int parts[3] = {1, 1, 1}, totparts;
 	
-	int caching=1, counter=0;
-	int totthread = re->r.threads;
+	int counter=0;
+	int totthread = re->r.threads, thread;
 	
 	double time, lasttime= PIL_check_seconds_timer();
 	
@@ -718,34 +713,29 @@
 	
 	precache_init_parts(re, tree, &shi, obi, totthread, parts);
 	totparts = parts[0] * parts[1] * parts[2];
+
+	/* setup work and done queues */
+	queue.work = BLI_thread_queue_init();
+	queue.done = BLI_thread_queue_init();
+	BLI_thread_queue_nowait(queue.work);
+
+	for(pa= re->volume_precache_parts.first; pa; pa= pa->next)
+		BLI_thread_queue_push(queue.work, pa);
 	
+	/* launch threads */
 	BLI_init_threads(&threads, vol_precache_part, totthread);
+
+	for(thread= 0; thread<totthread; thread++)
+		BLI_insert_thread(&threads, &queue);
 	
-	while(caching) {
+	/* loop waiting for work to be done */
+	while(counter < totparts) {
+		if(re->test_break && re->test_break(re->tbh))
+			break;
 
-		if(BLI_available_threads(&threads) && !(re->test_break(re->tbh))) {
-			nextpa = precache_get_new_part(re);
-			if (nextpa) {
-				nextpa->working = 1;
-				BLI_insert_thread(&threads, nextpa);
-			}
-		}
-		else PIL_sleep_ms(50);
+		if(BLI_thread_queue_pop_timeout(queue.done, 50))
+			counter++;
 
-		caching=0;
-		counter=0;
-		for(pa= re->volume_precache_parts.first; pa; pa= pa->next) {
-			
-			if(pa->done) {
-				counter++;
-				BLI_remove_thread(&threads, pa);
-			} else
-				caching = 1;
-		}
-		
-		if (re->test_break(re->tbh) && BLI_available_threads(&threads)==totthread)
-			caching=0;
-		
 		time= PIL_check_seconds_timer();
 		if(time-lasttime>1.0) {
 			char str[64];
@@ -757,7 +747,10 @@
 		}
 	}
 	
+	/* free */
 	BLI_end_threads(&threads);
+	BLI_thread_queue_free(queue.work);
+	BLI_thread_queue_free(queue.done);
 	BLI_freelistN(&re->volume_precache_parts);
 	
 	if(tree) {
@@ -788,13 +781,22 @@
 	ObjectInstanceRen *obi;
 	VolumeOb *vo;
 
+	re->i.infostr= "Volume preprocessing";
+	re->stats_draw(re->sdh, &re->i);
+
 	for(vo= re->volumes.first; vo; vo= vo->next) {
 		if (using_lightcache(vo->ma)) {
 			for(obi= re->instancetable.first; obi; obi= obi->next) {
 				if (obi->obr == vo->obr) {
 					vol_precache_objectinstance_threads(re, obi, vo->ma);
+
+					if(re->test_break && re->test_break(re->tbh))
+						break;
 				}
 			}
+
+			if(re->test_break && re->test_break(re->tbh))
+				break;
 		}
 	}
 	




More information about the Bf-blender-cvs mailing list