void BLI_insert_work(ThreadedWorker *worker, void *param) { WorkParam *p = MEM_callocN(sizeof(WorkParam), "workparam"); int index; if (BLI_available_threads(&worker->threadbase) == 0) { index = worker->total; while(index == worker->total) { PIL_sleep_ms(worker->sleep_time); for (index = 0; index < worker->total; index++) { if (worker->busy[index] == 0) { BLI_remove_thread_index(&worker->threadbase, index); break; } } } } else { index = BLI_available_thread_index(&worker->threadbase); } worker->busy[index] = 1; p->param = param; p->index = index; p->worker = worker; BLI_insert_thread(&worker->threadbase, p); }
/* optimized tree execute test for compositing */ static void ntreeCompositExecTreeOld(bNodeTree *ntree, RenderData *rd, int do_preview) { bNodeExec *nodeexec; bNode *node; ListBase threads; ThreadData thdata; int totnode, curnode, rendering = TRUE, n; bNodeTreeExec *exec = ntree->execdata; if (do_preview) ntreeInitPreview(ntree, 0, 0); if (!ntree->execdata) { /* XXX this is the top-level tree, so we use the ntree->execdata pointer. */ exec = ntreeCompositBeginExecTree(ntree, 1); } ntree_composite_texnode(ntree, 1); /* prevent unlucky accidents */ if (G.background) rd->scemode &= ~R_COMP_CROP; /* setup callerdata for thread callback */ thdata.rd= rd; thdata.stack= exec->stack; /* fixed seed, for example noise texture */ BLI_srandom(rd->cfra); /* sets need_exec tags in nodes */ curnode = totnode= setExecutableNodes(exec, &thdata); BLI_init_threads(&threads, exec_composite_node, rd->threads); while (rendering) { if (BLI_available_threads(&threads)) { nodeexec= getExecutableNode(exec); if (nodeexec) { node = nodeexec->node; if (ntree->progress && totnode) ntree->progress(ntree->prh, (1.0f - curnode/(float)totnode)); if (ntree->stats_draw) { char str[128]; BLI_snprintf(str, sizeof(str), "Compositing %d %s", curnode, node->name); ntree->stats_draw(ntree->sdh, str); } curnode--; node->threaddata = &thdata; node->exec= NODE_PROCESSING; BLI_insert_thread(&threads, nodeexec); } else PIL_sleep_ms(50); } else PIL_sleep_ms(50); rendering= 0; /* test for ESC */ if (ntree->test_break && ntree->test_break(ntree->tbh)) { for (node= ntree->nodes.first; node; node= node->next) node->exec |= NODE_READY; } /* check for ready ones, and if we need to continue */ for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { node = nodeexec->node; if (node->exec & NODE_READY) { if ((node->exec & NODE_FINISHED)==0) { BLI_remove_thread(&threads, nodeexec); /* this waits for running thread to finish btw */ node->exec |= NODE_FINISHED; /* freeing unused buffers */ if (rd->scemode & R_COMP_FREE) freeExecutableNode(exec); } } else rendering= 1; } } BLI_end_threads(&threads); /* XXX top-level tree uses the ntree->execdata pointer */ ntreeCompositEndExecTree(exec, 1); }
/* Precache a volume into a 3D voxel grid. * The voxel grid is stored in the ObjectInstanceRen, * in camera space, aligned with the ObjectRen's bounding box. * Resolution is defined by the user. */ void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Material *ma) { VolumePrecache *vp; VolPrecachePart *nextpa, *pa; RayObject *tree; ShadeInput shi; ListBase threads; float *bbmin=obi->obr->boundbox[0], *bbmax=obi->obr->boundbox[1]; int parts[3] = {1, 1, 1}, totparts; int caching=1, counter=0; int totthread = re->r.threads; double time, lasttime= PIL_check_seconds_timer(); R = *re; /* create a raytree with just the faces of the instanced ObjectRen, * used for checking if the cached point is inside or outside. */ //tree = create_raytree_obi(obi, bbmin, bbmax); tree = makeraytree_object(&R, obi); if (!tree) return; INIT_MINMAX(bbmin, bbmax); RE_rayobject_merge_bb( tree, bbmin, bbmax); vp = MEM_callocN(sizeof(VolumePrecache), "volume light cache"); if (!precache_resolution(vp, bbmin, bbmax, ma->vol.precache_resolution)) { MEM_freeN(vp); vp = NULL; return; } vp->data_r = MEM_callocN(sizeof(float)*vp->res[0]*vp->res[1]*vp->res[2], "volume light cache data red channel"); vp->data_g = MEM_callocN(sizeof(float)*vp->res[0]*vp->res[1]*vp->res[2], "volume light cache data green channel"); vp->data_b = MEM_callocN(sizeof(float)*vp->res[0]*vp->res[1]*vp->res[2], "volume light cache data blue channel"); obi->volume_precache = vp; /* Need a shadeinput to calculate scattering */ precache_setup_shadeinput(re, obi, ma, &shi); precache_init_parts(re, tree, &shi, obi, totthread, parts); totparts = parts[0] * parts[1] * parts[2]; BLI_init_threads(&threads, vol_precache_part, totthread); while(caching) { 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); 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.0f) { char str[64]; sprintf(str, "Precaching volume: %d%%", (int)(100.0f * ((float)counter / (float)totparts))); re->i.infostr= str; re->stats_draw(re->sdh, &re->i); re->i.infostr= NULL; lasttime= time; } } BLI_end_threads(&threads); BLI_freelistN(&re->volume_precache_parts); if(tree) { //TODO: makeraytree_object creates a tree and saves it on OBI, if we free this tree we should also clear other pointers to it //RE_rayobject_free(tree); //tree= NULL; } lightcache_filter(obi->volume_precache); if (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) { multiple_scattering_diffusion(re, vp, ma); } }