Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2022-05-30 13:54:07 +0300
committerJacques Lucke <jacques@blender.org>2022-05-30 13:54:07 +0300
commitbb0fc675822f313c5546a2498a162472c2571ecb (patch)
tree2f4a7941a1a32d24260d3add53e92103506a8593 /source/blender/blenkernel
parent2f77b2daaccfa00866f049e4c2fc1cdee41e8ae1 (diff)
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
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_node_runtime.hh40
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/node.cc18
-rw-r--r--source/blender/blenkernel/intern/node_tree_update.cc76
4 files changed, 90 insertions, 45 deletions
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 NodeTreeMainUpdater {
{
bNodeTree &ntree = *node.btree();
bNode &bnode = *node.bnode();
- if (ntree.changed_flag & NTREE_CHANGED_ANY) {
+ if (ntree.runtime->changed_flag & NTREE_CHANGED_ANY) {
return true;
}
if (bnode.changed_flag & NTREE_CHANGED_NODE_PROPERTY) {
return true;
}
- if (ntree.changed_flag & NTREE_CHANGED_LINK) {
+ if (ntree.runtime->changed_flag & NTREE_CHANGED_LINK) {
/* Node groups currently always rebuilt their sockets when they are updated.
* So avoid calling the update method when no new link was added to it. */
if (node.is_group_input_node()) {
@@ -1101,7 +1103,7 @@ class NodeTreeMainUpdater {
return true;
}
}
- if (ntree.changed_flag & NTREE_CHANGED_INTERFACE) {
+ if (ntree.runtime->changed_flag & NTREE_CHANGED_INTERFACE) {
if (node.is_group_input_node() || node.is_group_output_node()) {
return true;
}
@@ -1232,16 +1234,16 @@ class NodeTreeMainUpdater {
}
/* Reset the changed_flag to allow detecting when the update callback changed the node tree. */
- 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;
ntree.typeinfo->update(&ntree);
- 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. */
tree_ref.reset();
}
- ntree.changed_flag |= old_changed_flag;
+ ntree.runtime->changed_flag |= old_changed_flag;
}
void remove_unused_previews_when_necessary(bNodeTree &ntree)
@@ -1250,7 +1252,7 @@ class NodeTreeMainUpdater {
const uint32_t allowed_flags = NTREE_CHANGED_LINK | NTREE_CHANGED_SOCKET_PROPERTY |
NTREE_CHANGED_NODE_PROPERTY | NTREE_CHANGED_NODE_OUTPUT |
NTREE_CHANGED_INTERFACE;
- if ((ntree.changed_flag & allowed_flags) == ntree.changed_flag) {
+ if ((ntree.runtime->changed_flag & allowed_flags) == ntree.runtime->changed_flag) {
return;
}
BKE_node_preview_remove_unused(&ntree);
@@ -1259,7 +1261,7 @@ class NodeTreeMainUpdater {
void propagate_runtime_flags(const NodeTreeRef &tree_ref)
{
bNodeTree &ntree = *tree_ref.btree();
- ntree.runtime_flag = 0;
+ ntree.runtime->runtime_flag = 0;
if (ntree.type != NTREE_SHADER) {
return;
}
@@ -1268,7 +1270,7 @@ class NodeTreeMainUpdater {
for (const NodeRef *group_node : tree_ref.nodes_by_type("NodeGroup")) {
const bNodeTree *group = reinterpret_cast<bNodeTree *>(group_node->bnode()->id);
if (group != nullptr) {
- ntree.runtime_flag |= group->runtime_flag;
+ ntree.runtime->runtime_flag |= group->runtime->runtime_flag;
}
}
/* Check if the tree itself has an animated image. */
@@ -1276,7 +1278,7 @@ class NodeTreeMainUpdater {
for (const NodeRef *node : tree_ref.nodes_by_type(idname)) {
Image *image = reinterpret_cast<Image *>(node->bnode()->id);
if (image != nullptr && BKE_image_is_animated(image)) {
- ntree.runtime_flag |= NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION;
+ ntree.runtime->runtime_flag |= NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION;
break;
}
}
@@ -1288,7 +1290,7 @@ class NodeTreeMainUpdater {
"ShaderNodeOutputAOV"}) {
const Span<const NodeRef *> nodes = tree_ref.nodes_by_type(idname);
if (!nodes.is_empty()) {
- ntree.runtime_flag |= NTREE_RUNTIME_FLAG_HAS_MATERIAL_OUTPUT;
+ ntree.runtime->runtime_flag |= NTREE_RUNTIME_FLAG_HAS_MATERIAL_OUTPUT;
break;
}
}
@@ -1323,12 +1325,12 @@ class NodeTreeMainUpdater {
/* Compute a hash that represents the node topology connected to the output. This always has to
* be updated even if it is not used to detect changes right now. Otherwise
- * #btree.output_topology_hash will go out of date. */
+ * #btree.runtime.output_topology_hash will go out of date. */
const Vector<const SocketRef *> tree_output_sockets = this->find_output_sockets(tree);
- const uint32_t old_topology_hash = btree.output_topology_hash;
+ const uint32_t old_topology_hash = btree.runtime->output_topology_hash;
const uint32_t new_topology_hash = this->get_combined_socket_topology_hash(
tree, tree_output_sockets);
- btree.output_topology_hash = new_topology_hash;
+ btree.runtime->output_topology_hash = new_topology_hash;
if (const AnimData *adt = BKE_animdata_from_id(&btree.id)) {
/* Drivers may copy values in the node tree around arbitrarily and may cause the output to
@@ -1352,7 +1354,7 @@ class NodeTreeMainUpdater {
}
}
- if (btree.changed_flag & NTREE_CHANGED_ANY) {
+ if (btree.runtime->changed_flag & NTREE_CHANGED_ANY) {
return true;
}
@@ -1361,8 +1363,8 @@ class NodeTreeMainUpdater {
}
/* The topology hash can only be used when only topology-changing operations have been done. */
- if (btree.changed_flag ==
- (btree.changed_flag & (NTREE_CHANGED_LINK | NTREE_CHANGED_REMOVED_NODE))) {
+ if (btree.runtime->changed_flag ==
+ (btree.runtime->changed_flag & (NTREE_CHANGED_LINK | NTREE_CHANGED_REMOVED_NODE))) {
if (old_topology_hash == new_topology_hash) {
return false;
}
@@ -1404,7 +1406,7 @@ class NodeTreeMainUpdater {
if (bnode.type == NODE_GROUP) {
const bNodeTree *node_group = reinterpret_cast<const bNodeTree *>(bnode.id);
if (node_group != nullptr &&
- node_group->runtime_flag & NTREE_RUNTIME_FLAG_HAS_MATERIAL_OUTPUT) {
+ node_group->runtime->runtime_flag & NTREE_RUNTIME_FLAG_HAS_MATERIAL_OUTPUT) {
return true;
}
}
@@ -1591,7 +1593,7 @@ class NodeTreeMainUpdater {
void reset_changed_flags(bNodeTree &ntree)
{
- ntree.changed_flag = NTREE_CHANGED_NOTHING;
+ ntree.runtime->changed_flag = NTREE_CHANGED_NOTHING;
LISTBASE_FOREACH (bNode *, node, &ntree.nodes) {
node->changed_flag = NTREE_CHANGED_NOTHING;
node->update = 0;