Commit: 1776f75c3b3621a28ed7af535192ce7f05faea8f
Author: Alexander Gavrilov
Date:   Sat Jul 30 20:03:49 2016 +0200
Branches: master
https://developer.blender.org/rB1776f75c3b3621a28ed7af535192ce7f05faea8f

Cycles: constant fold add/mul type nodes with known 0 and 1 arguments.

These values often either turn the node into a no-op, or even make it
evaluate to 0 no matter what the other input value is, thus allowing
deletion of a branch of the node graph that otherwise is not constant.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D2085

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

M       intern/cycles/render/constant_fold.cpp
M       intern/cycles/render/constant_fold.h
M       intern/cycles/render/nodes.cpp

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

diff --git a/intern/cycles/render/constant_fold.cpp 
b/intern/cycles/render/constant_fold.cpp
index 13e1222..473560b 100644
--- a/intern/cycles/render/constant_fold.cpp
+++ b/intern/cycles/render/constant_fold.cpp
@@ -64,7 +64,7 @@ void ConstantFolder::make_constant_clamp(float value, bool 
clamp) const
 
 void ConstantFolder::make_constant_clamp(float3 value, bool clamp) const
 {
-       if (clamp) {
+       if(clamp) {
                value.x = saturate(value.x);
                value.y = saturate(value.y);
                value.z = saturate(value.z);
@@ -73,6 +73,19 @@ void ConstantFolder::make_constant_clamp(float3 value, bool 
clamp) const
        make_constant(value);
 }
 
+void ConstantFolder::make_zero() const
+{
+       if(output->type() == SocketType::FLOAT) {
+               make_constant(0.0f);
+       }
+       else if(SocketType::is_float3(output->type())) {
+               make_constant(make_float3(0.0f, 0.0f, 0.0f));
+       }
+       else {
+               assert(0);
+       }
+}
+
 void ConstantFolder::bypass(ShaderOutput *new_output) const
 {
        assert(new_output);
@@ -99,7 +112,7 @@ void ConstantFolder::bypass_or_discard(ShaderInput *input) 
const
 {
        assert(input->type() == SocketType::CLOSURE);
 
-       if (input->link) {
+       if(input->link) {
                bypass(input->link);
        }
        else {
@@ -107,11 +120,20 @@ void ConstantFolder::bypass_or_discard(ShaderInput 
*input) const
        }
 }
 
-bool ConstantFolder::try_bypass_or_make_constant(ShaderInput *input, float3 
input_value, bool clamp) const
+bool ConstantFolder::try_bypass_or_make_constant(ShaderInput *input, bool 
clamp) const
 {
-       if(!input->link) {
-               make_constant_clamp(input_value, clamp);
-               return true;
+       if(input->type() != output->type()) {
+               return false;
+       }
+       else if(!input->link) {
+               if(input->type() == SocketType::FLOAT) {
+                       
make_constant_clamp(node->get_float(input->socket_type), clamp);
+                       return true;
+               }
+               else if(SocketType::is_float3(input->type())) {
+                       
make_constant_clamp(node->get_float3(input->socket_type), clamp);
+                       return true;
+               }
        }
        else if(!clamp) {
                bypass(input->link);
@@ -121,4 +143,212 @@ bool 
ConstantFolder::try_bypass_or_make_constant(ShaderInput *input, float3 inpu
        return false;
 }
 
+bool ConstantFolder::is_zero(ShaderInput *input) const
+{
+       if(!input->link) {
+               if(input->type() == SocketType::FLOAT) {
+                       return node->get_float(input->socket_type) == 0.0f;
+               }
+               else if(SocketType::is_float3(input->type())) {
+                       return node->get_float3(input->socket_type) ==
+                              make_float3(0.0f, 0.0f, 0.0f);
+               }
+       }
+
+       return false;
+}
+
+bool ConstantFolder::is_one(ShaderInput *input) const
+{
+       if(!input->link) {
+               if(input->type() == SocketType::FLOAT) {
+                       return node->get_float(input->socket_type) == 1.0f;
+               }
+               else if(SocketType::is_float3(input->type())) {
+                       return node->get_float3(input->socket_type) ==
+                              make_float3(1.0f, 1.0f, 1.0f);
+               }
+       }
+
+       return false;
+}
+
+/* Specific nodes */
+
+void ConstantFolder::fold_mix(NodeMix type, bool clamp) const
+{
+    ShaderInput *fac_in = node->input("Fac");
+    ShaderInput *color1_in = node->input("Color1");
+    ShaderInput *color2_in = node->input("Color2");
+
+       float fac = saturate(node->get_float(fac_in->socket_type));
+       bool fac_is_zero = !fac_in->link && fac == 0.0f;
+       bool fac_is_one = !fac_in->link && fac == 1.0f;
+
+       /* remove no-op node when factor is 0.0 */
+       if(fac_is_zero) {
+               /* note that some of the modes will clamp out of bounds values 
even without use_clamp */
+               if(!(type == NODE_MIX_LIGHT || type == NODE_MIX_DODGE || type 
== NODE_MIX_BURN)) {
+                       if(try_bypass_or_make_constant(color1_in, clamp)) {
+                               return;
+                       }
+               }
+       }
+
+       switch(type) {
+               case NODE_MIX_BLEND:
+                       /* remove useless mix colors nodes */
+                       if(color1_in->link && color2_in->link) {
+                               if(color1_in->link == color2_in->link) {
+                                       try_bypass_or_make_constant(color1_in, 
clamp);
+                                       break;
+                               }
+                       }
+                       else if(!color1_in->link && !color2_in->link) {
+                               float3 color1 = 
node->get_float3(color1_in->socket_type);
+                               float3 color2 = 
node->get_float3(color2_in->socket_type);
+                               if(color1 == color2) {
+                                       try_bypass_or_make_constant(color1_in, 
clamp);
+                                       break;
+                               }
+                       }
+                       /* remove no-op mix color node when factor is 1.0 */
+                       if(fac_is_one) {
+                               try_bypass_or_make_constant(color2_in, clamp);
+                               break;
+                       }
+                       break;
+               case NODE_MIX_ADD:
+                       /* 0 + X (fac 1) == X */
+                       if(is_zero(color1_in) && fac_is_one) {
+                               try_bypass_or_make_constant(color2_in, clamp);
+                       }
+                       /* X + 0 (fac ?) == X */
+                       else if(is_zero(color2_in)) {
+                               try_bypass_or_make_constant(color1_in, clamp);
+                       }
+                       break;
+               case NODE_MIX_SUB:
+                       /* X - 0 (fac ?) == X */
+                       if(is_zero(color2_in)) {
+                               try_bypass_or_make_constant(color1_in, clamp);
+                       }
+                       /* X - X (fac 1) == 0 */
+                       else if(color1_in->link && color1_in->link == 
color2_in->link && fac_is_one) {
+                               make_zero();
+                       }
+                       break;
+               case NODE_MIX_MUL:
+                       /* X * 1 (fac ?) == X, 1 * X (fac 1) == X */
+                       if(is_one(color1_in) && fac_is_one) {
+                               try_bypass_or_make_constant(color2_in, clamp);
+                       }
+                       else if(is_one(color2_in)) {
+                               try_bypass_or_make_constant(color1_in, clamp);
+                       }
+                       /* 0 * ? (fac ?) == 0, ? * 0 (fac 1) == 0 */
+                       else if(is_zero(color1_in) && fac_is_one) {
+                               make_zero();
+                       }
+                       else if(is_zero(color2_in)) {
+                               make_zero();
+                       }
+                       break;
+               case NODE_MIX_DIV:
+                       /* X / 1 (fac ?) == X */
+                       if(is_one(color2_in)) {
+                               try_bypass_or_make_constant(color1_in, clamp);
+                       }
+                       /* 0 / ? (fac ?) == 0 */
+                       else if(is_zero(color1_in)) {
+                               make_zero();
+                       }
+                       break;
+               default:
+                       break;
+       }
+}
+
+void ConstantFolder::fold_math(NodeMath type, bool clamp) const
+{
+       ShaderInput *value1_in = node->input("Value1");
+       ShaderInput *value2_in = node->input("Value2");
+
+       switch(type) {
+               case NODE_MATH_ADD:
+                       /* X + 0 == 0 + X == X */
+                       if(is_zero(value1_in)) {
+                               try_bypass_or_make_constant(value2_in, clamp);
+                       }
+                       else if(is_zero(value2_in)) {
+                               try_bypass_or_make_constant(value1_in, clamp);
+                       }
+                       break;
+               case NODE_MATH_SUBTRACT:
+                       /* X - 0 == X */
+                       if(is_zero(value2_in)) {
+                               try_bypass_or_make_constant(value1_in, clamp);
+                       }
+                       break;
+               case NODE_MATH_MULTIPLY:
+                       /* X * 1 == 1 * X == X */
+                       if(is_one(value1_in)) {
+                               try_bypass_or_make_constant(value2_in, clamp);
+                       }
+                       else if(is_one(value2_in)) {
+                               try_bypass_or_make_constant(value1_in, clamp);
+                       }
+                       /* X * 0 == 0 * X == 0 */
+                       else if(is_zero(value1_in) || is_zero(value2_in)) {
+                               make_zero();
+                       }
+                       break;
+               case NODE_MATH_DIVIDE:
+                       /* X / 1 == X */
+                       if(is_one(value2_in)) {
+                               try_bypass_or_make_constant(value1_in, clamp);
+                       }
+                       /* 0 / X == 0 */
+                       else if(is_zero(value1_in)) {
+                               make_zero();
+                       }
+                       break;
+               default:
+                       break;
+       }
+}
+
+void ConstantFolder::fold_vector_math(NodeVectorMath type) const
+{
+       ShaderInput *vector1_in = node->input("Vector1");
+       ShaderInput *vector2_in = node->input("Vector2");
+
+       switch(type) {
+               case NODE_VECTOR_MATH_ADD:
+                       /* X + 0 == 0 + X == X */
+                       if(is_zero(vector1_in)) {
+                               try_bypass_or_make_constant(vector2_in);
+                       }
+                       else if(is_zero(vector2_in)) {
+                               try_bypass_or_make_constant(vector1_in);
+                       }
+                       break;
+               case NODE_VECTOR_MATH_SUBTRACT:
+                       /* X - 0 == X */
+                       if(is_zero(vector2_in)) {
+                               try_bypass_or_make_constant(vector1_in);
+                       }
+                       break;
+               case NODE_VECTOR_MATH_DOT_PRODUCT:
+               case NODE_VECTOR_MATH_CROSS_PRODUCT:
+                       /* X * 0 == 0 * X == 0 */
+                       if(is_zero(vector1_in) || is_zero(vector2_in)) {
+                               make_zero();
+                       }
+                       break;
+               default:
+                       break;
+       }
+}
+
 CCL_NAMESPACE_END
diff --git a/intern/cycles/render/constant_fold.h 
b/intern/cycles/render/constant_fold.h
index 195e5b1..2b31c2a 100644
--- a/intern/cycles/render/constant_fold.h
+++ b/intern/cycles/render/constant_fold.h
@@ -18,7 +18,7 @@
 #define __CONSTANT_FOLD_H__
 
 #include "util_types.h"
-#include "util_vector.h"
+#include "svm_types.h"
 
 CCL_NAMESPACE_BEGIN
 
@@ -37,11 +37,12 @@ public:
 
        bool all_inputs_constant() const;
 
-       /* Constant folding helpers, always return true for convenience. */
+       /* Constant folding helpers */
        void make_constant(float value) const;
        void make_constant(float3 value) const;
        void make_constant_clamp(float value, bool clamp) const;
        void make_constant_clamp(float3 value, bool clamp) const;
+       void make_zero() const;
 
        /* Bypass node, relinking to another output socket. */
        void bypass(ShaderOutput *output) const;
@@ -51,7 +52,16 @@ public:
        void bypass_or_discard(ShaderInput *input) const;
 
        /* Bypass or make constant, unless we can't due to clamp being true. */
-       bool try_bypass_or_make_constant(ShaderInput *input, float3 
input_value, bool clamp) const;
+       bool try_bypass_or_make_constant(ShaderInput *input, bool clamp = 
false) const;
+
+       /* Test if shader inputs of the current nodes have fixed values. */
+       bool is_zero(ShaderInput *input) const;
+       bool is_one(ShaderInput *input) const;
+
+       /* Specific nodes. */
+       void fold_mix(NodeMix type, bool clamp) const;
+       void fold_math(NodeMath type, bool clamp) const;
+       void fold_vector_math(NodeVectorMath type) const;
 };
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index b3b0108..9009d71 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -3701,44 +3701,11 @@ void MixNode::compile(OSLCompiler& compiler)
 
 void MixNode::constant_fold(const ConstantFolder& folder)
 {
-       ShaderInput *fac_in = input("Fac");
-       ShaderInput *color1_in = input("Color1");
-       ShaderInput *color2_in = input("Color2");
-
-       /* evaluate fully constant node */
        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(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(folder.try_bypass_or_make_constant(color1_in, color1, 
use_clamp)) {
-                       return;
-               }
        }
-
-       if(type == NODE_MIX_BLEND) {
-               /* rem

@@ Diff output truncated at 10240 characters. @@

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

Reply via email to