[Bf-blender-cvs] [6d7a067a83b] blender-v3.4-release: Fix T100904: Shader Nodes: Optimize-out inactive mix branches

Miguel Pozo noreply at git.blender.org
Tue Nov 22 13:40:43 CET 2022


Commit: 6d7a067a83bbae7ebb965e364eb9a6b8d0f333f3
Author: Miguel Pozo
Date:   Tue Nov 22 13:39:20 2022 +0100
Branches: blender-v3.4-release
https://developer.blender.org/rB6d7a067a83bbae7ebb965e364eb9a6b8d0f333f3

Fix T100904: Shader Nodes: Optimize-out inactive mix branches

Ensure inactive mix branches don't modify material flags or generate code.

Reviewed By: fclem

Maniphest Tasks: T100904

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

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

M	source/blender/nodes/shader/node_shader_tree.cc
M	source/blender/nodes/shader/nodes/node_shader_mix.cc

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

diff --git a/source/blender/nodes/shader/node_shader_tree.cc b/source/blender/nodes/shader/node_shader_tree.cc
index f177fc95ef8..7cdeb0c49b8 100644
--- a/source/blender/nodes/shader/node_shader_tree.cc
+++ b/source/blender/nodes/shader/node_shader_tree.cc
@@ -984,6 +984,93 @@ static void ntree_shader_shader_to_rgba_branch(bNodeTree *ntree, bNode *output_n
   }
 }
 
+static void shader_node_disconnect_input(bNodeTree *ntree, bNode *node, int index)
+{
+  bNodeLink *link = ntree_shader_node_input_get(node, index)->link;
+  if (link) {
+    nodeRemLink(ntree, link);
+  }
+}
+
+static void shader_node_disconnect_inactive_mix_branch(bNodeTree *ntree,
+                                                       bNode *node,
+                                                       int factor_socket_index,
+                                                       int a_socket_index,
+                                                       int b_socket_index,
+                                                       bool clamp_factor)
+{
+  bNodeSocket *factor_socket = ntree_shader_node_input_get(node, factor_socket_index);
+  if (factor_socket->link == nullptr) {
+    float factor = 0.5;
+
+    if (factor_socket->type == SOCK_FLOAT) {
+      factor = factor_socket->default_value_typed<bNodeSocketValueFloat>()->value;
+      if (clamp_factor) {
+        factor = clamp_f(factor, 0.0f, 1.0f);
+      }
+    }
+    else if (factor_socket->type == SOCK_VECTOR) {
+      const float *vfactor = factor_socket->default_value_typed<bNodeSocketValueVector>()->value;
+      float vfactor_copy[3];
+      for (int i = 0; i < 3; i++) {
+        if (clamp_factor) {
+          vfactor_copy[i] = clamp_f(vfactor[i], 0.0f, 1.0f);
+        }
+        else {
+          vfactor_copy[i] = vfactor[i];
+        }
+      }
+      if (vfactor_copy[0] == vfactor_copy[1] && vfactor_copy[0] == vfactor_copy[2]) {
+        factor = vfactor_copy[0];
+      }
+    }
+
+    if (factor == 1.0f && a_socket_index >= 0) {
+      shader_node_disconnect_input(ntree, node, a_socket_index);
+    }
+    else if (factor == 0.0f && b_socket_index >= 0) {
+      shader_node_disconnect_input(ntree, node, b_socket_index);
+    }
+  }
+}
+
+static void ntree_shader_disconnect_inactive_mix_branches(bNodeTree *ntree)
+{
+  LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+    if (node->type == SH_NODE_MIX_SHADER) {
+      shader_node_disconnect_inactive_mix_branch(ntree, node, 0, 1, 2, true);
+    }
+    else if (node->type == SH_NODE_MIX) {
+      const NodeShaderMix *storage = static_cast<NodeShaderMix *>(node->storage);
+      if (storage->data_type == SOCK_FLOAT) {
+        shader_node_disconnect_inactive_mix_branch(ntree, node, 0, 2, 3, storage->clamp_factor);
+        /* Disconnect links from data_type-specific sockets that are not currently in use */
+        for (int i : {1, 4, 5, 6, 7}) {
+          shader_node_disconnect_input(ntree, node, i);
+        }
+      }
+      else if (storage->data_type == SOCK_VECTOR) {
+        int factor_socket = storage->factor_mode == NODE_MIX_MODE_UNIFORM ? 0 : 1;
+        shader_node_disconnect_inactive_mix_branch(
+            ntree, node, factor_socket, 4, 5, storage->clamp_factor);
+        /* Disconnect links from data_type-specific sockets that are not currently in use */
+        int unused_factor_socket = factor_socket == 0 ? 1 : 0;
+        for (int i : {unused_factor_socket, 2, 3, 6, 7}) {
+          shader_node_disconnect_input(ntree, node, i);
+        }
+      }
+      else if (storage->data_type == SOCK_RGBA) {
+        /* Branch A can't be optimized-out, since its alpha is always used regardless of factor */
+        shader_node_disconnect_inactive_mix_branch(ntree, node, 0, -1, 7, storage->clamp_factor);
+        /* Disconnect links from data_type-specific sockets that are not currently in use */
+        for (int i : {1, 2, 3, 4, 5}) {
+          shader_node_disconnect_input(ntree, node, i);
+        }
+      }
+    }
+  }
+}
+
 static bool ntree_branch_node_tag(bNode *fromnode, bNode *tonode, void * /*userdata*/)
 {
   fromnode->tmp_flag = 1;
@@ -996,6 +1083,8 @@ static bool ntree_branch_node_tag(bNode *fromnode, bNode *tonode, void * /*userd
  * first executed SSS node gets a SSS profile. */
 static void ntree_shader_pruned_unused(bNodeTree *ntree, bNode *output_node)
 {
+  ntree_shader_disconnect_inactive_mix_branches(ntree);
+
   bool changed = false;
 
   LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
diff --git a/source/blender/nodes/shader/nodes/node_shader_mix.cc b/source/blender/nodes/shader/nodes/node_shader_mix.cc
index 878648105d1..28cbc85e93d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mix.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_mix.cc
@@ -22,6 +22,9 @@ NODE_STORAGE_FUNCS(NodeShaderMix)
 static void sh_node_mix_declare(NodeDeclarationBuilder &b)
 {
   b.is_function_node();
+  /** WARNING:
+   * Input socket indices must be kept in sync with ntree_shader_disconnect_inactive_mix_branches
+   */
   b.add_input<decl::Float>(N_("Factor"), "Factor_Float")
       .no_muted_links()
       .default_value(0.5f)



More information about the Bf-blender-cvs mailing list