[Bf-blender-cvs] [bb0fc675822] master: Nodes: add separately allocated run-time data for bNodeTree

Jacques Lucke noreply at git.blender.org
Mon May 30 12:54:17 CEST 2022


Commit: bb0fc675822f313c5546a2498a162472c2571ecb
Author: Jacques Lucke
Date:   Mon May 30 12:54:07 2022 +0200
Branches: master
https://developer.blender.org/rBbb0fc675822f313c5546a2498a162472c2571ecb

Nodes: add separately allocated run-time data for bNodeTree

`bNodeTree` has a lot of run-time embedded in it currently. Having a separately
allocated run-time struct has some benefits:
* Run-time data is not stored in files.
* Makes it easy to use c++ types as run-time data.
* More clear distinction between what data only exists at run-time and which doesn't.

This commit doesn't move all run-time data to the new struct yet, only the data where
I know for sure how it is used. The remaining data can be moved separately.

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

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

A	source/blender/blenkernel/BKE_node_runtime.hh
M	source/blender/blenkernel/CMakeLists.txt
M	source/blender/blenkernel/intern/node.cc
M	source/blender/blenkernel/intern/node_tree_update.cc
M	source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
M	source/blender/depsgraph/intern/builder/deg_builder_relations.cc
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/modifiers/intern/MOD_nodes.cc

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

diff --git a/source/blender/blenkernel/BKE_node_runtime.hh b/source/blender/blenkernel/BKE_node_runtime.hh
new file mode 100644
index 00000000000..c9c4577a2d4
--- /dev/null
+++ b/source/blender/blenkernel/BKE_node_runtime.hh
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#pragma once
+
+#include <memory>
+
+#include "BLI_sys_types.h"
+#include "BLI_utility_mixins.hh"
+
+namespace blender::nodes {
+struct FieldInferencingInterface;
+}
+
+namespace blender::bke {
+
+class bNodeTreeRuntime : NonCopyable, NonMovable {
+ public:
+  /**
+   * Keeps track of what changed in the node tree until the next update.
+   * Should not be changed directly, instead use the functions in `BKE_node_tree_update.h`.
+   * #eNodeTreeChangedFlag.
+   */
+  uint32_t changed_flag = 0;
+  /**
+   * A hash of the topology of the node tree leading up to the outputs. This is used to determine
+   * of the node tree changed in a way that requires updating geometry nodes or shaders.
+   */
+  uint32_t output_topology_hash = 0;
+
+  /**
+   * Used to cache run-time information of the node tree.
+   * #eNodeTreeRuntimeFlag.
+   */
+  uint8_t runtime_flag = 0;
+
+  /** Information about how inputs and outputs of the node group interact with fields. */
+  std::unique_ptr<nodes::FieldInferencingInterface> field_inferencing_interface;
+};
+
+}  // namespace blender::bke
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 0b4f81df452..4edec268fe8 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -431,6 +431,7 @@ set(SRC
   BKE_multires.h
   BKE_nla.h
   BKE_node.h
+  BKE_node_runtime.hh
   BKE_node_tree_update.h
   BKE_object.h
   BKE_object_deform.h
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 4d96ba58d28..95a514ef474 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -60,6 +60,7 @@
 #include "BKE_lib_query.h"
 #include "BKE_main.h"
 #include "BKE_node.h"
+#include "BKE_node_runtime.hh"
 #include "BKE_node_tree_update.h"
 
 #include "RNA_access.h"
@@ -94,6 +95,7 @@ using blender::Stack;
 using blender::StringRef;
 using blender::Vector;
 using blender::VectorSet;
+using blender::bke::bNodeTreeRuntime;
 using blender::nodes::FieldInferencingInterface;
 using blender::nodes::InputSocketFieldType;
 using blender::nodes::NodeDeclaration;
@@ -123,6 +125,7 @@ static void nodeMuteRerouteOutputLinks(struct bNodeTree *ntree,
 static void ntree_init_data(ID *id)
 {
   bNodeTree *ntree = (bNodeTree *)id;
+  ntree->runtime = MEM_new<bNodeTreeRuntime>(__func__);
   ntree_set_typeinfo(ntree, nullptr);
 }
 
@@ -134,6 +137,8 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
   /* We never handle usercount here for own data. */
   const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
 
+  ntree_dst->runtime = MEM_new<bNodeTreeRuntime>(__func__);
+
   /* in case a running nodetree is copied */
   ntree_dst->execdata = nullptr;
 
@@ -203,9 +208,9 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
   /* node tree will generate its own interface type */
   ntree_dst->interface_type = nullptr;
 
-  if (ntree_src->field_inferencing_interface) {
-    ntree_dst->field_inferencing_interface = new FieldInferencingInterface(
-        *ntree_src->field_inferencing_interface);
+  if (ntree_src->runtime->field_inferencing_interface) {
+    ntree_dst->runtime->field_inferencing_interface = std::make_unique<FieldInferencingInterface>(
+        *ntree_src->runtime->field_inferencing_interface);
   }
 
   if (flag & LIB_ID_COPY_NO_PREVIEW) {
@@ -258,8 +263,6 @@ static void ntree_free_data(ID *id)
     MEM_freeN(sock);
   }
 
-  delete ntree->field_inferencing_interface;
-
   /* free preview hash */
   if (ntree->previews) {
     BKE_node_instance_hash_free(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
@@ -270,6 +273,7 @@ static void ntree_free_data(ID *id)
   }
 
   BKE_previewimg_free(&ntree->preview);
+  MEM_delete(ntree->runtime);
 }
 
 static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket *sock)
@@ -670,9 +674,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
 
   ntree->progress = nullptr;
   ntree->execdata = nullptr;
-  ntree->runtime_flag = 0;
-
-  ntree->field_inferencing_interface = nullptr;
+  ntree->runtime = MEM_new<bNodeTreeRuntime>(__func__);
   BKE_ntree_update_tag_missing_runtime_data(ntree);
 
   BLO_read_data_address(reader, &ntree->adt);
diff --git a/source/blender/blenkernel/intern/node_tree_update.cc b/source/blender/blenkernel/intern/node_tree_update.cc
index 68e4cccba00..d4b7f695ee1 100644
--- a/source/blender/blenkernel/intern/node_tree_update.cc
+++ b/source/blender/blenkernel/intern/node_tree_update.cc
@@ -15,6 +15,7 @@
 #include "BKE_image.h"
 #include "BKE_main.h"
 #include "BKE_node.h"
+#include "BKE_node_runtime.hh"
 #include "BKE_node_tree_update.h"
 
 #include "MOD_nodes.h"
@@ -48,7 +49,7 @@ enum eNodeTreeChangedFlag {
 
 static void add_tree_tag(bNodeTree *ntree, const eNodeTreeChangedFlag flag)
 {
-  ntree->changed_flag |= flag;
+  ntree->runtime->changed_flag |= flag;
 }
 
 static void add_node_tag(bNodeTree *ntree, bNode *node, const eNodeTreeChangedFlag flag)
@@ -172,11 +173,11 @@ static FieldInferencingInterface get_node_field_inferencing_interface(const Node
       /* This can happen when there is a linked node group that was not found (see T92799). */
       return get_dummy_field_inferencing_interface(node);
     }
-    if (group->field_inferencing_interface == nullptr) {
+    if (!group->runtime->field_inferencing_interface) {
       /* This shouldn't happen because referenced node groups should always be updated first. */
       BLI_assert_unreachable();
     }
-    return *group->field_inferencing_interface;
+    return *group->runtime->field_inferencing_interface;
   }
 
   FieldInferencingInterface inferencing_interface;
@@ -551,7 +552,8 @@ static bool update_field_inferencing(const NodeTreeRef &tree)
   bNodeTree &btree = *tree.btree();
 
   /* Create new inferencing interface for this node group. */
-  FieldInferencingInterface *new_inferencing_interface = new FieldInferencingInterface();
+  std::unique_ptr<FieldInferencingInterface> new_inferencing_interface =
+      std::make_unique<FieldInferencingInterface>();
   new_inferencing_interface->inputs.resize(BLI_listbase_count(&btree.inputs),
                                            InputSocketFieldType::IsSupported);
   new_inferencing_interface->outputs.resize(BLI_listbase_count(&btree.outputs),
@@ -567,11 +569,10 @@ static bool update_field_inferencing(const NodeTreeRef &tree)
   update_socket_shapes(tree, field_state_by_socket_id);
 
   /* Update the previous group interface. */
-  const bool group_interface_changed = btree.field_inferencing_interface == nullptr ||
-                                       *btree.field_inferencing_interface !=
+  const bool group_interface_changed = !btree.runtime->field_inferencing_interface ||
+                                       *btree.runtime->field_inferencing_interface !=
                                            *new_inferencing_interface;
-  delete btree.field_inferencing_interface;
-  btree.field_inferencing_interface = new_inferencing_interface;
+  btree.runtime->field_inferencing_interface = std::move(new_inferencing_interface);
 
   return group_interface_changed;
 }
@@ -799,7 +800,7 @@ class NodeTreeMainUpdater {
   {
     Vector<bNodeTree *> changed_ntrees;
     FOREACH_NODETREE_BEGIN (bmain_, ntree, id) {
-      if (ntree->changed_flag != NTREE_CHANGED_NOTHING) {
+      if (ntree->runtime->changed_flag != NTREE_CHANGED_NOTHING) {
         changed_ntrees.append(ntree);
       }
     }
@@ -817,7 +818,7 @@ class NodeTreeMainUpdater {
 
     if (root_ntrees.size() == 1) {
       bNodeTree *ntree = root_ntrees[0];
-      if (ntree->changed_flag == NTREE_CHANGED_NOTHING) {
+      if (ntree->runtime->changed_flag == NTREE_CHANGED_NOTHING) {
         return;
       }
       const TreeUpdateResult result = this->update_tree(*ntree);
@@ -830,7 +831,7 @@ class NodeTreeMainUpdater {
     if (!is_single_tree_update) {
       Vector<bNodeTree *> ntrees_in_order = this->get_tree_update_order(root_ntrees);
       for (bNodeTree *ntree : ntrees_in_order) {
-        if (ntree->changed_flag == NTREE_CHANGED_NOTHING) {
+        if (ntree->runtime->changed_flag == NTREE_CHANGED_NOTHING) {
           continue;
         }
         if (!update_result_by_tree_.contains(ntree)) {
@@ -1002,7 +1003,8 @@ class NodeTreeMainUpdater {
       ntreeTexCheckCyclics(&ntree);
     }
 
-    if (ntree.changed_flag & NTREE_CHANGED_INTERFACE || ntree.changed_flag & NTREE_CHANGED_ANY) {
+    if (ntree.runtime->changed_flag & NTREE_CHANGED_INTERFACE ||
+        ntree.runtime->changed_flag & NTREE_CHANGED_ANY) {
       result.interface_changed = true;
     }
 
@@ -1057,18 +1059,18 @@ class NodeTreeMainUpdater {
       this->ensure_tree_ref(ntree, tree_ref);
       const NodeRef &node = *tree_ref->find_node(*bnode);
       if (this->should_update_individual_node(node)) {
-        const uint32_t old_changed_flag = ntree.changed_flag;
-        ntree.changed_flag = NTREE_CHANGED_NOTHING;
+        const uint32_t old_changed_flag = ntree.runtime->changed_flag;
+        ntree.runtime->changed_flag = NTREE_CHANGED_NOTHING;
 
-        /* This may set #ntree.changed_flag which is detected below. */
+        /* This may set #ntree.runtime->changed_flag which is detected below. */
         this->update_individual_node(node);
 
-        if (ntree.changed_flag != NTREE_CHANGED_NOTHING) {
+        if (ntree.runtime->changed_flag != NTREE_CHANGED_NOTHING) {
           /* The tree ref is outdated and needs to be rebuilt. Generally, only very few update
            * functions change the node. Typically zero or one nodes change after an update. */
           tree_ref.reset();
         }
-        ntree.changed_flag |= old_changed_flag;
+        ntree.runtime->changed_flag |= old_changed_flag;
       }
     }
   }
@@ -1077,13 +1079,13 @@ class NodeTre

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list