forked from bartvdbraak/blender
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:
parent
e54bfda0f3
commit
f05b6bb7c1
@ -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,57 +490,64 @@ 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));
|
||||
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));
|
||||
res[0]= pa->res[0];
|
||||
res[1]= pa->res[1];
|
||||
res[2]= pa->res[2];
|
||||
|
||||
for (x=pa->minx; x < pa->maxx; x++) {
|
||||
co[0] = pa->bbmin[0] + (pa->voxel[0] * (x + 0.5f));
|
||||
for (z= pa->minz; z < pa->maxz; z++) {
|
||||
co[2] = pa->bbmin[2] + (pa->voxel[2] * (z + 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);
|
||||
for (x=pa->minx; x < pa->maxx; x++) {
|
||||
co[0] = pa->bbmin[0] + (pa->voxel[0] * (x + 0.5f));
|
||||
|
||||
i= V_I(x, y, z, res);
|
||||
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);
|
||||
|
||||
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];
|
||||
|
||||
// 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);
|
||||
|
||||
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];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pa->done = 1;
|
||||
BLI_thread_queue_push(queue->done, pa);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -603,9 +615,6 @@ static void precache_init_parts(Render *re, RayObject *tree, ShadeInput *shi, Ob
|
||||
maxz = minz + sizez;
|
||||
maxz = (maxz>res[2])?res[2]:maxz;
|
||||
|
||||
pa->done = 0;
|
||||
pa->working = 0;
|
||||
|
||||
pa->re = re;
|
||||
pa->num = i;
|
||||
pa->tree = tree;
|
||||
@ -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();
|
||||
|
||||
@ -719,32 +714,27 @@ 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);
|
||||
|
||||
while(caching) {
|
||||
for(thread= 0; thread<totthread; thread++)
|
||||
BLI_insert_thread(&threads, &queue);
|
||||
|
||||
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);
|
||||
/* loop waiting for work to be done */
|
||||
while(counter < totparts) {
|
||||
if(re->test_break && re->test_break(re->tbh))
|
||||
break;
|
||||
|
||||
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;
|
||||
if(BLI_thread_queue_pop_timeout(queue.done, 50))
|
||||
counter++;
|
||||
|
||||
time= PIL_check_seconds_timer();
|
||||
if(time-lasttime>1.0) {
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user