Fix for multiple parallel group node executions.

This would previously break because begin/end functions for each tree type still have some checks of the ntree->execdata pointer in them, despite the intended use of execdata instances instead of trees themselves for execution data storage. This is an artifact of the old execution system that required these checks to be made in the functions to avoid multiple execution of top-level trees. Now these functions take an additional argument, so group nodes can prevent them from setting and checking the nodetree->execdata pointers.
This commit is contained in:
Lukas Toenne 2011-09-06 16:32:51 +00:00
parent e79d16270b
commit 884fc84793
13 changed files with 110 additions and 71 deletions

@ -466,8 +466,8 @@ struct ShadeResult;
/* API */
struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree);
void ntreeShaderEndExecTree(struct bNodeTreeExec *exec);
struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
void ntreeShaderEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
void ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr);
void ntreeShaderGetTexcoMode(struct bNodeTree *ntree, int osa, short *texco, int *mode);
void nodeShaderSynchronizeID(struct bNode *node, int copyto);
@ -594,8 +594,8 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat);
/* API */
struct CompBuf;
struct bNodeTreeExec *ntreeCompositBeginExecTree(struct bNodeTree *ntree);
void ntreeCompositEndExecTree(struct bNodeTreeExec *exec);
struct bNodeTreeExec *ntreeCompositBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
void ntreeCompositEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
void ntreeCompositExecTree(struct bNodeTree *ntree, struct RenderData *rd, int do_previews);
void ntreeCompositTagRender(struct Scene *sce);
int ntreeCompositTagAnimated(struct bNodeTree *ntree);
@ -642,8 +642,8 @@ void ntreeTexSetPreviewFlag(int);
void ntreeTexCheckCyclics(struct bNodeTree *ntree);
char* ntreeTexOutputMenu(struct bNodeTree *ntree);
struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree);
void ntreeTexEndExecTree(struct bNodeTreeExec *exec);
struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
void ntreeTexEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target, float *coord, float *dxt, float *dyt, int osatex, short thread, struct Tex *tex, short which_output, int cfra, int preview, struct ShadeInput *shi, struct MTex *mtex);

@ -926,7 +926,7 @@ void init_render_material(Material *mat, int r_mode, float *amb)
init_render_nodetree(mat->nodetree, mat, r_mode, amb);
if (!mat->nodetree->execdata)
mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree);
mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree, 1);
}
}
@ -960,7 +960,7 @@ void end_render_material(Material *mat)
{
if(mat && mat->nodetree && mat->use_nodes) {
if (mat->nodetree->execdata)
ntreeShaderEndExecTree(mat->nodetree->execdata);
ntreeShaderEndExecTree(mat->nodetree->execdata, 1);
}
}

@ -897,13 +897,13 @@ void ntreeFreeTree(bNodeTree *ntree)
if (ntree->execdata) {
switch (ntree->type) {
case NTREE_COMPOSIT:
ntreeCompositEndExecTree(ntree->execdata);
ntreeCompositEndExecTree(ntree->execdata, 1);
break;
case NTREE_SHADER:
ntreeShaderEndExecTree(ntree->execdata);
ntreeShaderEndExecTree(ntree->execdata, 1);
break;
case NTREE_TEXTURE:
ntreeTexEndExecTree(ntree->execdata);
ntreeTexEndExecTree(ntree->execdata, 1);
break;
}
}

@ -767,7 +767,7 @@ Tex *copy_texture(Tex *tex)
if(tex->nodetree) {
if (tex->nodetree->execdata) {
ntreeTexEndExecTree(tex->nodetree->execdata);
ntreeTexEndExecTree(tex->nodetree->execdata, 1);
}
texn->nodetree= ntreeCopyTree(tex->nodetree);
}

@ -4664,7 +4664,7 @@ static void paint_brush_init_tex(Brush *brush)
if(brush) {
MTex *mtex= &brush->mtex;
if(mtex->tex && mtex->tex->nodetree)
ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */
ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
}
}
@ -4806,7 +4806,7 @@ static void paint_brush_exit_tex(Brush *brush)
if(brush) {
MTex *mtex= &brush->mtex;
if(mtex->tex && mtex->tex->nodetree)
ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
}
}

@ -3274,7 +3274,7 @@ static void sculpt_brush_init_tex(Sculpt *sd, SculptSession *ss)
/* init mtex nodes */
if(mtex->tex && mtex->tex->nodetree)
ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */
ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
/* TODO: Shouldn't really have to do this at the start of every
stroke, but sculpt would need some sort of notification when
@ -3455,7 +3455,7 @@ static void sculpt_brush_exit_tex(Sculpt *sd)
MTex *mtex= &brush->mtex;
if(mtex->tex && mtex->tex->nodetree)
ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
}
static void sculpt_stroke_done(bContext *C, struct PaintStroke *UNUSED(stroke))

@ -200,17 +200,22 @@ bNodeTreeType ntreeType_Composite = {
};
struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree)
/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
* If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
*/
struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree, int use_tree_data)
{
bNodeTreeExec *exec;
bNode *node;
bNodeSocket *sock;
/* XXX hack: prevent exec data from being generated twice.
* this should be handled by the renderer!
*/
if (ntree->execdata)
return ntree->execdata;
if (use_tree_data) {
/* XXX hack: prevent exec data from being generated twice.
* this should be handled by the renderer!
*/
if (ntree->execdata)
return ntree->execdata;
}
/* ensures only a single output node is enabled */
ntreeSetOutput(ntree);
@ -236,15 +241,20 @@ struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree)
}
}
/* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
if (use_tree_data) {
/* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
* which only store the ntree pointer. Should be fixed at some point!
*/
ntree->execdata = exec;
ntree->execdata = exec;
}
return exec;
}
void ntreeCompositEndExecTree(bNodeTreeExec *exec)
/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
* If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
*/
void ntreeCompositEndExecTree(bNodeTreeExec *exec, int use_tree_data)
{
if(exec) {
bNodeTree *ntree= exec->nodetree;
@ -269,8 +279,10 @@ void ntreeCompositEndExecTree(bNodeTreeExec *exec)
ntree_exec_end(exec);
/* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
ntree->execdata = NULL;
if (use_tree_data) {
/* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
ntree->execdata = NULL;
}
}
}
@ -495,10 +507,10 @@ static void ntree_composite_texnode(bNodeTree *ntree, int init)
/* has internal flag to detect it only does it once */
if(init) {
if (!tex->nodetree->execdata)
tex->nodetree->execdata = ntreeTexBeginExecTree(tex->nodetree);
tex->nodetree->execdata = ntreeTexBeginExecTree(tex->nodetree, 1);
}
else
ntreeTexEndExecTree(tex->nodetree->execdata);
ntreeTexEndExecTree(tex->nodetree->execdata, 1);
tex->nodetree->execdata = NULL;
}
}
@ -521,8 +533,10 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
if(do_preview)
ntreeInitPreview(ntree, 0, 0);
if (!ntree->execdata)
exec = ntreeCompositBeginExecTree(ntree);
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 */
@ -592,7 +606,8 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
BLI_end_threads(&threads);
ntreeCompositEndExecTree(exec);
/* XXX top-level tree uses the ntree->execdata pointer */
ntreeCompositEndExecTree(exec, 1);
}
/* *********************************************** */

@ -122,7 +122,7 @@ static void *group_initexec(bNode *node)
bNodeStack *ns;
/* initialize the internal node tree execution */
exec = ntreeCompositBeginExecTree(ngroup);
exec = ntreeCompositBeginExecTree(ngroup, 0);
/* tag group outputs as external to prevent freeing */
for (sock=ngroup->outputs.first; sock; sock=sock->next) {
@ -135,11 +135,11 @@ static void *group_initexec(bNode *node)
return exec;
}
static void group_freeexec(bNode *UNUSED(node), void *nodedata)
static void group_freeexec(bNode *node, void *nodedata)
{
bNodeTreeExec *gexec= (bNodeTreeExec*)nodedata;
ntreeCompositEndExecTree(gexec);
ntreeCompositEndExecTree(gexec, 0);
}
/* Copy inputs to the internal stack.

@ -108,11 +108,11 @@ void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat)
bNodeTreeExec *exec;
if(!ntree->execdata)
exec = ntreeShaderBeginExecTree(ntree);
exec = ntreeShaderBeginExecTree(ntree, 1);
ntreeExecGPUNodes(exec, mat, 1);
ntreeShaderEndExecTree(exec);
ntreeShaderEndExecTree(exec, 1);
}
/* **************** call to switch lamploop for material node ************ */
@ -125,16 +125,21 @@ void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult
}
bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree)
/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
* If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
*/
bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree, int use_tree_data)
{
bNodeTreeExec *exec;
bNode *node;
/* XXX hack: prevent exec data from being generated twice.
* this should be handled by the renderer!
*/
if (ntree->execdata)
return ntree->execdata;
if (use_tree_data) {
/* XXX hack: prevent exec data from being generated twice.
* this should be handled by the renderer!
*/
if (ntree->execdata)
return ntree->execdata;
}
/* ensures only a single output node is enabled */
ntreeSetOutput(ntree);
@ -148,15 +153,20 @@ bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree)
for(node= exec->nodetree->nodes.first; node; node= node->next)
node->need_exec= 1;
/* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
* which only store the ntree pointer. Should be fixed at some point!
*/
ntree->execdata = exec;
if (use_tree_data) {
/* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
* which only store the ntree pointer. Should be fixed at some point!
*/
ntree->execdata = exec;
}
return exec;
}
void ntreeShaderEndExecTree(bNodeTreeExec *exec)
/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
* If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
*/
void ntreeShaderEndExecTree(bNodeTreeExec *exec, int use_tree_data)
{
if(exec) {
bNodeTree *ntree= exec->nodetree;
@ -176,8 +186,10 @@ void ntreeShaderEndExecTree(bNodeTreeExec *exec)
ntree_exec_end(exec);
/* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
ntree->execdata = NULL;
if (use_tree_data) {
/* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
ntree->execdata = NULL;
}
}
}
@ -199,7 +211,7 @@ void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
memset(shr, 0, sizeof(ShadeResult));
if (!exec)
exec = ntree->execdata = ntreeShaderBeginExecTree(exec->nodetree);
exec = ntree->execdata = ntreeShaderBeginExecTree(exec->nodetree, 1);
nts= ntreeGetThreadStack(exec, shi->thread);
ntreeExecThreadNodes(exec, nts, &scd, shi->thread);

@ -76,7 +76,7 @@ static void *group_initexec(bNode *node)
bNodeTreeExec *exec;
/* initialize the internal node tree execution */
exec = ntreeShaderBeginExecTree(ngroup);
exec = ntreeShaderBeginExecTree(ngroup, 0);
return exec;
}
@ -85,7 +85,7 @@ static void group_freeexec(bNode *UNUSED(node), void *nodedata)
{
bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata;
ntreeShaderEndExecTree(gexec);
ntreeShaderEndExecTree(gexec, 0);
}
/* Copy inputs to the internal stack.

@ -121,16 +121,21 @@ int ntreeTexTagAnimated(bNodeTree *ntree)
return 0;
}
bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree)
/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
* If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
*/
bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree, int use_tree_data)
{
bNodeTreeExec *exec;
bNode *node;
/* XXX hack: prevent exec data from being generated twice.
* this should be handled by the renderer!
*/
if (ntree->execdata)
return ntree->execdata;
if (use_tree_data) {
/* XXX hack: prevent exec data from being generated twice.
* this should be handled by the renderer!
*/
if (ntree->execdata)
return ntree->execdata;
}
/* common base initialization */
exec = ntree_exec_begin(ntree);
@ -141,10 +146,12 @@ bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree)
for(node= exec->nodetree->nodes.first; node; node= node->next)
node->need_exec= 1;
/* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
* which only store the ntree pointer. Should be fixed at some point!
*/
ntree->execdata = exec;
if (use_tree_data) {
/* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
* which only store the ntree pointer. Should be fixed at some point!
*/
ntree->execdata = exec;
}
return exec;
}
@ -163,7 +170,10 @@ static void tex_free_delegates(bNodeTreeExec *exec)
MEM_freeN(ns->data);
}
void ntreeTexEndExecTree(bNodeTreeExec *exec)
/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
* If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
*/
void ntreeTexEndExecTree(bNodeTreeExec *exec, int use_tree_data)
{
if(exec) {
bNodeTree *ntree= exec->nodetree;
@ -185,8 +195,10 @@ void ntreeTexEndExecTree(bNodeTreeExec *exec)
ntree_exec_end(exec);
/* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
ntree->execdata = NULL;
if (use_tree_data) {
/* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
ntree->execdata = NULL;
}
}
}
@ -223,7 +235,7 @@ int ntreeTexExecTree(
data.shi= shi;
if (!exec)
exec = ntreeTexBeginExecTree(nodes);
exec = ntreeTexBeginExecTree(nodes, 1);
nts= ntreeGetThreadStack(exec, thread);
ntreeExecThreadNodes(exec, nts, &data, thread);

@ -61,7 +61,7 @@ static void *group_initexec(bNode *node)
void *exec;
/* initialize the internal node tree execution */
exec = ntreeTexBeginExecTree(ngroup);
exec = ntreeTexBeginExecTree(ngroup, 0);
return exec;
}
@ -70,7 +70,7 @@ static void group_freeexec(bNode *UNUSED(node), void *nodedata)
{
bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata;
ntreeTexEndExecTree(gexec);
ntreeTexEndExecTree(gexec, 0);
}
/* Copy inputs to the internal stack.

@ -125,7 +125,7 @@ static void init_render_texture(Render *re, Tex *tex)
}
if(tex->nodetree && tex->use_nodes) {
ntreeTexBeginExecTree(tex->nodetree); /* has internal flag to detect it only does it once */
ntreeTexBeginExecTree(tex->nodetree, 1); /* has internal flag to detect it only does it once */
}
}
@ -145,7 +145,7 @@ void init_render_textures(Render *re)
static void end_render_texture(Tex *tex)
{
if(tex && tex->use_nodes && tex->nodetree && tex->nodetree->execdata)
ntreeTexEndExecTree(tex->nodetree->execdata);
ntreeTexEndExecTree(tex->nodetree->execdata, 1);
}
void end_render_textures(Render *re)