diff options
author | Jacques Lucke <jacques@blender.org> | 2021-11-24 14:55:10 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-11-24 14:57:36 +0300 |
commit | 7ea4342e73c3b8d6323bb94096a1833ccbb309da (patch) | |
tree | 563cae28db95e4a20196fe339d6db44d07c17da3 /source/blender/modifiers/intern/MOD_nodes_evaluator.cc | |
parent | 833eb908200f3fa6e1cd605345a305ad04dbc10f (diff) |
Geometry Nodes: reduce number of scheduled nodes in evaluator
Previously, there were a couple of cases where nodes were scheduled when
that was not really necessary. This change doesn't seem to have a big impact
on performance, but simplifies the code a bit.
Diffstat (limited to 'source/blender/modifiers/intern/MOD_nodes_evaluator.cc')
-rw-r--r-- | source/blender/modifiers/intern/MOD_nodes_evaluator.cc | 46 |
1 files changed, 21 insertions, 25 deletions
diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc index 4af2caaaf7e..798942f71f5 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc @@ -1184,10 +1184,9 @@ class GeometryNodesEvaluator { /** * Load the required input from the socket or trigger nodes to the left to compute the value. - * When this function is called, the node will always be executed again eventually (either - * immediately, or when all required inputs have been computed by other nodes). + * \return True when the node will be triggered by another node again when the value is computed. */ - void set_input_required(LockedNode &locked_node, const DInputSocket input_socket) + bool set_input_required(LockedNode &locked_node, const DInputSocket input_socket) { BLI_assert(locked_node.node == input_socket.node()); InputState &input_state = locked_node.node_state.inputs[input_socket->index()]; @@ -1195,19 +1194,16 @@ class GeometryNodesEvaluator { /* Value set as unused cannot become used again. */ BLI_assert(input_state.usage != ValueUsage::Unused); - if (input_state.usage == ValueUsage::Required) { - /* The value is already required, but the node might expect to be evaluated again. */ - this->schedule_node(locked_node); - /* Returning here also ensure that the code below is executed at most once per input. */ - return; + if (input_state.was_ready_for_execution) { + return false; } - input_state.usage = ValueUsage::Required; - if (input_state.was_ready_for_execution) { - /* The value was already ready, but the node might expect to be evaluated again. */ - this->schedule_node(locked_node); - return; + if (input_state.usage == ValueUsage::Required) { + /* If the input was not ready for execution but is required, the node will be triggered again + * once the input has been computed. */ + return true; } + input_state.usage = ValueUsage::Required; /* Count how many values still have to be added to this input until it is "complete". */ int missing_values = 0; @@ -1222,9 +1218,7 @@ class GeometryNodesEvaluator { } } if (missing_values == 0) { - /* The input is fully available already, but the node might expect to be evaluated again. */ - this->schedule_node(locked_node); - return; + return false; } /* Increase the total number of missing required inputs. This ensures that the node will be * scheduled correctly when all inputs have been provided. */ @@ -1239,30 +1233,28 @@ class GeometryNodesEvaluator { /* If there are no origin sockets, just load the value from the socket directly. */ this->load_unlinked_input_value(locked_node, input_socket, input_state, input_socket); locked_node.node_state.missing_required_inputs -= 1; - this->schedule_node(locked_node); - return; + return false; } - bool will_be_triggered_by_other_node = false; + bool requested_from_other_node = false; for (const DSocket &origin_socket : origin_sockets) { if (origin_socket->is_input()) { /* Load the value directly from the origin socket. In most cases this is an unlinked * group input. */ this->load_unlinked_input_value(locked_node, input_socket, input_state, origin_socket); locked_node.node_state.missing_required_inputs -= 1; - this->schedule_node(locked_node); } else { /* The value has not been computed yet, so when it will be forwarded by another node, this * node will be triggered. */ - will_be_triggered_by_other_node = true; - + requested_from_other_node = true; locked_node.delayed_required_outputs.append(DOutputSocket(origin_socket)); } } /* If this node will be triggered by another node, we don't have to schedule it now. */ - if (!will_be_triggered_by_other_node) { - this->schedule_node(locked_node); + if (requested_from_other_node) { + return true; } + return false; } void set_input_unused(LockedNode &locked_node, const DInputSocket socket) @@ -1798,7 +1790,11 @@ bool NodeParamsProvider::lazy_require_input(StringRef identifier) return false; } evaluator_.with_locked_node(this->dnode, node_state_, [&](LockedNode &locked_node) { - evaluator_.set_input_required(locked_node, socket); + if (!evaluator_.set_input_required(locked_node, socket)) { + /* Schedule the currently executed node again because the value is available now but was not + * ready for the current execution. */ + evaluator_.schedule_node(locked_node); + } }); return true; } |