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>2021-11-03 12:54:17 +0300
committerJacques Lucke <jacques@blender.org>2021-11-03 12:54:17 +0300
commitb55bddde40db3eda3531d98caa99be9a8e88a8ee (patch)
tree1a4688fba2f4ecb68ad6e4838da6895da352ed1d /source/blender/modifiers
parent2b12b4cd7dccfa51cec53d5ae885a2142563fb17 (diff)
Fix T91862: do type conversion when data enters or exists node group
The geometry node evaluator now has access to the entire socket path from the node that produces a value to the node that uses it. This allows the evaluator to make decisions about at which points in the path the value should be converted. Multiple conversions may be necessary under some circumstances with nested node groups. Differential Revision: https://developer.blender.org/D13034
Diffstat (limited to 'source/blender/modifiers')
-rw-r--r--source/blender/modifiers/intern/MOD_nodes_evaluator.cc111
1 files changed, 54 insertions, 57 deletions
diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
index a312872f5d9..70d2bd9c7f5 100644
--- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
+++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
@@ -568,15 +568,15 @@ class GeometryNodesEvaluator {
}
/* Count the number of potential users for this socket. */
socket.foreach_target_socket(
- [&, this](const DInputSocket target_socket) {
+ [&, this](const DInputSocket target_socket,
+ const DOutputSocket::TargetSocketPathInfo &UNUSED(path_info)) {
const DNode target_node = target_socket.node();
if (!this->node_states_.contains_as(target_node)) {
/* The target node is not computed because it is not computed to the output. */
return;
}
output_state.potential_users += 1;
- },
- {});
+ });
if (output_state.potential_users == 0) {
/* If it does not have any potential users, it is unused. It might become required again in
* `schedule_initial_nodes`. */
@@ -1257,43 +1257,61 @@ class GeometryNodesEvaluator {
{
BLI_assert(value_to_forward.get() != nullptr);
- Vector<DSocket> sockets_to_log_to;
- sockets_to_log_to.append(from_socket);
-
- Vector<DInputSocket> to_sockets;
- auto handle_target_socket_fn = [&, this](const DInputSocket to_socket) {
- if (this->should_forward_to_socket(to_socket)) {
- to_sockets.append(to_socket);
- }
- };
- auto handle_skipped_socket_fn = [&](const DSocket socket) {
- sockets_to_log_to.append(socket);
- };
- from_socket.foreach_target_socket(handle_target_socket_fn, handle_skipped_socket_fn);
-
LinearAllocator<> &allocator = local_allocators_.local();
- const CPPType &from_type = *value_to_forward.type();
- Vector<DInputSocket> to_sockets_same_type;
- for (const DInputSocket &to_socket : to_sockets) {
- const CPPType &to_type = *get_socket_cpp_type(to_socket);
- if (from_type == to_type) {
- /* All target sockets that do not need a conversion will be handled afterwards. */
- to_sockets_same_type.append(to_socket);
- /* Multi input socket values are logged once all values are available. */
- if (!to_socket->is_multi_input_socket()) {
- sockets_to_log_to.append(to_socket);
- }
- continue;
- }
- this->forward_to_socket_with_different_type(
- allocator, value_to_forward, from_socket, to_socket, to_type);
- }
-
- this->log_socket_value(sockets_to_log_to, value_to_forward);
+ Vector<DSocket> log_original_value_sockets;
+ Vector<DInputSocket> forward_original_value_sockets;
+ log_original_value_sockets.append(from_socket);
+ from_socket.foreach_target_socket(
+ [&](const DInputSocket to_socket, const DOutputSocket::TargetSocketPathInfo &path_info) {
+ if (!this->should_forward_to_socket(to_socket)) {
+ return;
+ }
+ BLI_assert(to_socket == path_info.sockets.last());
+ GMutablePointer current_value = value_to_forward;
+ for (const DSocket &next_socket : path_info.sockets) {
+ const DNode next_node = next_socket.node();
+ const bool is_last_socket = to_socket == next_socket;
+ const bool do_conversion_if_necessary = is_last_socket ||
+ next_node->is_group_output_node() ||
+ (next_node->is_group_node() &&
+ !next_node->is_muted());
+ if (do_conversion_if_necessary) {
+ const CPPType &next_type = *get_socket_cpp_type(next_socket);
+ if (*current_value.type() != next_type) {
+ void *buffer = allocator.allocate(next_type.size(), next_type.alignment());
+ this->convert_value(*current_value.type(), next_type, current_value.get(), buffer);
+ if (current_value.get() != value_to_forward.get()) {
+ current_value.destruct();
+ }
+ current_value = {next_type, buffer};
+ }
+ }
+ if (current_value.get() == value_to_forward.get()) {
+ /* Log the original value at the current socket. */
+ log_original_value_sockets.append(next_socket);
+ }
+ else {
+ /* Multi-input sockets are logged when all values are available. */
+ if (!(next_socket->is_input() && next_socket->as_input().is_multi_input_socket())) {
+ /* Log the converted value at the socket. */
+ this->log_socket_value({next_socket}, current_value);
+ }
+ }
+ }
+ if (current_value.get() == value_to_forward.get()) {
+ /* The value has not been converted, so forward the original value. */
+ forward_original_value_sockets.append(to_socket);
+ }
+ else {
+ /* The value has been converted. */
+ this->add_value_to_input_socket(to_socket, from_socket, current_value);
+ }
+ });
+ this->log_socket_value(log_original_value_sockets, value_to_forward);
this->forward_to_sockets_with_same_type(
- allocator, to_sockets_same_type, value_to_forward, from_socket);
+ allocator, forward_original_value_sockets, value_to_forward, from_socket);
}
bool should_forward_to_socket(const DInputSocket socket)
@@ -1312,27 +1330,6 @@ class GeometryNodesEvaluator {
return target_input_state.usage != ValueUsage::Unused;
}
- void forward_to_socket_with_different_type(LinearAllocator<> &allocator,
- const GPointer value_to_forward,
- const DOutputSocket from_socket,
- const DInputSocket to_socket,
- const CPPType &to_type)
- {
- const CPPType &from_type = *value_to_forward.type();
-
- /* Allocate a buffer for the converted value. */
- void *buffer = allocator.allocate(to_type.size(), to_type.alignment());
- GMutablePointer value{to_type, buffer};
-
- this->convert_value(from_type, to_type, value_to_forward.get(), buffer);
-
- /* Multi input socket values are logged once all values are available. */
- if (!to_socket->is_multi_input_socket()) {
- this->log_socket_value({to_socket}, value);
- }
- this->add_value_to_input_socket(to_socket, from_socket, value);
- }
-
void forward_to_sockets_with_same_type(LinearAllocator<> &allocator,
Span<DInputSocket> to_sockets,
GMutablePointer value_to_forward,