From 5a964664d6cf54deb3d5590f8581683f865af747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dietrich?= Date: Sun, 2 May 2021 02:23:34 +0200 Subject: Cycles: add reference counting to Nodes This adds a reference count to Nodes which is incremented or decremented whenever they are added to or removed from a socket, which will help us track used Nodes throughout the scene graph generically without having to add an explicit count or flag on specific Node types. This is especially useful to track Nodes defined through Procedurals out of Cycles' control. This also modifies the order in which nodes are deleted to ensure that upon deletion, a Node does not attempt to decrement the reference count of another Node which was already freed or deleted. This is not currently used, but will be in the next commit. Reviewed By: brecht Differential Revision: https://developer.blender.org/D10965 --- intern/cycles/graph/node.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) (limited to 'intern/cycles/graph/node.cpp') diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp index c926f6ab8ef..c5b4bb471bb 100644 --- a/intern/cycles/graph/node.cpp +++ b/intern/cycles/graph/node.cpp @@ -367,9 +367,17 @@ void Node::copy_value(const SocketType &socket, const Node &other, const SocketT case SocketType::TRANSFORM_ARRAY: copy_array(this, socket, &other, other_socket); break; - case SocketType::NODE_ARRAY: + case SocketType::NODE_ARRAY: { copy_array(this, socket, &other, other_socket); + + array &node_array = get_socket_value>(this, socket); + + for (Node *node: node_array) { + node->reference(); + } + break; + } default: assert(0); break; @@ -379,6 +387,14 @@ void Node::copy_value(const SocketType &socket, const Node &other, const SocketT const void *src = ((char *)&other) + other_socket.struct_offset; void *dst = ((char *)this) + socket.struct_offset; memcpy(dst, src, socket.size()); + + if (socket.type == SocketType::NODE) { + Node *node = get_socket_value(this, socket); + + if (node) { + node->reference(); + } + } } } @@ -773,6 +789,26 @@ void Node::set_owner(const NodeOwner *owner_) owner = owner_; } +void Node::dereference_all_used_nodes() +{ + foreach (const SocketType &socket, type->inputs) { + if (socket.type == SocketType::NODE) { + Node *node = get_socket_value(this, socket); + + if (node) { + node->dereference(); + } + } + else if (socket.type == SocketType::NODE_ARRAY) { + const array &nodes = get_socket_value>(this, socket); + + for (Node *node : nodes) { + node->dereference(); + } + } + } +} + bool Node::socket_is_modified(const SocketType &input) const { return (socket_modified & input.modified_flag_bit) != 0; @@ -803,6 +839,25 @@ template void Node::set_if_different(const SocketType &input, T valu socket_modified |= input.modified_flag_bit; } +void Node::set_if_different(const SocketType &input, Node *value) +{ + if (get_socket_value(this, input) == value) { + return; + } + + Node *old_node = get_socket_value(this, input); + if (old_node) { + old_node->dereference(); + } + + if (value) { + value->reference(); + } + + get_socket_value(this, input) = value; + socket_modified |= input.modified_flag_bit; +} + template void Node::set_if_different(const SocketType &input, array &value) { if (!socket_is_modified(input)) { @@ -815,6 +870,27 @@ template void Node::set_if_different(const SocketType &input, array< socket_modified |= input.modified_flag_bit; } +void Node::set_if_different(const SocketType &input, array &value) +{ + if (!socket_is_modified(input)) { + if (get_socket_value>(this, input) == value) { + return; + } + } + + array &old_nodes = get_socket_value>(this, input); + for (Node *old_node : old_nodes) { + old_node->dereference(); + } + + for (Node *new_node : value) { + new_node->reference(); + } + + get_socket_value>(this, input).steal_data(value); + socket_modified |= input.modified_flag_bit; +} + void Node::print_modified_sockets() const { printf("Node : %s\n", name.c_str()); -- cgit v1.2.3