Fix for multiple parallel group node executions.
authorLukas Toenne <lukas.toenne@googlemail.com>
Tue, 6 Sep 2011 16:32:51 +0000 (16:32 +0000)
committerLukas Toenne <lukas.toenne@googlemail.com>
Tue, 6 Sep 2011 16:32:51 +0000 (16:32 +0000)
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.

13 files changed:
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/texture.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/nodes/composite/node_composite_tree.c
source/blender/nodes/composite/nodes/node_composite_common.c
source/blender/nodes/shader/node_shader_tree.c
source/blender/nodes/shader/nodes/node_shader_common.c
source/blender/nodes/texture/node_texture_tree.c
source/blender/nodes/texture/nodes/node_texture_common.c
source/blender/render/intern/source/render_texture.c

index 7207fb7d0fbca3b94583ab256cbefbecc823f9ab..1de3c295f4da30af5b3640a50f245890960a40a5 100644 (file)
@@ -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);
 
 
index 36631d5af90c9c78d58a14db215e93d5eb86175c..aab8e1abbeaa86908a6de0bdefc093f213a66cf0 100644 (file)
@@ -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);
        }
 }
 
index 481893b86a8e5b69de669aa4746591c5335c65f6..cd1a6e6115109fcaec5c9b955a9491d56822cf73 100644 (file)
@@ -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;
                }
        }
index 6119a8553667e71752964081eefd9142c9c70b7b..38165182d83beb13d09870f975373a2077d96483 100644 (file)
@@ -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); 
        }
index 9539706468f4282bf76cf05a0a31864ac58413f8..79a3251cdf1c052453d5a907325fbc1e80d3240b 100644 (file)
@@ -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);
        }       
 }
 
index bf34a3b8c9f4ad139474218be487ba00da63a8af..ced3dd00a9cfc9a4dd710b61a23f27de1f1dbad3 100644 (file)
@@ -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))
index 0ea62b0aa5f57cc7554118bbdf2f1546a8ab658d..4fc5e23e26a223592aefa4ec05044b93e1cbc4a4 100644 (file)
@@ -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);
 }
 
 /* *********************************************** */
index fbff8198ddeab100a856d66c9d7ad728cde3f54d..8067f7e92beeb71cc0842e1d6d73e941b13d8163 100644 (file)
@@ -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.
index 8cb1ebeb15f50fff4076ff2fffb230ae7da4561a..642e4be10d7db9cbba879d861a7c832afe605c55 100644 (file)
@@ -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);
index aa8e8241bf893b886ce537ae95e7d0b8d83bc656..2dd15ab1e99242145e8937984219f1be3a27e910 100644 (file)
@@ -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.
index 3ea15a316abb89f5df67354d19fe277e551521c7..603aa7ceb774b5df61b1f782b83d672fa507f957 100644 (file)
@@ -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);
index afb24226416ed1c4e9578976340a7067d82c667a..1b46b830909ff443da5356ffe2eccc8e005b0c3e 100644 (file)
@@ -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.
index e35b3e53f5baa7340dd355fc59cdd06cdc48eaa8..cf1fae81eb564a5c5ce8989051178b15370d7443 100644 (file)
@@ -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)