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.
This commit is contained in:
Brecht Van Lommel 2011-09-28 19:18:29 +00:00
parent e54bfda0f3
commit f05b6bb7c1
2 changed files with 88 additions and 87 deletions

@ -485,7 +485,6 @@ typedef struct VolPrecachePart
int res[3];
float bbmin[3];
float voxel[3];
int working, done;
struct Render *re;
} VolPrecachePart;

@ -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];
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 @@ 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;
}
}