Commit: 71499421915f3c2a7f300510142e7894a0b00090
Author: Sergey Sharybin
Date:   Fri Jul 11 18:19:14 2014 +0600
https://developer.blender.org/rB71499421915f3c2a7f300510142e7894a0b00090

Fix T41023: Specific material cause bad render result, different on CPU/GPU

Issue was caused by too much aggressive optimization, which skipped execution
of some nodes leading to an uninitialized memory read in SVM stack.

===================================================================

M       intern/cycles/render/svm.cpp
M       intern/cycles/render/svm.h

===================================================================

diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 576c176..13c63d9 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -363,14 +363,17 @@ bool SVMCompiler::node_skip_input(ShaderNode *node, 
ShaderInput *input)
        return false;
 }
 
-void SVMCompiler::find_dependencies(set<ShaderNode*>& dependencies, const 
set<ShaderNode*>& done, ShaderInput *input)
+void SVMCompiler::find_dependencies(set<ShaderNode*>& dependencies,
+                                    const set<ShaderNode*>& done,
+                                    ShaderInput *input,
+                                    ShaderNode *skip_node)
 {
        ShaderNode *node = (input->link)? input->link->parent: NULL;
 
-       if(node && done.find(node) == done.end()) {
+       if(node && done.find(node) == done.end() && node != skip_node) {
                foreach(ShaderInput *in, node->inputs)
                        if(!node_skip_input(node, in))
-                               find_dependencies(dependencies, done, in);
+                               find_dependencies(dependencies, done, in, 
skip_node);
 
                dependencies.insert(node);
        }
@@ -459,20 +462,28 @@ void SVMCompiler::generate_closure_node(ShaderNode *node, 
set<ShaderNode*>& done
        }
 }
 
-void SVMCompiler::generated_shared_closure_nodes(ShaderNode *node, 
set<ShaderNode*>& done, set<ShaderNode*>& closure_done, const set<ShaderNode*>& 
shared)
+void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
+                                                 ShaderNode *node,
+                                                 set<ShaderNode*>& done,
+                                                 set<ShaderNode*>& 
closure_done,
+                                                 const set<ShaderNode*>& 
shared)
 {
        if(shared.find(node) != shared.end()) {
-               generate_multi_closure(node, done, closure_done);
+               generate_multi_closure(root_node, node, done, closure_done);
        }
        else {
                foreach(ShaderInput *in, node->inputs) {
                        if(in->type == SHADER_SOCKET_CLOSURE && in->link)
-                               
generated_shared_closure_nodes(in->link->parent, done, closure_done, shared);
+                               generated_shared_closure_nodes(root_node, 
in->link->parent,
+                                                              done, 
closure_done, shared);
                }
        }
 }
 
-void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& 
done, set<ShaderNode*>& closure_done)
+void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
+                                         ShaderNode *node,
+                                         set<ShaderNode*>& done,
+                                         set<ShaderNode*>& closure_done)
 {
        /* only generate once */
        if(closure_done.find(node) != closure_done.end())
@@ -509,12 +520,33 @@ void SVMCompiler::generate_multi_closure(ShaderNode 
*node, set<ShaderNode*>& don
                        set_intersection(cl1deps.begin(), cl1deps.end(),
                                         cl2deps.begin(), cl2deps.end(),
                                         std::inserter(shareddeps, 
shareddeps.begin()));
-                       
+
+                       /* it's possible some nodes are not shared between this 
mix node
+                        * inputs, but still needed to be always executed, this 
mainly
+                        * happens when a node of current subbranch is used by 
a parent
+                        * node or so */
+                       if(root_node != node) {
+                               foreach(ShaderInput *in, root_node->inputs) {
+                                       set<ShaderNode*> rootdeps;
+                                       find_dependencies(rootdeps, done, in, 
node);
+                                       set_intersection(rootdeps.begin(), 
rootdeps.end(),
+                                                        cl1deps.begin(), 
cl1deps.end(),
+                                                        
std::inserter(shareddeps, shareddeps.begin()));
+                                       set_intersection(rootdeps.begin(), 
rootdeps.end(),
+                                                        cl2deps.begin(), 
cl2deps.end(),
+                                                        
std::inserter(shareddeps, shareddeps.begin()));
+                               }
+                       }
+
                        if(!shareddeps.empty()) {
-                               if(cl1in->link)
-                                       
generated_shared_closure_nodes(cl1in->link->parent, done, closure_done, 
shareddeps);
-                               if(cl2in->link)
-                                       
generated_shared_closure_nodes(cl2in->link->parent, done, closure_done, 
shareddeps);
+                               if(cl1in->link) {
+                                       
generated_shared_closure_nodes(root_node, cl1in->link->parent,
+                                                                      done, 
closure_done, shareddeps);
+                               }
+                               if(cl2in->link) {
+                                       
generated_shared_closure_nodes(root_node, cl2in->link->parent,
+                                                                      done, 
closure_done, shareddeps);
+                               }
 
                                generate_svm_nodes(shareddeps, done);
                        }
@@ -525,7 +557,7 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, 
set<ShaderNode*>& don
                                svm_nodes.push_back(make_int4(NODE_JUMP_IF_ONE, 
0, facin->stack_offset, 0));
                                int node_jump_skip_index = svm_nodes.size() - 1;
 
-                               generate_multi_closure(cl1in->link->parent, 
done, closure_done);
+                               generate_multi_closure(root_node, 
cl1in->link->parent, done, closure_done);
 
                                /* fill in jump instruction location to be 
after closure */
                                svm_nodes[node_jump_skip_index].y = 
svm_nodes.size() - node_jump_skip_index - 1;
@@ -537,7 +569,7 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, 
set<ShaderNode*>& don
                                
svm_nodes.push_back(make_int4(NODE_JUMP_IF_ZERO, 0, facin->stack_offset, 0));
                                int node_jump_skip_index = svm_nodes.size() - 1;
 
-                               generate_multi_closure(cl2in->link->parent, 
done, closure_done);
+                               generate_multi_closure(root_node, 
cl2in->link->parent, done, closure_done);
 
                                /* fill in jump instruction location to be 
after closure */
                                svm_nodes[node_jump_skip_index].y = 
svm_nodes.size() - node_jump_skip_index - 1;
@@ -551,9 +583,9 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, 
set<ShaderNode*>& don
                         * to skip closures here because was already optimized 
due to
                         * fixed weight or add closure that always needs both */
                        if(cl1in->link)
-                               generate_multi_closure(cl1in->link->parent, 
done, closure_done);
+                               generate_multi_closure(root_node, 
cl1in->link->parent, done, closure_done);
                        if(cl2in->link)
-                               generate_multi_closure(cl2in->link->parent, 
done, closure_done);
+                               generate_multi_closure(root_node, 
cl2in->link->parent, done, closure_done);
                }
        }
        else {
@@ -638,7 +670,8 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph 
*graph, ShaderType ty
 
                        if(generate) {
                                set<ShaderNode*> done, closure_done;
-                               generate_multi_closure(clin->link->parent, 
done, closure_done);
+                               generate_multi_closure(clin->link->parent, 
clin->link->parent,
+                                                      done, closure_done);
                        }
                }
 
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index 45aa4d2..c1dd96e 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -123,15 +123,21 @@ protected:
 
        /* single closure */
        void find_dependencies(set<ShaderNode*>& dependencies,
-               const set<ShaderNode*>& done, ShaderInput *input);
+                              const set<ShaderNode*>& done,
+                              ShaderInput *input,
+                              ShaderNode *skip_node = NULL);
        void generate_node(ShaderNode *node, set<ShaderNode*>& done);
        void generate_closure_node(ShaderNode *node, set<ShaderNode*>& done);
-       void generated_shared_closure_nodes(ShaderNode *node, set<ShaderNode*>& 
done,
+       void generated_shared_closure_nodes(ShaderNode *root_node, ShaderNode 
*node,
+                                           set<ShaderNode*>& done,
                set<ShaderNode*>& closure_done, const set<ShaderNode*>& shared);
        void generate_svm_nodes(const set<ShaderNode*>& nodes, 
set<ShaderNode*>& done);
 
        /* multi closure */
-       void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, 
set<ShaderNode*>& closure_done);
+       void generate_multi_closure(ShaderNode *root_node,
+                                   ShaderNode *node,
+                                   set<ShaderNode*>& done,
+                                   set<ShaderNode*>& closure_done);
 
        /* compile */
        void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);

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

Reply via email to