diff --git a/source/blender/functions/intern/lazy_function_graph_executor.cc b/source/blender/functions/intern/lazy_function_graph_executor.cc index 080c2d0fe8a..69780881f16 100644 --- a/source/blender/functions/intern/lazy_function_graph_executor.cc +++ b/source/blender/functions/intern/lazy_function_graph_executor.cc @@ -1503,17 +1503,13 @@ void GraphExecutor::destruct_storage(void *storage) const std::string GraphExecutor::input_name(const int index) const { const lf::OutputSocket &socket = *graph_inputs_[index]; - std::stringstream ss; - ss << socket.node().name() << " - " << socket.name(); - return ss.str(); + return socket.name(); } std::string GraphExecutor::output_name(const int index) const { const lf::InputSocket &socket = *graph_outputs_[index]; - std::stringstream ss; - ss << socket.node().name() << " - " << socket.name(); - return ss.str(); + return socket.name(); } void GraphExecutorLogger::log_socket_value(const Socket &socket, diff --git a/source/blender/nodes/NOD_geometry_nodes_lazy_function.hh b/source/blender/nodes/NOD_geometry_nodes_lazy_function.hh index daad4fd3be4..af3f0bb9564 100644 --- a/source/blender/nodes/NOD_geometry_nodes_lazy_function.hh +++ b/source/blender/nodes/NOD_geometry_nodes_lazy_function.hh @@ -252,36 +252,11 @@ struct InputUsageHint { * This is *not* a one-to-one mapping. */ struct GeometryNodeLazyFunctionGraphMapping { - /** - * The inputs sockets in the graph. Multiple group input nodes are combined into one in the - * lazy-function graph. - */ - Vector group_input_sockets; - /** - * Interface output sockets that correspond to the active group output node. If there is no such - * node, defaulted fallback outputs are created. - */ - Vector standard_group_output_sockets; - /** - * Interface boolean sockets that have to be passed in from the outside and indicate whether a - * specific output will be used. - */ - Vector group_output_used_sockets; - /** - * Interface boolean sockets that can be used as group output that indicate whether a specific - * input will be used (this may depend on the used outputs as well as other inputs). - */ - Vector group_input_usage_sockets; /** * This is an optimization to avoid partially evaluating a node group just to figure out which * inputs are needed. */ Vector group_input_usage_hints; - /** - * If the node group propagates attributes from an input geometry to the output, it has to know - * which attributes should be propagated and which can be removed (for optimization purposes). - */ - Map attribute_set_by_geometry_output; /** * A mapping used for logging intermediate values. */ @@ -302,6 +277,52 @@ struct GeometryNodeLazyFunctionGraphMapping { Array lf_index_by_bsocket; }; +/** + * Contains the information that is necessary to execute a geometry node tree. + */ +struct GeometryNodesGroupFunction { + /** + * The lazy-function that does what the node group does. Its inputs and outputs are described + * below. + */ + const LazyFunction *function = nullptr; + + struct { + /** + * Main input values that come out of the Group Input node. + */ + IndexRange main; + /** + * A boolean for every group output that indicates whether that output is needed. It's ok if + * those are set to true even when an output is not used, but the other way around will lead to + * bugs. The node group uses those values to compute the lifetimes of anonymous attributes. + */ + IndexRange output_usages; + /** + * Some node groups can propagate attributes from a geometry input to a geometry output. In + * those cases, the caller of the node group has to decide which anonymous attributes have to + * be kept alive on the geometry because the caller requires them. + */ + struct { + IndexRange range; + Vector geometry_outputs; + } attributes_to_propagate; + } inputs; + + struct { + /** + * Main output values that are passed into the Group Output node. + */ + IndexRange main; + /** + * A boolean for every group input that indicates whether this input will be used. Oftentimes + * this can be determined without actually computing much. This is used to compute anonymous + * attribute lifetimes. + */ + IndexRange input_usages; + } outputs; +}; + /** * Data that is cached for every #bNodeTree. */ @@ -310,6 +331,7 @@ struct GeometryNodesLazyFunctionGraphInfo { * Contains resources that need to be freed when the graph is not needed anymore. */ ResourceScope scope; + GeometryNodesGroupFunction function; /** * The actual lazy-function graph. */ diff --git a/source/blender/nodes/intern/geometry_nodes_execute.cc b/source/blender/nodes/intern/geometry_nodes_execute.cc index ee27e2030c4..c0bc0bc84c1 100644 --- a/source/blender/nodes/intern/geometry_nodes_execute.cc +++ b/source/blender/nodes/intern/geometry_nodes_execute.cc @@ -569,29 +569,22 @@ bke::GeometrySet execute_geometry_nodes_on_geometry( { const nodes::GeometryNodesLazyFunctionGraphInfo &lf_graph_info = *nodes::ensure_geometry_nodes_lazy_function_graph(btree); - const nodes::GeometryNodeLazyFunctionGraphMapping &mapping = lf_graph_info.mapping; + const GeometryNodesGroupFunction &function = lf_graph_info.function; + const lf::LazyFunction &lazy_function = *function.function; + const int num_inputs = lazy_function.inputs().size(); + const int num_outputs = lazy_function.outputs().size(); - Vector graph_inputs = mapping.group_input_sockets; - graph_inputs.extend(mapping.group_output_used_sockets); - graph_inputs.extend(mapping.attribute_set_by_geometry_output.values().begin(), - mapping.attribute_set_by_geometry_output.values().end()); - Vector graph_outputs = mapping.standard_group_output_sockets; + Array param_inputs(num_inputs); + Array param_outputs(num_outputs); + Array> param_input_usages(num_inputs); + Array param_output_usages(num_outputs); + Array param_set_outputs(num_outputs, false); - Array param_inputs(graph_inputs.size()); - Array param_outputs(graph_outputs.size()); - Array> param_input_usages(graph_inputs.size()); - Array param_output_usages(graph_outputs.size(), lf::ValueUsage::Used); - Array param_set_outputs(graph_outputs.size(), false); - - nodes::GeometryNodesLazyFunctionLogger lf_logger(lf_graph_info); - nodes::GeometryNodesLazyFunctionSideEffectProvider lf_side_effect_provider; - - lf::GraphExecutor graph_executor{lf_graph_info.graph, - graph_inputs, - graph_outputs, - &lf_logger, - &lf_side_effect_provider, - nullptr}; + /* We want to evaluate the main outputs, but don't care about which inputs are used for now. */ + param_output_usages.as_mutable_span().slice(function.outputs.main).fill(lf::ValueUsage::Used); + param_output_usages.as_mutable_span() + .slice(function.outputs.input_usages) + .fill(lf::ValueUsage::Unused); nodes::GeoNodesLFUserData user_data; fill_user_data(user_data); @@ -602,15 +595,15 @@ bke::GeometrySet execute_geometry_nodes_on_geometry( Vector inputs_to_destruct; btree.ensure_interface_cache(); - int input_index = -1; + + /* Prepare main inputs. */ for (const int i : btree.interface_inputs().index_range()) { - input_index++; const bNodeTreeInterfaceSocket &interface_socket = *btree.interface_inputs()[i]; const bNodeSocketType *typeinfo = interface_socket.socket_typeinfo(); const eNodeSocketDatatype socket_type = typeinfo ? eNodeSocketDatatype(typeinfo->type) : SOCK_CUSTOM; - if (socket_type == SOCK_GEOMETRY && input_index == 0) { - param_inputs[input_index] = &input_geometry; + if (socket_type == SOCK_GEOMETRY && i == 0) { + param_inputs[function.inputs.main[0]] = &input_geometry; continue; } @@ -618,41 +611,42 @@ bke::GeometrySet execute_geometry_nodes_on_geometry( BLI_assert(type != nullptr); void *value = allocator.allocate(type->size(), type->alignment()); initialize_group_input(btree, properties, i, value); - param_inputs[input_index] = {type, value}; + param_inputs[function.inputs.main[i]] = {type, value}; inputs_to_destruct.append({type, value}); } + /* Prepare used-outputs inputs. */ Array output_used_inputs(btree.interface_outputs().size(), true); for (const int i : btree.interface_outputs().index_range()) { - input_index++; - param_inputs[input_index] = &output_used_inputs[i]; + param_inputs[function.inputs.output_usages[i]] = &output_used_inputs[i]; } + /* No anonymous attributes have to be propagated. */ Array attributes_to_propagate( - mapping.attribute_set_by_geometry_output.size()); + function.inputs.attributes_to_propagate.geometry_outputs.size()); for (const int i : attributes_to_propagate.index_range()) { - input_index++; - param_inputs[input_index] = &attributes_to_propagate[i]; + param_inputs[function.inputs.attributes_to_propagate.range[i]] = &attributes_to_propagate[i]; } - for (const int i : graph_outputs.index_range()) { - const lf::GraphOutputSocket &socket = *graph_outputs[i]; - const CPPType &type = socket.type(); + /* Prepare memory for output values. */ + for (const int i : IndexRange(num_outputs)) { + const lf::Output &lf_output = lazy_function.outputs()[i]; + const CPPType &type = *lf_output.type; void *buffer = allocator.allocate(type.size(), type.alignment()); param_outputs[i] = {type, buffer}; } nodes::GeoNodesLFLocalUserData local_user_data(user_data); - lf::Context lf_context(graph_executor.init_storage(allocator), &user_data, &local_user_data); - lf::BasicParams lf_params{graph_executor, + lf::Context lf_context(lazy_function.init_storage(allocator), &user_data, &local_user_data); + lf::BasicParams lf_params{lazy_function, param_inputs, param_outputs, param_input_usages, param_output_usages, param_set_outputs}; - graph_executor.execute(lf_params, lf_context); - graph_executor.destruct_storage(lf_context.storage); + lazy_function.execute(lf_params, lf_context); + lazy_function.destruct_storage(lf_context.storage); for (GMutablePointer &ptr : inputs_to_destruct) { ptr.destruct(); @@ -661,8 +655,11 @@ bke::GeometrySet execute_geometry_nodes_on_geometry( bke::GeometrySet output_geometry = std::move(*param_outputs[0].get()); store_output_attributes(output_geometry, btree, properties, param_outputs); - for (GMutablePointer &ptr : param_outputs) { - ptr.destruct(); + for (const int i : IndexRange(num_outputs)) { + if (param_set_outputs[i]) { + GMutablePointer &ptr = param_outputs[i]; + ptr.destruct(); + } } return output_geometry; diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc index a1626d45edf..fdc7bb61acb 100644 --- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc +++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc @@ -928,89 +928,49 @@ class LazyFunctionForSimulationInputsUsage : public LazyFunction { class LazyFunctionForGroupNode : public LazyFunction { private: const bNode &group_node_; - const GeometryNodesLazyFunctionGraphInfo &own_lf_graph_info_; + const LazyFunction &group_lazy_function_; bool has_many_nodes_ = false; - std::optional lf_logger_; - std::optional lf_side_effect_provider_; - std::optional graph_executor_; struct Storage { - void *graph_executor_storage = nullptr; + void *group_storage = nullptr; /* To avoid computing the hash more than once. */ std::optional context_hash_cache; }; public: - /** - * For every input bsocket there is a corresponding boolean output that indicates whether that - * input is used. - */ - Map lf_output_for_input_bsocket_usage_; - LazyFunctionForGroupNode(const bNode &group_node, const GeometryNodesLazyFunctionGraphInfo &group_lf_graph_info, GeometryNodesLazyFunctionGraphInfo &own_lf_graph_info) - : group_node_(group_node), own_lf_graph_info_(own_lf_graph_info) + : group_node_(group_node), group_lazy_function_(*group_lf_graph_info.function.function) { debug_name_ = group_node.name; allow_missing_requested_inputs_ = true; - lazy_function_interface_from_node( - group_node, inputs_, outputs_, own_lf_graph_info.mapping.lf_index_by_bsocket); - for (lf::Input &input : inputs_) { - input.usage = lf::ValueUsage::Maybe; - } + /* This wrapper has the same interface as the actual underlying node group. */ + inputs_ = group_lf_graph_info.function.function->inputs(); + outputs_ = group_lf_graph_info.function.function->outputs(); has_many_nodes_ = group_lf_graph_info.num_inline_nodes_approximate > 1000; - Vector graph_inputs; - /* Add inputs that also exist on the bnode. */ - graph_inputs.extend(group_lf_graph_info.mapping.group_input_sockets); - /* Add a boolean input for every output bsocket that indicates whether that socket is used. */ for (const int i : group_node.output_sockets().index_range()) { own_lf_graph_info.mapping.lf_input_index_for_output_bsocket_usage - [group_node.output_socket(i).index_in_all_outputs()] = graph_inputs.append_and_get_index( - group_lf_graph_info.mapping.group_output_used_sockets[i]); - inputs_.append_as("Output is Used", CPPType::get(), lf::ValueUsage::Maybe); + [group_node.output_socket(i).index_in_all_outputs()] = + group_lf_graph_info.function.inputs.output_usages[i]; } /* Add an attribute set input for every output geometry socket that can propagate attributes * from inputs. */ - for (auto [output_index, lf_socket] : - group_lf_graph_info.mapping.attribute_set_by_geometry_output.items()) + for (const int i : group_lf_graph_info.function.inputs.attributes_to_propagate.geometry_outputs + .index_range()) { - const int lf_index = inputs_.append_and_get_index_as( - "Attribute Set", CPPType::get(), lf::ValueUsage::Maybe); - graph_inputs.append(lf_socket); + const int lf_index = group_lf_graph_info.function.inputs.attributes_to_propagate.range[i]; + const int output_index = + group_lf_graph_info.function.inputs.attributes_to_propagate.geometry_outputs[i]; + const bNodeSocket &output_bsocket = group_node_.output_socket(output_index); own_lf_graph_info.mapping.lf_input_index_for_attribute_propagation_to_output - [group_node_.output_socket(output_index).index_in_all_outputs()] = lf_index; + [output_bsocket.index_in_all_outputs()] = lf_index; } - - Vector graph_outputs; - /* Add outputs that also exist on the bnode. */ - graph_outputs.extend(group_lf_graph_info.mapping.standard_group_output_sockets); - /* Add a boolean output for every input bsocket that indicates whether that socket is used. */ - for (const int i : group_node.input_sockets().index_range()) { - const InputUsageHint &input_usage_hint = - group_lf_graph_info.mapping.group_input_usage_hints[i]; - if (input_usage_hint.type == InputUsageHintType::DynamicSocket) { - const lf::InputSocket *lf_socket = - group_lf_graph_info.mapping.group_input_usage_sockets[i]; - lf_output_for_input_bsocket_usage_.add_new(i, - graph_outputs.append_and_get_index(lf_socket)); - outputs_.append_as("Input is Used", CPPType::get()); - } - } - - lf_logger_.emplace(group_lf_graph_info); - lf_side_effect_provider_.emplace(); - graph_executor_.emplace(group_lf_graph_info.graph, - std::move(graph_inputs), - std::move(graph_outputs), - &*lf_logger_, - &*lf_side_effect_provider_, - nullptr); } void execute_impl(lf::Params ¶ms, const lf::Context &context) const override @@ -1040,23 +1000,22 @@ class LazyFunctionForGroupNode : public LazyFunction { GeoNodesLFLocalUserData group_local_user_data{group_user_data}; - lf::Context group_context{ - storage->graph_executor_storage, &group_user_data, &group_local_user_data}; + lf::Context group_context{storage->group_storage, &group_user_data, &group_local_user_data}; - graph_executor_->execute(params, group_context); + group_lazy_function_.execute(params, group_context); } void *init_storage(LinearAllocator<> &allocator) const override { Storage *s = allocator.construct().release(); - s->graph_executor_storage = graph_executor_->init_storage(allocator); + s->group_storage = group_lazy_function_.init_storage(allocator); return s; } void destruct_storage(void *storage) const override { Storage *s = static_cast(storage); - graph_executor_->destruct_storage(s->graph_executor_storage); + group_lazy_function_.destruct_storage(s->group_storage); std::destroy_at(s); } @@ -1067,43 +1026,12 @@ class LazyFunctionForGroupNode : public LazyFunction { std::string input_name(const int i) const override { - if (i < group_node_.input_sockets().size()) { - return group_node_.input_socket(i).name; - } - for (const bNodeSocket *bsocket : group_node_.output_sockets()) { - { - const int lf_index = - own_lf_graph_info_.mapping - .lf_input_index_for_output_bsocket_usage[bsocket->index_in_all_outputs()]; - if (i == lf_index) { - return StringRef("Use Output '") + bsocket->identifier + "'"; - } - } - { - const int lf_index = - own_lf_graph_info_.mapping.lf_input_index_for_attribute_propagation_to_output - [bsocket->index_in_all_outputs()]; - if (i == lf_index) { - return StringRef("Propagate to '") + bsocket->identifier + "'"; - } - } - } - return inputs_[i].debug_name; + return group_lazy_function_.input_name(i); } std::string output_name(const int i) const override { - if (i < group_node_.output_sockets().size()) { - return group_node_.output_socket(i).name; - } - for (const auto [bsocket_index, lf_socket_index] : lf_output_for_input_bsocket_usage_.items()) - { - if (i == lf_socket_index) { - return fmt::format(TIP_("'{}' input is used"), - group_node_.input_socket(bsocket_index).name); - } - } - return outputs_[i].debug_name; + return group_lazy_function_.output_name(i); } }; @@ -1736,11 +1664,11 @@ class LazyFunctionForRepeatZone : public LazyFunction { }; /** - * Utility class to build a lazy-function graph based on a geometry nodes tree. + * Utility class to build a lazy-function based on a geometry nodes tree. * This is mainly a separate class because it makes it easier to have variables that can be * accessed by many functions. */ -struct GeometryNodesLazyFunctionGraphBuilder { +struct GeometryNodesLazyFunctionBuilder { private: const bNodeTree &btree_; const aai::AnonymousAttributeInferencingResult &attribute_inferencing_; @@ -1758,11 +1686,37 @@ struct GeometryNodesLazyFunctionGraphBuilder { const bNodeTreeZones *tree_zones_; MutableSpan zone_build_infos_; + /** + * The inputs sockets in the graph. Multiple group input nodes are combined into one in the + * lazy-function graph. + */ + Vector group_input_sockets_; + /** + * Interface output sockets that correspond to the active group output node. If there is no such + * node, defaulted fallback outputs are created. + */ + Vector standard_group_output_sockets_; + /** + * Interface boolean sockets that have to be passed in from the outside and indicate whether a + * specific output will be used. + */ + Vector group_output_used_sockets_; + /** + * Interface boolean sockets that can be used as group output that indicate whether a specific + * input will be used (this may depend on the used outputs as well as other inputs). + */ + Vector group_input_usage_sockets_; + /** + * If the node group propagates attributes from an input geometry to the output, it has to know + * which attributes should be propagated and which can be removed (for optimization purposes). + */ + Map attribute_set_by_geometry_output_; + friend class UsedSocketVisualizeOptions; public: - GeometryNodesLazyFunctionGraphBuilder(const bNodeTree &btree, - GeometryNodesLazyFunctionGraphInfo &lf_graph_info) + GeometryNodesLazyFunctionBuilder(const bNodeTree &btree, + GeometryNodesLazyFunctionGraphInfo &lf_graph_info) : btree_(btree), attribute_inferencing_(*btree.runtime->anonymous_attribute_inferencing), scope_(lf_graph_info.scope), @@ -1783,6 +1737,7 @@ struct GeometryNodesLazyFunctionGraphBuilder { this->initialize_mapping_arrays(); this->build_zone_functions(); this->build_root_graph(); + this->build_geometry_nodes_group_function(); } private: @@ -2255,14 +2210,14 @@ struct GeometryNodesLazyFunctionGraphBuilder { for (const bNodeTreeInterfaceSocket *interface_input : btree_.interface_inputs()) { lf::GraphOutputSocket &lf_socket = lf_graph.add_output( CPPType::get(), StringRef("Usage: ") + interface_input->name); - mapping_->group_input_usage_sockets.append(&lf_socket); + group_input_usage_sockets_.append(&lf_socket); } Vector lf_output_usages; for (const bNodeTreeInterfaceSocket *interface_output : btree_.interface_outputs()) { lf::GraphInputSocket &lf_socket = lf_graph.add_input( CPPType::get(), StringRef("Usage: ") + interface_output->name); - mapping_->group_output_used_sockets.append(&lf_socket); + group_output_used_sockets_.append(&lf_socket); lf_output_usages.append(&lf_socket); } @@ -2303,6 +2258,48 @@ struct GeometryNodesLazyFunctionGraphBuilder { lf_graph_info_->num_inline_nodes_approximate += lf_graph.nodes().size(); } + /** + * Build a lazy-function from the generated graph. This is then the lazy-function that must be + * executed by others to run a geometry node group. + */ + void build_geometry_nodes_group_function() + { + GeometryNodesGroupFunction &function = lf_graph_info_->function; + + Vector lf_graph_inputs; + Vector lf_graph_outputs; + + lf_graph_inputs.extend(group_input_sockets_); + function.inputs.main = lf_graph_inputs.index_range().take_back(group_input_sockets_.size()); + + lf_graph_inputs.extend(group_output_used_sockets_); + function.inputs.output_usages = lf_graph_inputs.index_range().take_back( + group_output_used_sockets_.size()); + + for (auto [output_index, lf_socket] : attribute_set_by_geometry_output_.items()) { + lf_graph_inputs.append(lf_socket); + function.inputs.attributes_to_propagate.geometry_outputs.append(output_index); + } + function.inputs.attributes_to_propagate.range = lf_graph_inputs.index_range().take_back( + attribute_set_by_geometry_output_.size()); + + lf_graph_outputs.extend(standard_group_output_sockets_); + function.outputs.main = lf_graph_outputs.index_range().take_back( + standard_group_output_sockets_.size()); + + lf_graph_outputs.extend(group_input_usage_sockets_); + function.outputs.input_usages = lf_graph_outputs.index_range().take_back( + group_input_usage_sockets_.size()); + + function.function = &scope_.construct( + lf_graph_info_->graph, + std::move(lf_graph_inputs), + std::move(lf_graph_outputs), + &scope_.construct(*lf_graph_info_), + &scope_.construct(), + nullptr); + } + void build_attribute_set_inputs_outside_of_zones( BuildGraphParams &graph_params, Map &lf_attribute_set_by_field_source_index, @@ -2320,9 +2317,9 @@ struct GeometryNodesLazyFunctionGraphBuilder { { const int input_index = input_field_source->input_index; lf::OutputSocket &lf_field_socket = const_cast( - *mapping_->group_input_sockets[input_index]); + *group_input_sockets_[input_index]); lf::OutputSocket *lf_usage_socket = const_cast( - mapping_->group_input_usage_sockets[input_index]->origin()); + group_input_usage_sockets_[input_index]->origin()); lf_attribute_set_socket = &this->get_extracted_attributes( lf_field_socket, lf_usage_socket, @@ -2350,7 +2347,7 @@ struct GeometryNodesLazyFunctionGraphBuilder { const int group_output_index = attribute_inferencing_.propagated_output_geometry_indices[caller_propagation_index]; lf::OutputSocket &lf_attribute_set_socket = const_cast( - *mapping_->attribute_set_by_geometry_output.lookup(group_output_index)); + *attribute_set_by_geometry_output_.lookup(group_output_index)); lf_attribute_set_by_caller_propagation_index.add(caller_propagation_index, &lf_attribute_set_socket); } @@ -2669,7 +2666,7 @@ struct GeometryNodesLazyFunctionGraphBuilder { const bNodeSocketType *typeinfo = interface_input->socket_typeinfo(); lf::GraphInputSocket &lf_socket = lf_graph.add_input(*typeinfo->geometry_nodes_cpp_type, interface_input->name); - mapping_->group_input_sockets.append(&lf_socket); + group_input_sockets_.append(&lf_socket); } } @@ -2684,7 +2681,7 @@ struct GeometryNodesLazyFunctionGraphBuilder { const CPPType &type = *typeinfo->geometry_nodes_cpp_type; lf::GraphOutputSocket &lf_socket = lf_graph.add_output(type, interface_output->name); lf_socket.set_default_value(type.default_value()); - mapping_->standard_group_output_sockets.append(&lf_socket); + standard_group_output_sockets_.append(&lf_socket); } } @@ -2834,7 +2831,7 @@ struct GeometryNodesLazyFunctionGraphBuilder { for (const int i : btree_.interface_inputs().index_range()) { const bNodeSocket &bsocket = bnode.output_socket(i); lf::GraphInputSocket &lf_socket = *const_cast( - mapping_->group_input_sockets[i]); + group_input_sockets_[i]); graph_params.lf_output_by_bsocket.add_new(&bsocket, &lf_socket); mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket); } @@ -2857,7 +2854,7 @@ struct GeometryNodesLazyFunctionGraphBuilder { } if (&bnode == btree_.group_output_node()) { - mapping_->standard_group_output_sockets = lf_graph_outputs.as_span(); + standard_group_output_sockets_ = lf_graph_outputs.as_span(); } } @@ -2915,28 +2912,18 @@ struct GeometryNodesLazyFunctionGraphBuilder { } } - this->build_group_node_socket_usage(bnode, lf_node, graph_params); + this->build_group_node_socket_usage(bnode, lf_node, graph_params, *group_lf_graph_info); } void build_group_node_socket_usage(const bNode &bnode, lf::FunctionNode &lf_group_node, - BuildGraphParams &graph_params) + BuildGraphParams &graph_params, + const GeometryNodesLazyFunctionGraphInfo &group_lf_graph_info) { - const bNodeTree *bgroup = reinterpret_cast(bnode.id); - if (bgroup == nullptr) { - return; - } - const GeometryNodesLazyFunctionGraphInfo *group_lf_graph_info = - ensure_geometry_nodes_lazy_function_graph(*bgroup); - if (group_lf_graph_info == nullptr) { - return; - } - const auto &fn = static_cast(lf_group_node.function()); - for (const bNodeSocket *input_bsocket : bnode.input_sockets()) { const int input_index = input_bsocket->index(); const InputUsageHint &input_usage_hint = - group_lf_graph_info->mapping.group_input_usage_hints[input_index]; + group_lf_graph_info.mapping.group_input_usage_hints[input_index]; switch (input_usage_hint.type) { case InputUsageHintType::Never: { /* Nothing to do. */ @@ -2958,7 +2945,8 @@ struct GeometryNodesLazyFunctionGraphBuilder { case InputUsageHintType::DynamicSocket: { graph_params.usage_by_bsocket.add( input_bsocket, - &lf_group_node.output(fn.lf_output_for_input_bsocket_usage_.lookup(input_index))); + &lf_group_node.output( + group_lf_graph_info.function.outputs.input_usages[input_index])); break; } } @@ -3516,7 +3504,7 @@ struct GeometryNodesLazyFunctionGraphBuilder { lf::GraphInputSocket &lf_socket = lf_graph.add_input( CPPType::get(), StringRef("Propagate: ") + btree_.interface_outputs()[output_index]->name); - mapping_->attribute_set_by_geometry_output.add(output_index, &lf_socket); + attribute_set_by_geometry_output_.add(output_index, &lf_socket); } } @@ -3587,7 +3575,7 @@ struct GeometryNodesLazyFunctionGraphBuilder { lf::OutputSocket *lf_socket = this->or_socket_usages(target_usages, graph_params); lf::InputSocket *lf_group_output = const_cast( - mapping_->group_input_usage_sockets[i]); + group_input_usage_sockets_[i]); InputUsageHint input_usage_hint; if (lf_socket == nullptr) { static const bool static_false = false; @@ -3601,7 +3589,7 @@ struct GeometryNodesLazyFunctionGraphBuilder { * the future. */ input_usage_hint.type = InputUsageHintType::DependsOnOutput; input_usage_hint.output_dependencies = { - mapping_->group_output_used_sockets.first_index_of(lf_socket)}; + group_output_used_sockets_.first_index_of(lf_socket)}; } else { input_usage_hint.type = InputUsageHintType::DynamicSocket; @@ -3793,7 +3781,7 @@ const GeometryNodesLazyFunctionGraphInfo *ensure_geometry_nodes_lazy_function_gr } auto lf_graph_info = std::make_unique(); - GeometryNodesLazyFunctionGraphBuilder builder{btree, *lf_graph_info}; + GeometryNodesLazyFunctionBuilder builder{btree, *lf_graph_info}; builder.build(); lf_graph_info_ptr = std::move(lf_graph_info);