From 4c46203cb52ed37694709cc42aa6ca76ed24fe7a Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Sat, 1 Jan 2022 12:50:48 +0100 Subject: Geometry Nodes: small refactor towards supporting partially lazy nodes Currently, a node either supports lazyness during execution (like the Switch node), or it doesn't. If it does support lazyness, then every input is computed lazily. However, usually not all inputs actually have to be computed lazily. E.g. the boolean switch input is always required, while the other inputs should be computed lazily. Better support for such sockets can avoid unnecessary round trips through the node execution function. --- .../modifiers/intern/MOD_nodes_evaluator.cc | 31 +++++++++++++++------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'source/blender') diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc index 89987f261db..6b79c9e0f68 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc @@ -235,9 +235,10 @@ struct NodeState { MutableSpan outputs; /** - * Nodes that don't support laziness have some special handling the first time they are executed. + * Most nodes have inputs that are always required. Those have special handling to avoid an extra + * call to the node execution function. */ - bool non_lazy_node_is_initialized = false; + bool non_lazy_inputs_handled = false; /** * Used to check that nodes that don't support laziness do not run more than once. @@ -801,12 +802,12 @@ class GeometryNodesEvaluator { if (!this->prepare_node_outputs_for_execution(locked_node)) { return; } - /* Initialize nodes that don't support laziness. This is done after at least one output is + /* Initialize inputs that don't support laziness. This is done after at least one output is * required and before we check that all required inputs are provided. This reduces the * number of "round-trips" through the task pool by one for most nodes. */ - if (!node_state.non_lazy_node_is_initialized && !node_supports_laziness(node)) { - this->initialize_non_lazy_node(locked_node); - node_state.non_lazy_node_is_initialized = true; + if (!node_state.non_lazy_inputs_handled) { + this->require_non_lazy_inputs(locked_node); + node_state.non_lazy_inputs_handled = true; } /* Prepare inputs and check if all required inputs are provided. */ if (!this->prepare_node_inputs_for_execution(locked_node)) { @@ -880,17 +881,27 @@ class GeometryNodesEvaluator { return execution_is_necessary; } - void initialize_non_lazy_node(LockedNode &locked_node) + void require_non_lazy_inputs(LockedNode &locked_node) { + this->foreach_non_lazy_input(locked_node, [&](const DInputSocket socket) { + this->set_input_required(locked_node, socket); + }); + } + + void foreach_non_lazy_input(LockedNode &locked_node, FunctionRef fn) + { + if (node_supports_laziness(locked_node.node)) { + /* In the future only some of the inputs may support lazyness. */ + return; + } + /* Nodes that don't support laziness require all inputs. */ for (const int i : locked_node.node->inputs().index_range()) { InputState &input_state = locked_node.node_state.inputs[i]; if (input_state.type == nullptr) { /* Ignore unavailable/non-data sockets. */ continue; } - /* Nodes that don't support laziness require all inputs. */ - const DInputSocket input_socket = locked_node.node.input(i); - this->set_input_required(locked_node, input_socket); + fn(locked_node.node.input(i)); } } -- cgit v1.2.3