diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index c9bbeecc3a4..8b527691bd9 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -156,6 +156,34 @@ int SVMCompiler::stack_find_offset(ShaderSocketType type) return offset; } +void SVMCompiler::stack_backup(StackBackup& backup, set& done) +{ + backup.done = done; + backup.stack = active_stack; + + foreach(ShaderNode *node, current_graph->nodes) { + foreach(ShaderInput *input, node->inputs) + backup.offsets.push_back(input->stack_offset); + foreach(ShaderOutput *output, node->outputs) + backup.offsets.push_back(output->stack_offset); + } +} + +void SVMCompiler::stack_restore(StackBackup& backup, set& done) +{ + int i = 0; + + done = backup.done; + active_stack = backup.stack; + + foreach(ShaderNode *node, current_graph->nodes) { + foreach(ShaderInput *input, node->inputs) + input->stack_offset = backup.offsets[i++]; + foreach(ShaderOutput *output, node->outputs) + output->stack_offset = backup.offsets[i++]; + } +} + void SVMCompiler::stack_assign(ShaderInput *input) { /* stack offset assign? */ @@ -354,13 +382,8 @@ void SVMCompiler::generate_svm_nodes(const set& nodes, set done, Stack stack) +void SVMCompiler::generate_closure(ShaderNode *node, set& done) { - /* note that done and stack are passed by value, that's intentional - because different branches of the closure tree should not influence - each other */ - active_stack = stack; - if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) { ShaderInput *fin = node->input("Fac"); ShaderInput *cl1in = node->input("Closure1"); @@ -383,11 +406,17 @@ void SVMCompiler::generate_closure(ShaderNode *node, set done, Stac else add_node(NODE_ADD_CLOSURE, 0, 0, 0); - /* generate code for closure 1 */ + /* generate code for closure 1 + note we backup all compiler state and restore it afterwards, so one + closure choice doesn't influence the other*/ if(cl1in->link) { - generate_closure(cl1in->link->parent, done, stack); + StackBackup backup; + stack_backup(backup, done); + + generate_closure(cl1in->link->parent, done); add_node(NODE_END, 0, 0, 0); - active_stack = stack; + + stack_restore(backup, done); } else add_node(NODE_END, 0, 0, 0); @@ -396,9 +425,13 @@ void SVMCompiler::generate_closure(ShaderNode *node, set done, Stac int cl2_offset = svm_nodes.size(); if(cl2in->link) { - generate_closure(cl2in->link->parent, done, stack); + StackBackup backup; + stack_backup(backup, done); + + generate_closure(cl2in->link->parent, done); add_node(NODE_END, 0, 0, 0); - active_stack = stack; + + stack_restore(backup, done); } else add_node(NODE_END, 0, 0, 0); @@ -530,6 +563,7 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty */ current_type = type; + current_graph = graph; /* get input in output node */ ShaderNode *node = graph->output(); @@ -576,13 +610,10 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty if(generate) { set done; - if(use_multi_closure) { + if(use_multi_closure) generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID); - } - else { - Stack stack; - generate_closure(clin->link->parent, done, stack); - } + else + generate_closure(clin->link->parent, done); } } diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index 4c23e931e09..d66d3816068 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -104,6 +104,15 @@ protected: int users[SVM_STACK_SIZE]; }; + struct StackBackup { + Stack stack; + vector offsets; + set done; + }; + + void stack_backup(StackBackup& backup, set& done); + void stack_restore(StackBackup& backup, set& done); + void stack_clear_temporary(ShaderNode *node); int stack_size(ShaderSocketType type); int stack_find_offset(ShaderSocketType type); @@ -113,7 +122,7 @@ protected: void find_dependencies(set& dependencies, const set& done, ShaderInput *input); void generate_svm_nodes(const set& nodes, set& done); - void generate_closure(ShaderNode *node, set done, Stack stack); + void generate_closure(ShaderNode *node, set& done); void generate_multi_closure(ShaderNode *node, set& done, uint in_offset); void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type); @@ -121,6 +130,7 @@ protected: vector svm_nodes; ShaderType current_type; Shader *current_shader; + ShaderGraph *current_graph; Stack active_stack; int max_stack_use; uint mix_weight_offset;