[Bf-blender-cvs] [b3910374242] master: Nodes: Use topology cache for node exec node list

Hans Goudey noreply at git.blender.org
Mon Nov 21 18:53:09 CET 2022


Commit: b3910374242d7f8d43c908a2f0b9cc370d0a8f54
Author: Hans Goudey
Date:   Mon Nov 21 11:30:49 2022 -0600
Branches: master
https://developer.blender.org/rBb3910374242d7f8d43c908a2f0b9cc370d0a8f54

Nodes: Use topology cache for node exec node list

Instead of generating a dependency sorted node list whenever evaluating
texture or EEVEE/viewport shader nodes, use the existing sorted array
from the topology cache. This may be more efficient because the
algorithm isn't quadratic. It's also the second-to-last place to
use `node.runtime->level`, which can be removed soon.

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

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

M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/BKE_node_runtime.hh
M	source/blender/blenkernel/intern/node.cc
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/nodes/intern/node_exec.cc
M	source/blender/nodes/shader/node_shader_tree.cc

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

diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 7efc28a3ab3..680cf4c283d 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -512,9 +512,6 @@ bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup)
 void ntreeUpdateAllNew(struct Main *main);
 void ntreeUpdateAllUsers(struct Main *main, struct ID *id);
 
-void ntreeGetDependencyList(struct bNodeTree *ntree,
-                            struct bNode ***r_deplist,
-                            int *r_deplist_len);
 void ntreeUpdateNodeLevels(struct bNodeTree *ntree);
 
 /**
diff --git a/source/blender/blenkernel/BKE_node_runtime.hh b/source/blender/blenkernel/BKE_node_runtime.hh
index 831b5330a2f..48c6c7d3643 100644
--- a/source/blender/blenkernel/BKE_node_runtime.hh
+++ b/source/blender/blenkernel/BKE_node_runtime.hh
@@ -289,6 +289,18 @@ inline blender::Span<const bNode *> bNodeTree::toposort_right_to_left() const
   return this->runtime->toposort_right_to_left;
 }
 
+inline blender::Span<bNode *> bNodeTree::toposort_left_to_right()
+{
+  BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
+  return this->runtime->toposort_left_to_right;
+}
+
+inline blender::Span<bNode *> bNodeTree::toposort_right_to_left()
+{
+  BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
+  return this->runtime->toposort_right_to_left;
+}
+
 inline blender::Span<const bNode *> bNodeTree::all_nodes() const
 {
   BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 81ee2bdd34b..17fc4b51b95 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -4118,32 +4118,6 @@ static int node_get_deplist_recurs(bNodeTree *ntree, bNode *node, bNode ***nsort
   return level;
 }
 
-void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***r_deplist, int *r_deplist_len)
-{
-  *r_deplist_len = 0;
-
-  /* first clear data */
-  LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
-    node->runtime->done = false;
-    (*r_deplist_len)++;
-  }
-  if (*r_deplist_len == 0) {
-    *r_deplist = nullptr;
-    return;
-  }
-
-  bNode **nsort;
-  nsort = *r_deplist = (bNode **)MEM_callocN((*r_deplist_len) * sizeof(bNode *),
-                                             "sorted node array");
-
-  /* recursive check */
-  LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
-    if (node->runtime->done == 0) {
-      node->runtime->level = node_get_deplist_recurs(ntree, node, &nsort);
-    }
-  }
-}
-
 /* only updates node->level for detecting cycles links */
 void ntreeUpdateNodeLevels(bNodeTree *ntree)
 {
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 515740335a0..2399207464b 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -620,7 +620,9 @@ typedef struct bNodeTree {
    * toposort. However, if a connected component does not contain a cycle, this component is sorted
    * correctly. Use #has_available_link_cycle to check for cycles.
    */
+  blender::Span<bNode *> toposort_left_to_right();
   blender::Span<const bNode *> toposort_left_to_right() const;
+  blender::Span<bNode *> toposort_right_to_left();
   blender::Span<const bNode *> toposort_right_to_left() const;
   /** True when there are any cycles in the node tree. */
   bool has_available_link_cycle() const;
diff --git a/source/blender/nodes/intern/node_exec.cc b/source/blender/nodes/intern/node_exec.cc
index 53d6e2ea29e..3d8eafec75a 100644
--- a/source/blender/nodes/intern/node_exec.cc
+++ b/source/blender/nodes/intern/node_exec.cc
@@ -144,6 +144,7 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
                                 bNodeTree *ntree,
                                 bNodeInstanceKey parent_key)
 {
+  using namespace blender;
   bNodeTreeExec *exec;
   bNode *node;
   bNodeExec *nodeexec;
@@ -151,8 +152,6 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
   bNodeSocket *sock;
   bNodeStack *ns;
   int index;
-  bNode **nodelist;
-  int totnodes, n;
   /* XXX: texture-nodes have threading issues with muting, have to disable it there. */
 
   /* ensure all sock->link pointers and node levels are correct */
@@ -161,8 +160,8 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
    * since most of the time it won't be (thanks to ntree design)!!! */
   BKE_ntree_update_main_tree(G.main, ntree, nullptr);
 
-  /* get a dependency-sorted list of nodes */
-  ntreeGetDependencyList(ntree, &nodelist, &totnodes);
+  ntree->ensure_topology_cache();
+  const Span<bNode *> nodelist = ntree->toposort_left_to_right();
 
   /* XXX could let callbacks do this for specialized data */
   exec = MEM_cnew<bNodeTreeExec>("node tree execution data");
@@ -171,7 +170,7 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
 
   /* set stack indices */
   index = 0;
-  for (n = 0; n < totnodes; n++) {
+  for (const int n : nodelist.index_range()) {
     node = nodelist[n];
 
     /* init node socket stack indexes */
@@ -192,7 +191,7 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
   }
 
   /* allocated exec data pointers for nodes */
-  exec->totnodes = totnodes;
+  exec->totnodes = nodelist.size();
   exec->nodeexec = (bNodeExec *)MEM_callocN(exec->totnodes * sizeof(bNodeExec),
                                             "node execution data");
   /* allocate data pointer for node stack */
@@ -200,12 +199,13 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
   exec->stack = (bNodeStack *)MEM_callocN(exec->stacksize * sizeof(bNodeStack), "bNodeStack");
 
   /* all non-const results are considered inputs */
+  int n;
   for (n = 0; n < exec->stacksize; n++) {
     exec->stack[n].hasinput = 1;
   }
 
   /* prepare all nodes for execution */
-  for (n = 0, nodeexec = exec->nodeexec; n < totnodes; n++, nodeexec++) {
+  for (n = 0, nodeexec = exec->nodeexec; n < nodelist.size(); n++, nodeexec++) {
     node = nodeexec->node = nodelist[n];
     nodeexec->free_exec_fn = node->typeinfo->free_exec_fn;
 
@@ -236,10 +236,6 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
     }
   }
 
-  if (nodelist) {
-    MEM_freeN(nodelist);
-  }
-
   return exec;
 }
 
diff --git a/source/blender/nodes/shader/node_shader_tree.cc b/source/blender/nodes/shader/node_shader_tree.cc
index 0c0bb1c4316..188ed232858 100644
--- a/source/blender/nodes/shader/node_shader_tree.cc
+++ b/source/blender/nodes/shader/node_shader_tree.cc
@@ -889,6 +889,9 @@ static void ntree_shader_weight_tree_invert(bNodeTree *ntree, bNode *output_node
             case SH_NODE_VOLUME_PRINCIPLED:
             case SH_NODE_VOLUME_SCATTER:
               fromsock = ntree_shader_node_find_input(fromnode, "Weight");
+              /* Make "weight" sockets available so that links to it are available as well and are
+               * not ignored in other places. */
+              fromsock->flag &= ~SOCK_UNAVAIL;
               if (fromsock->link) {
                 ntree_weight_tree_merge_weight(ntree, fromnode, fromsock, &tonode, &tosock);
               }



More information about the Bf-blender-cvs mailing list