[Bf-blender-cvs] [edaeec3e720] master: Nodes: cache node declaration on node

Jacques Lucke noreply at git.blender.org
Tue Sep 14 16:38:56 CEST 2021


Commit: edaeec3e720cacf789d0b3c438df6c2944adbd8b
Author: Jacques Lucke
Date:   Tue Sep 14 16:34:31 2021 +0200
Branches: master
https://developer.blender.org/rBedaeec3e720cacf789d0b3c438df6c2944adbd8b

Nodes: cache node declaration on node

Previously, it was necessary to rebuild the node declaration
every time it was used. Now it is cached per node for easy
and fast access.

For more details on what this is, look at the comment in
`DNA_node_types.h`.

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

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

M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/intern/node.cc
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/nodes/NOD_node_declaration.hh
M	source/blender/nodes/intern/node_socket.cc

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

diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 9df3d7c544d..d4bc0245a61 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -731,6 +731,8 @@ void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available);
 
 int nodeSocketLinkLimit(const struct bNodeSocket *sock);
 
+void nodeDeclarationEnsure(struct bNodeTree *ntree, struct bNode *node);
+
 /* Node Clipboard */
 void BKE_node_clipboard_init(const struct bNodeTree *ntree);
 void BKE_node_clipboard_clear(void);
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index e6af587cbd7..61b90b44b03 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -653,6 +653,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
   BLO_read_list(reader, &ntree->nodes);
   LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
     node->typeinfo = nullptr;
+    node->declaration = nullptr;
 
     BLO_read_list(reader, &node->inputs);
     BLO_read_list(reader, &node->outputs);
@@ -1014,10 +1015,8 @@ IDTypeInfo IDType_ID_NT = {
 static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
 {
   if (ntype->declare != nullptr) {
-    blender::nodes::NodeDeclaration node_decl;
-    blender::nodes::NodeDeclarationBuilder builder{node_decl};
-    ntype->declare(builder);
-    node_decl.build(*ntree, *node);
+    nodeDeclarationEnsure(ntree, node);
+    node->declaration->build(*ntree, *node);
     return;
   }
   bNodeSocketTemplate *sockdef;
@@ -2216,6 +2215,10 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree,
   bNodeLink *link_dst, *link_src;
 
   *node_dst = *node_src;
+
+  /* Reset the declaration of the new node. */
+  node_dst->declaration = nullptr;
+
   /* can be called for nodes outside a node tree (e.g. clipboard) */
   if (ntree) {
     if (unique_name) {
@@ -3103,6 +3106,8 @@ static void node_free_node(bNodeTree *ntree, bNode *node)
     MEM_freeN(node->prop);
   }
 
+  delete node->declaration;
+
   MEM_freeN(node);
 
   if (ntree) {
@@ -3933,6 +3938,21 @@ int nodeSocketLinkLimit(const bNodeSocket *sock)
   return sock->limit;
 }
 
+/**
+ * If the node implements a `declare` function, this function makes sure that `node->declaration`
+ * is up to date.
+ */
+void nodeDeclarationEnsure(bNodeTree *UNUSED(ntree), bNode *node)
+{
+  if (node->typeinfo->declare == nullptr) {
+    return;
+  }
+
+  node->declaration = new blender::nodes::NodeDeclaration();
+  blender::nodes::NodeDeclarationBuilder builder{*node->declaration};
+  node->typeinfo->declare(builder);
+}
+
 /* ************** Node Clipboard *********** */
 
 #define USE_NODE_CB_VALIDATE
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 82eabf6995c..c4cbc71762c 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -216,6 +216,16 @@ typedef enum eNodeSocketFlag {
   SOCK_HIDE_LABEL = (1 << 12),
 } eNodeSocketFlag;
 
+/** Workaround to forward-declare C++ type in C header. */
+#ifdef __cplusplus
+namespace blender::nodes {
+class NodeDeclaration;
+}
+using NodeDeclarationHandle = blender::nodes::NodeDeclaration;
+#else
+typedef struct NodeDeclarationHandle NodeDeclarationHandle;
+#endif
+
 /* TODO: Limit data in bNode to what we want to see saved. */
 typedef struct bNode {
   struct bNode *next, *prev, *new_node;
@@ -315,6 +325,26 @@ typedef struct bNode {
    * needs to be a float to feed GPU_uniform.
    */
   float sss_id;
+
+  /**
+   * Describes the desired interface of the node. This is run-time data only.
+   * The actual interface of the node may deviate from the declaration temporarily.
+   * It's possible to sync the actual state of the node to the desired state. Currently, this is
+   * only done when a node is created or loaded.
+   *
+   * In the future, we may want to keep more data only in the declaration, so that it does not have
+   * to be synced to other places that are stored in files. That especially applies to data that
+   * can't be edited by users directly (e.g. min/max values of sockets, tooltips, ...).
+   *
+   * The declaration of a node can be recreated at any time when it is used. Caching it here is
+   * just a bit more efficient when it is used a lot. To make sure that the cache is up-to-date,
+   * call #nodeDeclarationEnsure before using it.
+   *
+   * Currently, the declaration is the same for every node of the same type. Going forward, that is
+   * intended to change though. Especially when nodes become more dynamic with respect to how many
+   * sockets they have.
+   */
+  NodeDeclarationHandle *declaration;
 } bNode;
 
 /* node->flag */
diff --git a/source/blender/nodes/NOD_node_declaration.hh b/source/blender/nodes/NOD_node_declaration.hh
index 52f4ac291d2..7ba4ac52b86 100644
--- a/source/blender/nodes/NOD_node_declaration.hh
+++ b/source/blender/nodes/NOD_node_declaration.hh
@@ -60,6 +60,8 @@ class NodeDeclaration {
 
   Span<SocketDeclarationPtr> inputs() const;
   Span<SocketDeclarationPtr> outputs() const;
+
+  MEM_CXX_CLASS_ALLOC_FUNCS("NodeDeclaration")
 };
 
 class NodeDeclarationBuilder {
diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc
index 8efd6c55459..31260f95242 100644
--- a/source/blender/nodes/intern/node_socket.cc
+++ b/source/blender/nodes/intern/node_socket.cc
@@ -269,11 +269,9 @@ void node_verify_sockets(bNodeTree *ntree, bNode *node, bool do_id_user)
     return;
   }
   if (ntype->declare != nullptr) {
-    blender::nodes::NodeDeclaration node_decl;
-    blender::nodes::NodeDeclarationBuilder builder{node_decl};
-    ntype->declare(builder);
-    if (!node_decl.matches(*node)) {
-      refresh_node(*ntree, *node, node_decl, do_id_user);
+    nodeDeclarationEnsure(ntree, node);
+    if (!node->declaration->matches(*node)) {
+      refresh_node(*ntree, *node, *node->declaration, do_id_user);
     }
     return;
   }



More information about the Bf-blender-cvs mailing list