diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index ec0335b75a1..db80aad74d4 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -385,6 +385,10 @@ void SVMCompiler::generate_node(ShaderNode *node, set& done) if(node->has_spatial_varying()) current_shader->has_heterogeneous_volume = true; } + + /* detect if we have a blackbody converter, to prepare lookup table */ + if(node->has_converter_blackbody()) + current_shader->has_converter_blackbody = true; } void SVMCompiler::generate_svm_nodes(const set& nodes, set& done) @@ -404,10 +408,6 @@ void SVMCompiler::generate_svm_nodes(const set& nodes, sethas_converter_blackbody()) - current_shader->has_converter_blackbody = true; - generate_node(node, done); done.insert(node); } @@ -418,6 +418,59 @@ void SVMCompiler::generate_svm_nodes(const set& nodes, set& done) +{ + /* execute dependencies for closure */ + foreach(ShaderInput *in, node->inputs) { + if(!node_skip_input(node, in) && in->link) { + set dependencies; + find_dependencies(dependencies, done, in); + generate_svm_nodes(dependencies, done); + } + } + + /* closure mix weight */ + const char *weight_name = (current_type == SHADER_TYPE_VOLUME)? "VolumeMixWeight": "SurfaceMixWeight"; + ShaderInput *weight_in = node->input(weight_name); + + if(weight_in && (weight_in->link || weight_in->value.x != 1.0f)) { + stack_assign(weight_in); + mix_weight_offset = weight_in->stack_offset; + } + else + mix_weight_offset = SVM_STACK_INVALID; + + /* compile closure itself */ + generate_node(node, done); + + mix_weight_offset = SVM_STACK_INVALID; + + if(current_type == SHADER_TYPE_SURFACE) { + if(node->has_surface_emission()) + current_shader->has_surface_emission = true; + if(node->has_surface_transparent()) + current_shader->has_surface_transparent = true; + if(node->has_surface_bssrdf()) { + current_shader->has_surface_bssrdf = true; + if(node->has_bssrdf_bump()) + current_shader->has_bssrdf_bump = true; + } + } +} + +void SVMCompiler::generated_shared_closure_nodes(ShaderNode *node, set& done, set& closure_done, const set& shared) +{ + if(shared.find(node) != shared.end()) { + generate_multi_closure(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); + } + } +} + void SVMCompiler::generate_multi_closure(ShaderNode *node, set& done, set& closure_done) { /* only generate once */ @@ -455,8 +508,15 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set& don set_intersection(cl1deps.begin(), cl1deps.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); - generate_svm_nodes(shareddeps, done); + generate_svm_nodes(shareddeps, done); + } /* generate instructions for input closure 1 */ if(cl1in->link) { @@ -496,42 +556,7 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set& don } } else { - /* execute dependencies for closure */ - foreach(ShaderInput *in, node->inputs) { - if(!node_skip_input(node, in) && in->link) { - set dependencies; - find_dependencies(dependencies, done, in); - generate_svm_nodes(dependencies, done); - } - } - - /* closure mix weight */ - const char *weight_name = (current_type == SHADER_TYPE_VOLUME)? "VolumeMixWeight": "SurfaceMixWeight"; - ShaderInput *weight_in = node->input(weight_name); - - if(weight_in && (weight_in->link || weight_in->value.x != 1.0f)) { - stack_assign(weight_in); - mix_weight_offset = weight_in->stack_offset; - } - else - mix_weight_offset = SVM_STACK_INVALID; - - /* compile closure itself */ - generate_node(node, done); - - mix_weight_offset = SVM_STACK_INVALID; - - if(current_type == SHADER_TYPE_SURFACE) { - if(node->has_surface_emission()) - current_shader->has_surface_emission = true; - if(node->has_surface_transparent()) - current_shader->has_surface_transparent = true; - if(node->has_surface_bssrdf()) { - current_shader->has_surface_bssrdf = true; - if(node->has_bssrdf_bump()) - current_shader->has_bssrdf_bump = true; - } - } + generate_closure_node(node, done); } done.insert(node); diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index 22aedd83463..45aa4d26926 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -122,8 +122,12 @@ protected: bool node_skip_input(ShaderNode *node, ShaderInput *input); /* single closure */ - void find_dependencies(set& dependencies, const set& done, ShaderInput *input); + void find_dependencies(set& dependencies, + const set& done, ShaderInput *input); void generate_node(ShaderNode *node, set& done); + void generate_closure_node(ShaderNode *node, set& done); + void generated_shared_closure_nodes(ShaderNode *node, set& done, + set& closure_done, const set& shared); void generate_svm_nodes(const set& nodes, set& done); /* multi closure */