Revision: 52533
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=52533
Author:   blendix
Date:     2012-11-24 14:50:21 +0000 (Sat, 24 Nov 2012)
Log Message:
-----------
Fix #33152: cycles SVM crash with certain shader nodes setups where closures 
would
appear multiple times after flattening the mix/add shader part of the graph 
into a
tree structure.

Modified Paths:
--------------
    trunk/blender/intern/cycles/render/svm.cpp
    trunk/blender/intern/cycles/render/svm.h

Modified: trunk/blender/intern/cycles/render/svm.cpp
===================================================================
--- trunk/blender/intern/cycles/render/svm.cpp  2012-11-24 14:19:21 UTC (rev 
52532)
+++ trunk/blender/intern/cycles/render/svm.cpp  2012-11-24 14:50:21 UTC (rev 
52533)
@@ -487,8 +487,40 @@
        }
 }
 
-void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& 
done, uint in_offset)
+void SVMCompiler::count_closure_users(ShaderNode *node, map<ShaderNode*, 
MultiClosureData>& closure_data)
 {
+       /* here we count the number of times each closure node is used, so that
+        * the last time we encounter it we can run the actually code with the
+        * weights from all other places added together */
+
+       if(node->name == ustring("mix_closure") || node->name == 
ustring("add_closure")) {
+               ShaderInput *cl1in = node->input("Closure1");
+               ShaderInput *cl2in = node->input("Closure2");
+
+               if(cl1in->link)
+                       count_closure_users(cl1in->link->parent, closure_data);
+               if(cl2in->link)
+                       count_closure_users(cl2in->link->parent, closure_data);
+       }
+       else {
+               MultiClosureData data;
+
+               if(closure_data.find(node) == closure_data.end()) {
+                       data.stack_offset = SVM_STACK_INVALID;
+                       data.users = 1;
+               }
+               else {
+                       data = closure_data[node];
+                       data.users++;
+               }
+
+               closure_data[node] = data;
+       }
+}
+
+void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& 
done,
+       map<ShaderNode*, MultiClosureData>& closure_data, uint in_offset)
+{
        /* todo: the weaks point here is that unlike the single closure 
sampling 
         * we will evaluate all nodes even if they are used as input for 
closures
         * that are unused. it's not clear what would be the best way to skip 
such
@@ -524,21 +556,37 @@
                        out2_offset = in_offset;
                }
 
-               if(cl1in->link) {
-                       generate_multi_closure(cl1in->link->parent, done, 
out1_offset);
+               if(cl1in->link)
+                       generate_multi_closure(cl1in->link->parent, done, 
closure_data, out1_offset);
 
-                       if(fin)
-                               stack_clear_offset(SHADER_SOCKET_FLOAT, 
out1_offset);
+               if(cl2in->link)
+                       generate_multi_closure(cl2in->link->parent, done, 
closure_data, out2_offset);
+
+               if(in_offset != SVM_STACK_INVALID)
+                       stack_clear_offset(SHADER_SOCKET_FLOAT, in_offset);
+       }
+       else {
+               MultiClosureData data = closure_data[node];
+
+               if(data.stack_offset == SVM_STACK_INVALID) {
+                       /* first time using closure, use stack position for 
weight */
+                       data.stack_offset = in_offset;
                }
+               else {
+                       /* not first time using, add weights together */
+                       add_node(NODE_MATH, NODE_MATH_ADD, data.stack_offset, 
in_offset);
+                       add_node(NODE_MATH, data.stack_offset);
 
-               if(cl2in->link) {
-                       generate_multi_closure(cl2in->link->parent, done, 
out2_offset);
+                       stack_clear_offset(SHADER_SOCKET_FLOAT, in_offset);
+               }
 
-                       if(fin)
-                               stack_clear_offset(SHADER_SOCKET_FLOAT, 
out2_offset);
-               }
-       }
-       else {
+               data.users--;
+               closure_data[node] = data;
+
+               /* still users coming? skip generating closure code */
+               if(data.users > 0)
+                       return;
+
                /* execute dependencies for closure */
                foreach(ShaderInput *in, node->inputs) {
                        if(!node_skip_input(node, in) && in->link) {
@@ -548,7 +596,7 @@
                        }
                }
 
-               mix_weight_offset = in_offset;
+               mix_weight_offset = data.stack_offset;
 
                /* compile closure itself */
                node->compile(*this);
@@ -563,6 +611,9 @@
                        current_shader->has_surface_transparent = true;
 
                /* end node is added outside of this */
+
+               if(data.stack_offset != SVM_STACK_INVALID)
+                       stack_clear_offset(SHADER_SOCKET_FLOAT, 
data.stack_offset);
        }
 }
 
@@ -634,8 +685,12 @@
                        if(generate) {
                                set<ShaderNode*> done;
 
-                               if(use_multi_closure)
-                                       
generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID);
+                               if(use_multi_closure) {
+                                       map<ShaderNode*, MultiClosureData> 
closure_data;
+
+                                       count_closure_users(clin->link->parent, 
closure_data);
+                                       
generate_multi_closure(clin->link->parent, done, closure_data, 
SVM_STACK_INVALID);
+                               }
                                else
                                        generate_closure(clin->link->parent, 
done);
                        }

Modified: trunk/blender/intern/cycles/render/svm.h
===================================================================
--- trunk/blender/intern/cycles/render/svm.h    2012-11-24 14:19:21 UTC (rev 
52532)
+++ trunk/blender/intern/cycles/render/svm.h    2012-11-24 14:50:21 UTC (rev 
52533)
@@ -81,6 +81,7 @@
        bool background;
 
 protected:
+       /* stack */
        struct Stack {
                Stack() { memset(users, 0, sizeof(users)); }
                Stack(const Stack& other) { memcpy(users, other.users, 
sizeof(users)); }
@@ -123,11 +124,22 @@
 
        bool node_skip_input(ShaderNode *node, ShaderInput *input);
 
+       /* single closure */
        void find_dependencies(set<ShaderNode*>& dependencies, const 
set<ShaderNode*>& done, ShaderInput *input);
        void generate_svm_nodes(const set<ShaderNode*>& nodes, 
set<ShaderNode*>& done);
        void generate_closure(ShaderNode *node, set<ShaderNode*>& done);
-       void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, 
uint in_offset);
 
+       /* multi closure */
+       struct MultiClosureData {
+               int stack_offset;
+               int users;
+       };
+
+       void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done,
+               map<ShaderNode*,MultiClosureData>& closure_data, uint 
in_offset);
+       void count_closure_users(ShaderNode *node, map<ShaderNode*, 
MultiClosureData>& closure_data);
+
+       /* compile */
        void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
 
        vector<int4> svm_nodes;

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to