diff options
Diffstat (limited to 'intern/cycles/render/nodes.cpp')
-rw-r--r-- | intern/cycles/render/nodes.cpp | 314 |
1 files changed, 136 insertions, 178 deletions
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 15b55d17301..e26084c690b 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -22,6 +22,7 @@ #include "svm_color_util.h" #include "svm_math_util.h" #include "osl.h" +#include "constant_fold.h" #include "util_sky_model.h" #include "util_foreach.h" @@ -1576,14 +1577,11 @@ RGBToBWNode::RGBToBWNode() { } -bool RGBToBWNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +void RGBToBWNode::constant_fold(const ConstantFolder& folder) { - if(all_inputs_constant()) { - optimized->set(linear_rgb_to_gray(color)); - return true; + if(folder.all_inputs_constant()) { + folder.make_constant(linear_rgb_to_gray(color)); } - - return false; } void RGBToBWNode::compile(SVMCompiler& compiler) @@ -1661,38 +1659,35 @@ ConvertNode::ConvertNode(SocketType::Type from_, SocketType::Type to_, bool auto special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT; } -bool ConvertNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +void ConvertNode::constant_fold(const ConstantFolder& folder) { /* proxy nodes should have been removed at this point */ assert(special_type != SHADER_SPECIAL_TYPE_PROXY); /* TODO(DingTo): conversion from/to int is not supported yet, don't fold in that case */ - if(all_inputs_constant()) { + if(folder.all_inputs_constant()) { if(from == SocketType::FLOAT) { if(SocketType::is_float3(to)) { - optimized->set(make_float3(value_float, value_float, value_float)); - return true; + folder.make_constant(make_float3(value_float, value_float, value_float)); } } else if(SocketType::is_float3(from)) { if(to == SocketType::FLOAT) { - if(from == SocketType::COLOR) + if(from == SocketType::COLOR) { /* color to float */ - optimized->set(linear_rgb_to_gray(value_color)); - else + folder.make_constant(linear_rgb_to_gray(value_color)); + } + else { /* vector/point/normal to float */ - optimized->set(average(value_vector)); - return true; + folder.make_constant(average(value_vector)); + } } else if(SocketType::is_float3(to)) { - optimized->set(value_color); - return true; + folder.make_constant(value_color); } } } - - return false; } void ConvertNode::compile(SVMCompiler& compiler) @@ -2362,13 +2357,15 @@ void EmissionNode::compile(OSLCompiler& compiler) compiler.add(this, "node_emission"); } -bool EmissionNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *) +void EmissionNode::constant_fold(const ConstantFolder& folder) { ShaderInput *color_in = input("Color"); ShaderInput *strength_in = input("Strength"); - return ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) || - (!strength_in->link && strength == 0.0f)); + if ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) || + (!strength_in->link && strength == 0.0f)) { + folder.discard(); + } } /* Background Closure */ @@ -2412,13 +2409,15 @@ void BackgroundNode::compile(OSLCompiler& compiler) compiler.add(this, "node_background"); } -bool BackgroundNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *) +void BackgroundNode::constant_fold(const ConstantFolder& folder) { ShaderInput *color_in = input("Color"); ShaderInput *strength_in = input("Strength"); - return ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) || - (!strength_in->link && strength == 0.0f)); + if ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) || + (!strength_in->link && strength == 0.0f)) { + folder.discard(); + } } /* Holdout Closure */ @@ -3380,10 +3379,9 @@ ValueNode::ValueNode() { } -bool ValueNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +void ValueNode::constant_fold(const ConstantFolder& folder) { - optimized->set(value); - return true; + folder.make_constant(value); } void ValueNode::compile(SVMCompiler& compiler) @@ -3416,10 +3414,9 @@ ColorNode::ColorNode() { } -bool ColorNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +void ColorNode::constant_fold(const ConstantFolder& folder) { - optimized->set(value); - return true; + folder.make_constant(value); } void ColorNode::compile(SVMCompiler& compiler) @@ -3468,6 +3465,20 @@ void AddClosureNode::compile(OSLCompiler& compiler) compiler.add(this, "node_add_closure"); } +void AddClosureNode::constant_fold(const ConstantFolder& folder) +{ + ShaderInput *closure1_in = input("Closure1"); + ShaderInput *closure2_in = input("Closure2"); + + /* remove useless add closures nodes */ + if(!closure1_in->link) { + folder.bypass_or_discard(closure2_in); + } + else if(!closure2_in->link) { + folder.bypass_or_discard(closure1_in); + } +} + /* Mix Closure */ NODE_DEFINE(MixClosureNode) @@ -3499,35 +3510,28 @@ void MixClosureNode::compile(OSLCompiler& compiler) compiler.add(this, "node_mix_closure"); } -bool MixClosureNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *) +void MixClosureNode::constant_fold(const ConstantFolder& folder) { ShaderInput *fac_in = input("Fac"); ShaderInput *closure1_in = input("Closure1"); ShaderInput *closure2_in = input("Closure2"); - ShaderOutput *closure_out = output("Closure"); /* remove useless mix closures nodes */ if(closure1_in->link == closure2_in->link) { - graph->relink(this, closure_out, closure1_in->link); - return true; + folder.bypass_or_discard(closure1_in); } - - /* remove unused mix closure input when factor is 0.0 or 1.0 */ - /* check for closure links and make sure factor link is disconnected */ - if(closure1_in->link && closure2_in->link && !fac_in->link) { + /* remove unused mix closure input when factor is 0.0 or 1.0 + * check for closure links and make sure factor link is disconnected */ + else if(!fac_in->link) { /* factor 0.0 */ - if(fac == 0.0f) { - graph->relink(this, closure_out, closure1_in->link); - return true; + if(fac <= 0.0f) { + folder.bypass_or_discard(closure1_in); } /* factor 1.0 */ - else if(fac == 1.0f) { - graph->relink(this, closure_out, closure2_in->link); - return true; + else if(fac >= 1.0f) { + folder.bypass_or_discard(closure2_in); } } - - return false; } /* Mix Closure */ @@ -3589,26 +3593,21 @@ InvertNode::InvertNode() { } -bool InvertNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *optimized) +void InvertNode::constant_fold(const ConstantFolder& folder) { ShaderInput *fac_in = input("Fac"); ShaderInput *color_in = input("Color"); - ShaderOutput *color_out = output("Color"); if(!fac_in->link) { /* evaluate fully constant node */ if(!color_in->link) { - optimized->set(interp(color, make_float3(1.0f, 1.0f, 1.0f) - color, fac)); - return true; + folder.make_constant(interp(color, make_float3(1.0f, 1.0f, 1.0f) - color, fac)); } /* remove no-op node */ else if(fac == 0.0f) { - graph->relink(this, color_out, color_in->link); - return true; + folder.bypass(color_in->link); } } - - return false; } void InvertNode::compile(SVMCompiler& compiler) @@ -3697,61 +3696,47 @@ void MixNode::compile(OSLCompiler& compiler) compiler.add(this, "node_mix"); } -bool MixNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *optimized) +void MixNode::constant_fold(const ConstantFolder& folder) { ShaderInput *fac_in = input("Fac"); ShaderInput *color1_in = input("Color1"); ShaderInput *color2_in = input("Color2"); - ShaderOutput *color_out = output("Color"); /* evaluate fully constant node */ - if(all_inputs_constant()) { - float3 result = svm_mix(type, fac, color1, color2); - optimized->set(use_clamp ? svm_mix_clamp(result) : result); - return true; + if(folder.all_inputs_constant()) { + folder.make_constant_clamp(svm_mix(type, fac, color1, color2), use_clamp); + return; } /* remove no-op node when factor is 0.0 */ if(!fac_in->link && fac <= 0.0f) { /* note that some of the modes will clamp out of bounds values even without use_clamp */ - if(!color1_in->link) { - float3 result = svm_mix(type, 0.0f, color1, color1); - optimized->set(use_clamp ? svm_mix_clamp(result) : result); - return true; + if(type == NODE_MIX_LIGHT || type == NODE_MIX_DODGE || type == NODE_MIX_BURN) { + if(!color1_in->link) { + folder.make_constant_clamp(svm_mix(type, 0.0f, color1, color1), use_clamp); + return; + } } - else if(!use_clamp && type != NODE_MIX_LIGHT && type != NODE_MIX_DODGE && type != NODE_MIX_BURN) { - graph->relink(this, color_out, color1_in->link); - return true; + else if(folder.try_bypass_or_make_constant(color1_in, color1, use_clamp)) { + return; } } - if(type != NODE_MIX_BLEND) { - return false; - } - - /* remove useless mix colors nodes */ - if(color1_in->link && color1_in->link == color2_in->link && !use_clamp) { - graph->relink(this, color_out, color1_in->link); - return true; - } - if(!color1_in->link && !color2_in->link && color1 == color2) { - optimized->set(use_clamp ? svm_mix_clamp(color1) : color1); - return true; - } - - /* remove no-op mix color node when factor is 1.0 */ - if(!fac_in->link && fac >= 1.0f) { - if(!color2_in->link) { - optimized->set(use_clamp ? svm_mix_clamp(color2) : color2); - return true; + if(type == NODE_MIX_BLEND) { + /* remove useless mix colors nodes */ + if(color1_in->link ? (color1_in->link == color2_in->link) : (!color2_in->link && color1 == color2)) { + if(folder.try_bypass_or_make_constant(color1_in, color1, use_clamp)) { + return; + } } - else if(!use_clamp) { - graph->relink(this, color_out, color2_in->link); - return true; + + /* remove no-op mix color node when factor is 1.0 */ + if(!fac_in->link && fac >= 1.0f) { + if(folder.try_bypass_or_make_constant(color2_in, color2, use_clamp)) { + return; + } } } - - return false; } /* Combine RGB */ @@ -3774,14 +3759,11 @@ CombineRGBNode::CombineRGBNode() { } -bool CombineRGBNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +void CombineRGBNode::constant_fold(const ConstantFolder& folder) { - if(all_inputs_constant()) { - optimized->set(make_float3(r, g, b)); - return true; + if(folder.all_inputs_constant()) { + folder.make_constant(make_float3(r, g, b)); } - - return false; } void CombineRGBNode::compile(SVMCompiler& compiler) @@ -3829,14 +3811,11 @@ CombineXYZNode::CombineXYZNode() { } -bool CombineXYZNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +void CombineXYZNode::constant_fold(const ConstantFolder& folder) { - if(all_inputs_constant()) { - optimized->set(make_float3(x, y, z)); - return true; + if(folder.all_inputs_constant()) { + folder.make_constant(make_float3(x, y, z)); } - - return false; } void CombineXYZNode::compile(SVMCompiler& compiler) @@ -3884,14 +3863,11 @@ CombineHSVNode::CombineHSVNode() { } -bool CombineHSVNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +void CombineHSVNode::constant_fold(const ConstantFolder& folder) { - if(all_inputs_constant()) { - optimized->set(hsv_to_rgb(make_float3(h, s, v))); - return true; + if(folder.all_inputs_constant()) { + folder.make_constant(hsv_to_rgb(make_float3(h, s, v))); } - - return false; } void CombineHSVNode::compile(SVMCompiler& compiler) @@ -3932,14 +3908,11 @@ GammaNode::GammaNode() { } -bool GammaNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +void GammaNode::constant_fold(const ConstantFolder& folder) { - if(all_inputs_constant()) { - optimized->set(svm_math_gamma_color(color, gamma)); - return true; + if(folder.all_inputs_constant()) { + folder.make_constant(svm_math_gamma_color(color, gamma)); } - - return false; } void GammaNode::compile(SVMCompiler& compiler) @@ -3979,14 +3952,11 @@ BrightContrastNode::BrightContrastNode() { } -bool BrightContrastNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +void BrightContrastNode::constant_fold(const ConstantFolder& folder) { - if(all_inputs_constant()) { - optimized->set(svm_brightness_contrast(color, bright, contrast)); - return true; + if(folder.all_inputs_constant()) { + folder.make_constant(svm_brightness_contrast(color, bright, contrast)); } - - return false; } void BrightContrastNode::compile(SVMCompiler& compiler) @@ -4029,18 +3999,16 @@ SeparateRGBNode::SeparateRGBNode() { } -bool SeparateRGBNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized) +void SeparateRGBNode::constant_fold(const ConstantFolder& folder) { - if(all_inputs_constant()) { + if(folder.all_inputs_constant()) { for(int channel = 0; channel < 3; channel++) { - if(outputs[channel] == socket) { - optimized->set(color[channel]); - return true; + if(outputs[channel] == folder.output) { + folder.make_constant(color[channel]); + return; } } } - - return false; } void SeparateRGBNode::compile(SVMCompiler& compiler) @@ -4088,18 +4056,16 @@ SeparateXYZNode::SeparateXYZNode() { } -bool SeparateXYZNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized) +void SeparateXYZNode::constant_fold(const ConstantFolder& folder) { - if(all_inputs_constant()) { + if(folder.all_inputs_constant()) { for(int channel = 0; channel < 3; channel++) { - if(outputs[channel] == socket) { - optimized->set(vector[channel]); - return true; + if(outputs[channel] == folder.output) { + folder.make_constant(vector[channel]); + return; } } } - - return false; } void SeparateXYZNode::compile(SVMCompiler& compiler) @@ -4147,20 +4113,18 @@ SeparateHSVNode::SeparateHSVNode() { } -bool SeparateHSVNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized) +void SeparateHSVNode::constant_fold(const ConstantFolder& folder) { - if(all_inputs_constant()) { + if(folder.all_inputs_constant()) { float3 hsv = rgb_to_hsv(color); for(int channel = 0; channel < 3; channel++) { - if(outputs[channel] == socket) { - optimized->set(hsv[channel]); - return true; + if(outputs[channel] == folder.output) { + folder.make_constant(hsv[channel]); + return; } } } - - return false; } void SeparateHSVNode::compile(SVMCompiler& compiler) @@ -4546,14 +4510,11 @@ BlackbodyNode::BlackbodyNode() { } -bool BlackbodyNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +void BlackbodyNode::constant_fold(const ConstantFolder& folder) { - if(all_inputs_constant()) { - optimized->set(svm_math_blackbody_color(temperature)); - return true; + if(folder.all_inputs_constant()) { + folder.make_constant(svm_math_blackbody_color(temperature)); } - - return false; } void BlackbodyNode::compile(SVMCompiler& compiler) @@ -4655,15 +4616,11 @@ MathNode::MathNode() { } -bool MathNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +void MathNode::constant_fold(const ConstantFolder& folder) { - if(all_inputs_constant()) { - float value = svm_math(type, value1, value2); - optimized->set(use_clamp ? saturate(value) : value); - return true; + if(folder.all_inputs_constant()) { + folder.make_constant_clamp(svm_math(type, value1, value2), use_clamp); } - - return false; } void MathNode::compile(SVMCompiler& compiler) @@ -4717,29 +4674,25 @@ VectorMathNode::VectorMathNode() { } -bool VectorMathNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized) +void VectorMathNode::constant_fold(const ConstantFolder& folder) { float value; float3 vector; - if(all_inputs_constant()) { + if(folder.all_inputs_constant()) { svm_vector_math(&value, &vector, type, vector1, vector2); - if(socket == output("Value")) { - optimized->set(value); - return true; + if(folder.output == output("Value")) { + folder.make_constant(value); } - else if(socket == output("Vector")) { - optimized->set(vector); - return true; + else if(folder.output == output("Vector")) { + folder.make_constant(vector); } } - - return false; } void VectorMathNode::compile(SVMCompiler& compiler) @@ -4873,7 +4826,7 @@ void BumpNode::compile(OSLCompiler& compiler) compiler.add(this, "node_bump"); } -bool BumpNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *) +void BumpNode::constant_fold(const ConstantFolder& folder) { ShaderInput *height_in = input("Height"); ShaderInput *normal_in = input("Normal"); @@ -4881,18 +4834,15 @@ bool BumpNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *) if(height_in->link == NULL) { if(normal_in->link == NULL) { GeometryNode *geom = new GeometryNode(); - graph->add(geom); - graph->relink(this, outputs[0], geom->output("Normal")); + folder.graph->add(geom); + folder.bypass(geom->output("Normal")); } else { - graph->relink(this, outputs[0], normal_in->link); + folder.bypass(normal_in->link); } - return true; } /* TODO(sergey): Ignore bump with zero strength. */ - - return false; } @@ -5112,12 +5062,10 @@ OSLNode::~OSLNode() ShaderNode *OSLNode::clone() const { - OSLNode *node = new OSLNode(*this); - node->type = new NodeType(*type); - return node; + return OSLNode::create(this->inputs.size(), this); } -OSLNode* OSLNode::create(size_t num_inputs) +OSLNode* OSLNode::create(size_t num_inputs, const OSLNode *from) { /* allocate space for the node itself and parameters, aligned to 16 bytes * assuming that's the most parameter types need */ @@ -5127,7 +5075,17 @@ OSLNode* OSLNode::create(size_t num_inputs) char *node_memory = (char*) operator new(node_size + inputs_size); memset(node_memory, 0, node_size + inputs_size); - return new(node_memory) OSLNode(); + if (!from) { + return new(node_memory) OSLNode(); + } + else { + /* copy input default values and node type for cloning */ + memcpy(node_memory + node_size, (char*)from + node_size, inputs_size); + + OSLNode *node = new(node_memory) OSLNode(*from); + node->type = new NodeType(*(from->type)); + return node; + } } char* OSLNode::input_default_value() |