Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2011-09-28 23:18:29 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2011-09-28 23:18:29 +0400
commitf05b6bb7c1c9f5f4bd6199d6f40b56fe5729d4dd (patch)
tree02e8839ce9cb8f9ded93958310a40227cda4f0f6 /source/blender/render
parente54bfda0f3caff9de44fb13416cf6e192e262425 (diff)
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.
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/intern/include/render_types.h1
-rw-r--r--source/blender/render/intern/source/volume_precache.c178
2 files changed, 90 insertions, 89 deletions
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 0b339d285ce..6d27c7707f0 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -485,7 +485,6 @@ typedef struct VolPrecachePart
int res[3];
float bbmin[3];
float voxel[3];
- int working, done;
struct Render *re;
} VolPrecachePart;
diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c
index 18132c4a7f3..d6cfcee4ac9 100644
--- a/source/blender/render/intern/source/volume_precache.c
+++ b/source/blender/render/intern/source/volume_precache.c
@@ -477,6 +477,11 @@ static void *vol_precache_part_test(void *data)
}
#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_test(void *data)
*/
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];
-
- 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 (y= pa->miny; y < pa->maxy; y++) {
- co[1] = pa->bbmin[1] + (pa->voxel[1] * (y + 0.5f));
+ VolPrecacheQueue *queue = (VolPrecacheQueue*)data;
+ VolPrecachePart *pa;
+
+ 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];
+
+ 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));
-
- if (pa->re->test_break && pa->re->test_break(pa->re->tbh))
- break;
+ for (y= pa->miny; y < pa->maxy; y++) {
+ co[1] = pa->bbmin[1] + (pa->voxel[1] * (y + 0.5f));
- /* convert from world->camera space for shading */
- mul_v3_m4v3(cco, pa->viewmat, co);
-
- i= V_I(x, y, z, res);
+ 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);
- // 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 @@ static void precache_init_parts(Render *re, RayObject *tree, ShadeInput *shi, Ob
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 void precache_init_parts(Render *re, RayObject *tree, ShadeInput *shi, Ob
}
}
-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 int precache_resolution(Render *re, VolumePrecache *vp, ObjectInstanceRen
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 @@ static void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *o
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 @@ static void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *o
}
}
+ /* 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 @@ void volume_precache(Render *re)
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;
}
}