3497 const aai::AnonymousAttributeInferencingResult &attribute_inferencing_;
3512 std::optional<BuildGraphParams> root_graph_build_params_;
3546 attribute_inferencing_(*btree.runtime->anonymous_attribute_inferencing),
3547 scope_(lf_graph_info.scope),
3549 lf_graph_info_(&lf_graph_info)
3555 btree_.ensure_topology_cache();
3556 btree_.ensure_interface_cache();
3558 mapping_ = &lf_graph_info_->mapping;
3560 tree_zones_ = btree_.zones();
3562 this->initialize_mapping_arrays();
3563 this->build_zone_functions();
3564 this->build_root_graph();
3565 this->build_geometry_nodes_group_function();
3569 void initialize_mapping_arrays()
3572 btree_.all_output_sockets().size());
3575 btree_.all_output_sockets().size());
3584 void build_zone_functions()
3588 const Array<int> zone_build_order = this->compute_zone_build_order();
3590 for (
const int zone_i : zone_build_order) {
3594 this->build_simulation_zone_function(zone);
3598 this->build_repeat_zone_function(zone);
3602 this->build_foreach_geometry_element_zone_function(zone);
3612 Array<int> compute_zone_build_order()
3615 Array<int> zone_build_order(tree_zones_->zones.size());
3618 zone_build_order.begin(), zone_build_order.end(), [&](
const int zone_a,
const int zone_b) {
3619 return tree_zones_->zones[zone_a]->depth > tree_zones_->zones[zone_b]->depth;
3621 return zone_build_order;
3628 void build_simulation_zone_function(
const bNodeTreeZone &zone)
3630 const int zone_i = zone.
index;
3631 ZoneBuildInfo &zone_info = zone_build_infos_[zone_i];
3632 lf::Graph &lf_graph = scope_.construct<lf::Graph>();
3642 &lf_graph.
add_input(*bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name)));
3648 this->build_zone_border_links_inputs(
3649 zone, lf_graph, lf_zone_inputs, zone_info.indices.inputs.border_links);
3650 this->build_zone_border_link_input_usages(
3651 zone, lf_graph, lf_zone_outputs, zone_info.indices.outputs.border_link_usages);
3655 &lf_graph.
add_output(*bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name)));
3660 lf::Node &lf_simulation_usage_node = [&]() -> lf::Node & {
3661 auto &lazy_function = scope_.construct<LazyFunctionForSimulationInputsUsage>(
3663 lf::Node &lf_node = lf_graph.
add_function(lazy_function);
3665 for (
const int i : zone_info.indices.outputs.input_usages) {
3666 lf_graph.
add_link(lf_node.output(0), *lf_zone_outputs[i]);
3672 BuildGraphParams graph_params{lf_graph};
3674 lf::FunctionNode *lf_simulation_input =
nullptr;
3676 lf_simulation_input = this->insert_simulation_input_node(
3679 lf::FunctionNode &lf_simulation_output = this->insert_simulation_output_node(*zone.
output_node,
3683 graph_params.usage_by_bsocket.add(bsocket, &lf_simulation_usage_node.
output(1));
3687 for (
const int i : IndexRange(sim_output_storage.items_num)) {
3688 lf::InputSocket &lf_to = lf_simulation_output.
input(i + 1);
3689 if (lf_simulation_input) {
3690 lf::OutputSocket &lf_from = lf_simulation_input->
output(i + 1);
3701 this->build_output_socket_usages(*zone.
input_node, graph_params);
3703 for (
const auto item : graph_params.lf_output_by_bsocket.items()) {
3704 this->insert_links_from_socket(*item.key, *item.value, graph_params);
3707 this->link_border_link_inputs_and_usages(zone,
3709 zone_info.indices.inputs.border_links,
3711 zone_info.indices.outputs.border_link_usages,
3714 for (
const int i : zone_info.indices.inputs.main) {
3715 lf_graph.
add_link(*lf_zone_inputs[i], lf_simulation_input->
input(i));
3718 for (
const int i : zone_info.indices.outputs.main.index_range()) {
3720 *lf_zone_outputs[zone_info.indices.outputs.main[i]]);
3723 this->add_default_inputs(graph_params);
3727 this->build_attribute_set_inputs_for_zone(graph_params,
3728 lf_attribute_set_by_field_source_index,
3729 lf_attribute_set_by_caller_propagation_index);
3730 for (
const auto item : lf_attribute_set_by_field_source_index.
items()) {
3731 lf::OutputSocket &lf_attribute_set_socket = *item.value;
3733 zone_info.indices.inputs.attributes_by_field_source_index.add_new(
3737 for (
const auto item : lf_attribute_set_by_caller_propagation_index.
items()) {
3738 lf::OutputSocket &lf_attribute_set_socket = *item.value;
3740 zone_info.indices.inputs.attributes_by_caller_propagation_index.add_new(
3744 this->link_attribute_set_inputs(lf_graph,
3746 lf_attribute_set_by_field_source_index,
3747 lf_attribute_set_by_caller_propagation_index);
3748 this->fix_link_cycles(lf_graph, graph_params.socket_usage_inputs);
3752 auto &logger = scope_.construct<GeometryNodesLazyFunctionLogger>(*lf_graph_info_);
3753 auto &side_effect_provider = scope_.construct<GeometryNodesLazyFunctionSideEffectProvider>();
3755 const auto &lf_graph_fn = scope_.construct<lf::GraphExecutor>(lf_graph,
3759 &side_effect_provider,
3761 const auto &zone_function = scope_.construct<LazyFunctionForSimulationZone>(*zone.
output_node,
3763 zone_info.lazy_function = &zone_function;
3772 void build_repeat_zone_function(
const bNodeTreeZone &zone)
3774 ZoneBuildInfo &zone_info = zone_build_infos_[zone.
index];
3776 ZoneBodyFunction &body_fn = this->build_zone_body_function(zone,
"Repeat Body");
3778 auto &zone_fn = scope_.construct<LazyFunctionForRepeatZone>(btree_, zone, zone_info, body_fn);
3779 zone_info.lazy_function = &zone_fn;
3782 void build_foreach_geometry_element_zone_function(
const bNodeTreeZone &zone)
3784 ZoneBuildInfo &zone_info = zone_build_infos_[zone.
index];
3786 ZoneBodyFunction &body_fn = this->build_zone_body_function(zone,
"Foreach Body");
3788 auto &zone_fn = scope_.construct<LazyFunctionForForeachGeometryElementZone>(
3789 btree_, zone, zone_info, body_fn);
3790 zone_info.lazy_function = &zone_fn;
3796 ZoneBodyFunction &build_zone_body_function(
const bNodeTreeZone &zone,
const StringRef name)
3798 lf::Graph &lf_body_graph = scope_.construct<lf::Graph>(name);
3800 BuildGraphParams graph_params{lf_body_graph};
3804 ZoneBodyFunction &body_fn = scope_.construct<ZoneBodyFunction>();
3811 *bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name);
3815 body_fn.indices.outputs.input_usages.append(
3817 graph_params.lf_output_by_bsocket.add_new(bsocket, &lf_input);
3820 this->build_zone_border_links_inputs(
3821 zone, lf_body_graph, lf_body_inputs, body_fn.indices.inputs.border_links);
3822 this->build_zone_border_link_input_usages(
3823 zone, lf_body_graph, lf_body_outputs, body_fn.indices.outputs.border_link_usages);
3830 *bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name);
3833 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_output);
3834 graph_params.usage_by_bsocket.add(bsocket, &lf_output_usage);
3836 body_fn.indices.inputs.output_usages.append(
3842 this->build_output_socket_usages(*zone.
input_node, graph_params);
3845 int valid_socket_i = 0;
3850 lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.
lookup_default(bsocket,
3853 *lf_body_outputs[body_fn.indices.outputs.input_usages[valid_socket_i]];
3855 lf_body_graph.
add_link(*lf_usage, lf_usage_output);
3858 static const bool static_false =
false;
3865 for (
const auto item : graph_params.lf_output_by_bsocket.items()) {
3866 this->insert_links_from_socket(*item.key, *item.value, graph_params);
3869 this->link_border_link_inputs_and_usages(zone,
3871 body_fn.indices.inputs.border_links,
3873 body_fn.indices.outputs.border_link_usages,
3876 this->add_default_inputs(graph_params);
3881 this->build_attribute_set_inputs_for_zone(graph_params,
3882 lf_attribute_set_by_field_source_index,
3883 lf_attribute_set_by_caller_propagation_index);
3884 for (
const auto item : lf_attribute_set_by_field_source_index.
items()) {
3885 lf::OutputSocket &lf_attribute_set_socket = *item.value;
3887 body_fn.indices.inputs.attributes_by_field_source_index.add_new(
3891 for (
const auto item : lf_attribute_set_by_caller_propagation_index.
items()) {
3892 lf::OutputSocket &lf_attribute_set_socket = *item.value;
3894 body_fn.indices.inputs.attributes_by_caller_propagation_index.add_new(
3898 this->link_attribute_set_inputs(lf_body_graph,
3900 lf_attribute_set_by_field_source_index,
3901 lf_attribute_set_by_caller_propagation_index);
3902 this->fix_link_cycles(lf_body_graph, graph_params.socket_usage_inputs);
3906 auto &logger = scope_.construct<GeometryNodesLazyFunctionLogger>(*lf_graph_info_);
3907 auto &side_effect_provider = scope_.construct<GeometryNodesLazyFunctionSideEffectProvider>();
3909 body_fn.function = &scope_.construct<lf::GraphExecutor>(lf_body_graph,
3913 &side_effect_provider,
3923 void build_zone_border_links_inputs(
const bNodeTreeZone &zone,
3924 lf::Graph &lf_graph,
3926 Vector<int> &r_indices)
3931 StringRef(
"Link from ") + border_link->
fromsock->
name)));
3935 void build_zone_border_link_input_usages(
const bNodeTreeZone &zone,
3936 lf::Graph &lf_graph,
3938 Vector<int> &r_indices)
3946 void build_attribute_set_inputs_for_zone(
3947 BuildGraphParams &graph_params,
3951 const Vector<int> all_required_field_sources = this->find_all_required_field_source_indices(
3952 graph_params.lf_attribute_set_input_by_output_geometry_bsocket,
3953 graph_params.lf_attribute_set_input_by_field_source_index);
3954 const Vector<int> all_required_caller_propagation_indices =
3955 this->find_all_required_caller_propagation_indices(
3956 graph_params.lf_attribute_set_input_by_output_geometry_bsocket,
3957 graph_params.lf_attribute_set_input_by_caller_propagation_index);
3959 Map<int, int> input_by_field_source_index;
3961 for (
const int field_source_index : all_required_field_sources) {
3962 const aai::FieldSource &field_source =
3963 attribute_inferencing_.all_field_sources[field_source_index];
3964 if ([[maybe_unused]]
const auto *input_field_source = std::get_if<aai::InputFieldSource>(
3965 &field_source.data))
3967 input_by_field_source_index.
add_new(field_source_index,
3968 input_by_field_source_index.
size());
3971 const auto &socket_field_source = std::get<aai::SocketFieldSource>(field_source.data);
3972 const bNodeSocket &bsocket = *socket_field_source.socket;
3973 if (lf::OutputSocket *lf_field_socket = graph_params.lf_output_by_bsocket.lookup_default(
3976 lf::OutputSocket *lf_usage_socket = graph_params.usage_by_bsocket.
lookup_default(
3978 lf::OutputSocket &lf_attribute_set_socket = this->get_extracted_attributes(
3981 graph_params.lf_graph,
3982 graph_params.socket_usage_inputs);
3983 lf_attribute_set_by_field_source_index.
add(field_source_index, &lf_attribute_set_socket);
3986 input_by_field_source_index.
add_new(field_source_index,
3987 input_by_field_source_index.
size());
3994 const int num = input_by_field_source_index.
size() +
3995 all_required_caller_propagation_indices.
size();
3996 for ([[maybe_unused]]
const int i : IndexRange(num)) {
3997 attribute_set_inputs.
append(&graph_params.lf_graph.add_input(
4001 for (
const auto item : input_by_field_source_index.
items()) {
4002 const int field_source_index = item.key;
4003 const int attribute_set_index = item.value;
4005 lf_attribute_set_by_field_source_index.
add(field_source_index, &lf_attribute_set_socket);
4007 for (
const int i : all_required_caller_propagation_indices.
index_range()) {
4008 const int caller_propagation_index = all_required_caller_propagation_indices[i];
4010 *attribute_set_inputs[input_by_field_source_index.
size() + i];
4011 lf_attribute_set_by_caller_propagation_index.
add_new(caller_propagation_index,
4012 &lf_attribute_set_socket);
4021 void build_root_graph()
4023 lf::Graph &lf_graph = lf_graph_info_->graph;
4025 this->build_main_group_inputs(lf_graph);
4026 if (btree_.group_output_node() ==
nullptr) {
4027 this->build_fallback_group_outputs(lf_graph);
4033 StringRef(
"Usage: ") + (interface_input->name ? interface_input->name :
""));
4034 group_input_usage_sockets_.append(&lf_socket);
4041 StringRef(
"Usage: ") + (interface_output->name ? interface_output->name :
""));
4042 group_output_used_sockets_.append(&lf_socket);
4043 lf_output_usages.
append(&lf_socket);
4046 BuildGraphParams &graph_params = root_graph_build_params_.emplace(lf_graph);
4047 if (
const bNode *group_output_bnode = btree_.group_output_node()) {
4048 for (
const bNodeSocket *bsocket : group_output_bnode->input_sockets().drop_back(1)) {
4049 graph_params.usage_by_bsocket.add(bsocket, lf_output_usages[bsocket->index()]);
4053 this->insert_nodes_and_zones(
4054 tree_zones_->nodes_outside_zones, tree_zones_->root_zones, graph_params);
4056 for (
const auto item : graph_params.lf_output_by_bsocket.items()) {
4057 this->insert_links_from_socket(*item.key, *item.value, graph_params);
4059 this->build_group_input_usages(graph_params);
4060 this->add_default_inputs(graph_params);
4062 this->build_attribute_propagation_input_node(lf_graph);
4066 this->build_attribute_set_inputs_outside_of_zones(
4068 lf_attribute_set_by_field_source_index,
4069 lf_attribute_set_by_caller_propagation_index);
4070 this->link_attribute_set_inputs(lf_graph,
4072 lf_attribute_set_by_field_source_index,
4073 lf_attribute_set_by_caller_propagation_index);
4075 this->fix_link_cycles(lf_graph, graph_params.socket_usage_inputs);
4080 lf_graph_info_->num_inline_nodes_approximate += lf_graph.
nodes().size();
4087 void build_geometry_nodes_group_function()
4089 GeometryNodesGroupFunction &function = lf_graph_info_->function;
4094 lf_graph_inputs.
extend(group_input_sockets_);
4097 lf_graph_inputs.
extend(group_output_used_sockets_);
4099 group_output_used_sockets_.size());
4101 for (
auto [output_index, lf_socket] : attribute_set_by_geometry_output_.items()) {
4102 lf_graph_inputs.
append(lf_socket);
4103 function.inputs.attributes_to_propagate.geometry_outputs.append(output_index);
4106 attribute_set_by_geometry_output_.size());
4108 lf_graph_outputs.
extend(standard_group_output_sockets_);
4110 standard_group_output_sockets_.size());
4112 lf_graph_outputs.
extend(group_input_usage_sockets_);
4114 group_input_usage_sockets_.size());
4118 for (
const bNode *bnode : btree_.nodes_by_type(
"GeometryNodeWarning")) {
4119 if (bnode->output_socket(0).is_directly_linked()) {
4124 if (tree_zones_->get_zone_by_node(bnode->identifier)) {
4131 const lf::Socket *lf_socket = root_graph_build_params_->lf_inputs_by_bsocket.lookup(
4132 &bnode->input_socket(0))[0];
4133 const lf::FunctionNode &lf_node =
static_cast<const lf::FunctionNode &
>(lf_socket->
node());
4134 local_side_effect_nodes.
append(&lf_node);
4137 function.function = &scope_.construct<lf::GraphExecutor>(
4138 lf_graph_info_->graph,
4139 std::move(lf_graph_inputs),
4140 std::move(lf_graph_outputs),
4141 &scope_.construct<GeometryNodesLazyFunctionLogger>(*lf_graph_info_),
4142 &scope_.construct<GeometryNodesLazyFunctionSideEffectProvider>(local_side_effect_nodes),
4146 void build_attribute_set_inputs_outside_of_zones(
4147 BuildGraphParams &graph_params,
4151 const Vector<int> all_required_field_sources = this->find_all_required_field_source_indices(
4152 graph_params.lf_attribute_set_input_by_output_geometry_bsocket,
4153 graph_params.lf_attribute_set_input_by_field_source_index);
4155 for (
const int field_source_index : all_required_field_sources) {
4156 const aai::FieldSource &field_source =
4157 attribute_inferencing_.all_field_sources[field_source_index];
4158 lf::OutputSocket *lf_attribute_set_socket;
4159 if (
const auto *input_field_source = std::get_if<aai::InputFieldSource>(&field_source.data))
4161 const int input_index = input_field_source->input_index;
4162 lf::OutputSocket &lf_field_socket =
const_cast<lf::OutputSocket &
>(
4163 *group_input_sockets_[input_index]);
4164 lf::OutputSocket *lf_usage_socket =
const_cast<lf::OutputSocket *
>(
4165 group_input_usage_sockets_[input_index]->origin());
4166 lf_attribute_set_socket = &this->get_extracted_attributes(
4169 graph_params.lf_graph,
4170 graph_params.socket_usage_inputs);
4173 const auto &socket_field_source = std::get<aai::SocketFieldSource>(field_source.data);
4174 const bNodeSocket &bsocket = *socket_field_source.socket;
4175 lf::OutputSocket &lf_field_socket = *graph_params.lf_output_by_bsocket.lookup(&bsocket);
4176 lf::OutputSocket *lf_usage_socket = graph_params.usage_by_bsocket.lookup_default(&bsocket,
4178 lf_attribute_set_socket = &this->get_extracted_attributes(
4181 graph_params.lf_graph,
4182 graph_params.socket_usage_inputs);
4184 lf_attribute_set_by_field_source_index.
add_new(field_source_index, lf_attribute_set_socket);
4187 for (
const int caller_propagation_index :
4188 attribute_inferencing_.propagated_output_geometry_indices.index_range())
4190 const int group_output_index =
4191 attribute_inferencing_.propagated_output_geometry_indices[caller_propagation_index];
4192 lf::OutputSocket &lf_attribute_set_socket =
const_cast<lf::OutputSocket &
>(
4193 *attribute_set_by_geometry_output_.lookup(group_output_index));
4194 lf_attribute_set_by_caller_propagation_index.
add(caller_propagation_index,
4195 &lf_attribute_set_socket);
4199 Vector<int> find_all_required_field_source_indices(
4201 &lf_attribute_set_input_by_output_geometry_bsocket,
4202 const MultiValueMap<int, lf::InputSocket *> &lf_attribute_set_input_by_field_source_index)
4204 BitVector<> all_required_field_sources(attribute_inferencing_.all_field_sources.size(),
false);
4206 lf_attribute_set_input_by_output_geometry_bsocket.
keys())
4208 all_required_field_sources |=
4209 attribute_inferencing_
4210 .required_fields_by_geometry_socket[geometry_output_bsocket->index_in_tree()];
4212 for (
const int field_source_index : lf_attribute_set_input_by_field_source_index.
keys()) {
4213 all_required_field_sources[field_source_index].set();
4221 Vector<int> find_all_required_caller_propagation_indices(
4223 &lf_attribute_set_input_by_output_geometry_bsocket,
4224 const MultiValueMap<int, lf::InputSocket *>
4225 &lf_attribute_set_input_by_caller_propagation_index)
4227 BitVector<> all_required_caller_propagation_indices(
4228 attribute_inferencing_.propagated_output_geometry_indices.size(),
false);
4230 lf_attribute_set_input_by_output_geometry_bsocket.
keys())
4232 all_required_caller_propagation_indices |=
4233 attribute_inferencing_
4234 .propagate_to_output_by_geometry_socket[geometry_output_bs->index_in_tree()];
4236 for (
const int caller_propagation_index :
4237 lf_attribute_set_input_by_caller_propagation_index.
keys())
4239 all_required_caller_propagation_indices[caller_propagation_index].set();
4244 [&](
const int i) {
indices.append(i); });
4248 void link_attribute_set_inputs(
4249 lf::Graph &lf_graph,
4250 BuildGraphParams &graph_params,
4256 for (
const MapItem<const bNodeSocket *, lf::InputSocket *> item :
4257 graph_params.lf_attribute_set_input_by_output_geometry_bsocket.items())
4259 const bNodeSocket &geometry_output_bsocket = *item.key;
4260 lf::InputSocket &lf_attribute_set_input = *item.value;
4264 const BoundedBitSpan required_fields =
4265 attribute_inferencing_
4266 .required_fields_by_geometry_socket[geometry_output_bsocket.index_in_tree()];
4268 const auto &field_source = attribute_inferencing_.all_field_sources[field_source_index];
4269 if (
const auto *socket_field_source = std::get_if<aai::SocketFieldSource>(
4270 &field_source.data))
4272 if (&socket_field_source->socket->owner_node() == &geometry_output_bsocket.owner_node())
4277 lf_attribute_set_sockets.
append(
4278 lf_attribute_set_by_field_source_index.
lookup(field_source_index));
4281 const BoundedBitSpan required_caller_propagations =
4282 attribute_inferencing_
4283 .propagate_to_output_by_geometry_socket[geometry_output_bsocket.index_in_tree()];
4285 lf_attribute_set_sockets.
append(
4286 lf_attribute_set_by_caller_propagation_index.
lookup(caller_propagation_index));
4289 if (lf::OutputSocket *lf_attribute_set = this->join_attribute_sets(
4290 lf_attribute_set_sockets,
4291 join_attribute_sets_cache,
4293 graph_params.socket_usage_inputs))
4295 lf_graph.
add_link(*lf_attribute_set, lf_attribute_set_input);
4298 static const bke::AnonymousAttributeSet empty_set;
4303 for (
const auto item : graph_params.lf_attribute_set_input_by_field_source_index.items()) {
4304 const int field_source_index = item.key;
4305 lf::OutputSocket &lf_attribute_set_socket = *lf_attribute_set_by_field_source_index.
lookup(
4306 field_source_index);
4307 for (lf::InputSocket *lf_attribute_set_input : item.value) {
4308 lf_graph.
add_link(lf_attribute_set_socket, *lf_attribute_set_input);
4311 for (
const auto item : graph_params.lf_attribute_set_input_by_caller_propagation_index.items())
4313 const int caller_propagation_index = item.key;
4314 lf::OutputSocket &lf_attribute_set_socket =
4315 *lf_attribute_set_by_caller_propagation_index.
lookup(caller_propagation_index);
4316 for (lf::InputSocket *lf_attribute_set_input : item.value) {
4317 lf_graph.
add_link(lf_attribute_set_socket, *lf_attribute_set_input);
4322 void insert_nodes_and_zones(
const Span<const bNode *> bnodes,
4323 const Span<const bNodeTreeZone *> zones,
4324 BuildGraphParams &graph_params)
4326 Vector<const bNode *> nodes_to_insert = bnodes;
4328 for (
const bNodeTreeZone *zone : zones) {
4333 std::sort(nodes_to_insert.
begin(), nodes_to_insert.
end(), [](
const bNode *a,
const bNode *
b) {
4334 return a->runtime->toposort_right_to_left_index < b->runtime->toposort_right_to_left_index;
4337 for (
const bNode *bnode : nodes_to_insert) {
4338 this->build_output_socket_usages(*bnode, graph_params);
4339 if (
const bNodeTreeZone *zone = zone_by_output.
lookup_default(bnode,
nullptr)) {
4340 this->insert_child_zone_node(*zone, graph_params);
4343 this->insert_node_in_graph(*bnode, graph_params);
4348 void link_border_link_inputs_and_usages(
const bNodeTreeZone &zone,
4349 const Span<lf::GraphInputSocket *> lf_inputs,
4350 const Span<int> lf_border_link_input_indices,
4351 const Span<lf::GraphOutputSocket *> lf_usages,
4352 const Span<int> lf_border_link_usage_indices,
4353 BuildGraphParams &graph_params)
4355 lf::Graph &lf_graph = graph_params.lf_graph;
4356 for (
const int border_link_i : zone.
border_links.index_range()) {
4361 for (lf::InputSocket *lf_to : lf_link_targets) {
4362 lf_graph.
add_link(lf_from, *lf_to);
4365 *lf_usages[lf_border_link_usage_indices[border_link_i]];
4366 if (lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(
4367 border_link.
tosock,
nullptr))
4369 lf_graph.
add_link(*lf_usage, lf_usage_output);
4372 static const bool static_false =
false;
4378 lf::OutputSocket &get_extracted_attributes(lf::OutputSocket &lf_field_socket,
4379 lf::OutputSocket *lf_usage_socket,
4380 lf::Graph &lf_graph,
4381 Set<lf::InputSocket *> &socket_usage_inputs)
4383 auto &lazy_function = scope_.construct<LazyFunctionForAnonymousAttributeSetExtract>();
4384 lf::Node &lf_node = lf_graph.
add_function(lazy_function);
4385 lf::InputSocket &lf_use_input = lf_node.
input(0);
4386 lf::InputSocket &lf_field_input = lf_node.input(1);
4387 socket_usage_inputs.
add_new(&lf_use_input);
4388 if (lf_usage_socket) {
4389 lf_graph.
add_link(*lf_usage_socket, lf_use_input);
4392 static const bool static_false =
false;
4395 lf_graph.
add_link(lf_field_socket, lf_field_input);
4396 return lf_node.output(0);
4402 lf::OutputSocket *join_attribute_sets(
const Span<lf::OutputSocket *> lf_attribute_set_sockets,
4404 lf::Graph &lf_graph,
4405 Set<lf::InputSocket *> &socket_usage_inputs)
4407 if (lf_attribute_set_sockets.
is_empty()) {
4410 if (lf_attribute_set_sockets.
size() == 1) {
4411 return lf_attribute_set_sockets[0];
4416 return cache.lookup_or_add_cb(key, [&]() {
4418 lf_attribute_set_sockets.
size(), scope_);
4419 lf::Node &lf_node = lf_graph.
add_function(lazy_function);
4420 for (
const int i : lf_attribute_set_sockets.
index_range()) {
4421 lf::OutputSocket &lf_attribute_set_socket = *lf_attribute_set_sockets[i];
4422 lf::InputSocket &lf_use_input = lf_node.
input(lazy_function.get_use_input(i));
4426 static const bool static_true =
true;
4429 socket_usage_inputs.
add(&lf_use_input);
4430 lf::InputSocket &lf_attribute_set_input = lf_node.
input(
4431 lazy_function.get_attribute_set_input(i));
4432 lf_graph.
add_link(lf_attribute_set_socket, lf_attribute_set_input);
4434 return &lf_node.
output(0);
4438 void insert_child_zone_node(
const bNodeTreeZone &child_zone, BuildGraphParams &graph_params)
4440 const int child_zone_i = child_zone.
index;
4441 ZoneBuildInfo &child_zone_info = zone_build_infos_[child_zone_i];
4442 lf::FunctionNode &child_zone_node = graph_params.lf_graph.add_function(
4443 *child_zone_info.lazy_function);
4444 mapping_->zone_node_map.add_new(&child_zone, &child_zone_node);
4447 int valid_socket_i = 0;
4452 lf::InputSocket &lf_input_socket = child_zone_node.
input(
4453 child_zone_info.indices.inputs.main[valid_socket_i]);
4454 lf::OutputSocket &lf_usage_socket = child_zone_node.
output(
4455 child_zone_info.indices.outputs.input_usages[valid_socket_i]);
4456 mapping_->bsockets_by_lf_socket_map.add(&lf_input_socket, bsocket);
4457 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_input_socket);
4458 graph_params.usage_by_bsocket.add(bsocket, &lf_usage_socket);
4463 int valid_socket_i = 0;
4468 lf::OutputSocket &lf_output_socket = child_zone_node.
output(
4469 child_zone_info.indices.outputs.main[valid_socket_i]);
4470 lf::InputSocket &lf_usage_input = child_zone_node.
input(
4471 child_zone_info.indices.inputs.output_usages[valid_socket_i]);
4472 mapping_->bsockets_by_lf_socket_map.add(&lf_output_socket, bsocket);
4473 graph_params.lf_output_by_bsocket.add(bsocket, &lf_output_socket);
4474 graph_params.socket_usage_inputs.add(&lf_usage_input);
4475 if (lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(bsocket,
4478 graph_params.lf_graph.add_link(*lf_usage, lf_usage_input);
4481 static const bool static_false =
false;
4488 const Span<const bNodeLink *> child_border_links = child_zone.
border_links;
4489 for (
const int child_border_link_i : child_border_links.
index_range()) {
4490 lf::InputSocket &child_border_link_input = child_zone_node.
input(
4491 child_zone_info.indices.inputs.border_links[child_border_link_i]);
4492 const bNodeLink &link = *child_border_links[child_border_link_i];
4493 graph_params.lf_input_by_border_link.add(&link, &child_border_link_input);
4494 lf::OutputSocket &lf_usage = child_zone_node.
output(
4495 child_zone_info.indices.outputs.border_link_usages[child_border_link_i]);
4496 graph_params.lf_inputs_by_bsocket.add(link.
tosock, &child_border_link_input);
4497 graph_params.usage_by_bsocket.add(link.
tosock, &lf_usage);
4500 for (
const auto item : child_zone_info.indices.inputs.attributes_by_field_source_index.items())
4502 const int field_source_index = item.key;
4503 const int child_zone_input_index = item.value;
4504 lf::InputSocket &lf_attribute_set_input = child_zone_node.
input(child_zone_input_index);
4505 graph_params.lf_attribute_set_input_by_field_source_index.add(field_source_index,
4506 &lf_attribute_set_input);
4508 for (
const auto item :
4509 child_zone_info.indices.inputs.attributes_by_caller_propagation_index.items())
4511 const int caller_propagation_index = item.key;
4512 const int child_zone_input_index = item.value;
4513 lf::InputSocket &lf_attribute_set_input = child_zone_node.
input(child_zone_input_index);
4514 BLI_assert(lf_attribute_set_input.
type().
is<bke::AnonymousAttributeSet>());
4515 graph_params.lf_attribute_set_input_by_caller_propagation_index.add(caller_propagation_index,
4516 &lf_attribute_set_input);
4520 void build_main_group_inputs(lf::Graph &lf_graph)
4522 const Span<const bNodeTreeInterfaceSocket *> interface_inputs = btree_.interface_inputs();
4524 const bke::bNodeSocketType *typeinfo = interface_input->socket_typeinfo();
4526 *typeinfo->geometry_nodes_cpp_type, interface_input->name ? interface_input->name :
"");
4527 group_input_sockets_.append(&lf_socket);
4535 void build_fallback_group_outputs(lf::Graph &lf_graph)
4538 const bke::bNodeSocketType *typeinfo = interface_output->socket_typeinfo();
4539 const CPPType &type = *typeinfo->geometry_nodes_cpp_type;
4541 type, interface_output->name ? interface_output->name :
"");
4542 const void *default_value = typeinfo->geometry_nodes_default_cpp_value;
4543 if (default_value ==
nullptr) {
4544 default_value = type.default_value();
4547 standard_group_output_sockets_.append(&lf_socket);
4551 void insert_node_in_graph(
const bNode &bnode, BuildGraphParams &graph_params)
4553 const bke::bNodeType *node_type = bnode.
typeinfo;
4554 if (node_type ==
nullptr) {
4557 if (bnode.is_muted()) {
4558 this->build_muted_node(bnode, graph_params);
4561 switch (node_type->type) {
4567 this->build_reroute_node(bnode, graph_params);
4571 this->handle_group_input_node(bnode, graph_params);
4575 this->build_group_output_node(bnode, graph_params);
4580 this->build_group_node(bnode, graph_params);
4584 this->build_viewer_node(bnode, graph_params);
4588 this->build_switch_node(bnode, graph_params);
4592 this->build_index_switch_node(bnode, graph_params);
4596 this->build_warning_node(bnode, graph_params);
4602 this->build_gizmo_node(bnode, graph_params);
4606 this->build_bake_node(bnode, graph_params);
4610 this->build_menu_switch_node(bnode, graph_params);
4614 if (node_type->geometry_node_execute) {
4615 this->build_geometry_node(bnode, graph_params);
4618 const NodeMultiFunctions::Item &fn_item = node_multi_functions_.try_get(bnode);
4619 if (fn_item.fn !=
nullptr) {
4620 this->build_multi_function_node(bnode, fn_item, graph_params);
4624 this->build_undefined_node(bnode, graph_params);
4633 void build_muted_node(
const bNode &bnode, BuildGraphParams &graph_params)
4635 auto &lazy_function = scope_.construct<LazyFunctionForMutedNode>(
4636 bnode, mapping_->lf_index_by_bsocket);
4637 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
4638 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
4639 const int lf_index = mapping_->lf_index_by_bsocket[bsocket->index_in_tree()];
4640 if (lf_index == -1) {
4643 lf::InputSocket &lf_socket = lf_node.input(lf_index);
4644 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
4645 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, bsocket);
4647 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
4648 const int lf_index = mapping_->lf_index_by_bsocket[bsocket->index_in_tree()];
4649 if (lf_index == -1) {
4652 lf::OutputSocket &lf_socket = lf_node.output(lf_index);
4653 graph_params.lf_output_by_bsocket.add_new(bsocket, &lf_socket);
4654 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, bsocket);
4657 this->build_muted_node_usages(bnode, graph_params);
4663 void build_muted_node_usages(
const bNode &bnode, BuildGraphParams &graph_params)
4666 MultiValueMap<const bNodeSocket *, const bNodeSocket *> outputs_by_input;
4667 for (
const bNodeLink &blink : bnode.internal_links()) {
4668 outputs_by_input.
add(blink.fromsock, blink.tosock);
4670 for (
const auto item : outputs_by_input.
items()) {
4672 const Span<const bNodeSocket *> output_bsockets = item.value;
4676 for (
const bNodeSocket *output_bsocket : output_bsockets) {
4677 if (lf::OutputSocket *lf_socket = graph_params.usage_by_bsocket.lookup_default(
4678 output_bsocket,
nullptr))
4680 lf_socket_usages.
append(lf_socket);
4683 graph_params.usage_by_bsocket.add(&input_bsocket,
4684 this->or_socket_usages(lf_socket_usages, graph_params));
4688 void build_reroute_node(
const bNode &bnode, BuildGraphParams &graph_params)
4690 const bNodeSocket &input_bsocket = bnode.input_socket(0);
4691 const bNodeSocket &output_bsocket = bnode.output_socket(0);
4693 if (type ==
nullptr) {
4697 auto &lazy_function = scope_.construct<LazyFunctionForRerouteNode>(*type);
4698 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
4700 lf::InputSocket &lf_input = lf_node.
input(0);
4701 lf::OutputSocket &lf_output = lf_node.
output(0);
4702 graph_params.lf_inputs_by_bsocket.add(&input_bsocket, &lf_input);
4703 graph_params.lf_output_by_bsocket.add_new(&output_bsocket, &lf_output);
4704 mapping_->bsockets_by_lf_socket_map.add(&lf_input, &input_bsocket);
4705 mapping_->bsockets_by_lf_socket_map.add(&lf_output, &output_bsocket);
4707 if (lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(
4708 &bnode.output_socket(0),
nullptr))
4710 graph_params.usage_by_bsocket.add(&bnode.input_socket(0), lf_usage);
4714 void handle_group_input_node(
const bNode &bnode, BuildGraphParams &graph_params)
4716 for (
const int i : btree_.interface_inputs().index_range()) {
4717 const bNodeSocket &bsocket = bnode.output_socket(i);
4719 group_input_sockets_[i]);
4720 graph_params.lf_output_by_bsocket.add_new(&bsocket, &lf_socket);
4721 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
4725 void build_group_output_node(
const bNode &bnode, BuildGraphParams &graph_params)
4729 for (
const int i : btree_.interface_outputs().index_range()) {
4731 const bNodeSocket &bsocket = bnode.input_socket(i);
4732 const bke::bNodeSocketType *typeinfo = interface_output.socket_typeinfo();
4733 const CPPType &type = *typeinfo->geometry_nodes_cpp_type;
4735 type, interface_output.
name ? interface_output.
name :
"");
4736 lf_graph_outputs.
append(&lf_socket);
4737 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
4738 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
4741 if (&bnode == btree_.group_output_node()) {
4742 standard_group_output_sockets_ = lf_graph_outputs.
as_span();
4746 void build_group_node(
const bNode &bnode, BuildGraphParams &graph_params)
4749 if (group_btree ==
nullptr) {
4752 const GeometryNodesLazyFunctionGraphInfo *group_lf_graph_info =
4754 if (group_lf_graph_info ==
nullptr) {
4758 auto &lazy_function = scope_.construct<LazyFunctionForGroupNode>(
4759 bnode, *group_lf_graph_info, *lf_graph_info_);
4760 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(lazy_function);
4762 for (
const int i : bnode.input_sockets().index_range()) {
4763 const bNodeSocket &bsocket = bnode.input_socket(i);
4765 lf::InputSocket &lf_socket = lf_node.input(group_lf_graph_info->function.inputs.main[i]);
4766 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
4767 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
4769 for (
const int i : bnode.output_sockets().index_range()) {
4770 const bNodeSocket &bsocket = bnode.output_socket(i);
4771 lf::OutputSocket &lf_socket = lf_node.output(group_lf_graph_info->function.outputs.main[i]);
4772 graph_params.lf_output_by_bsocket.add_new(&bsocket, &lf_socket);
4773 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
4775 mapping_->group_node_map.add(&bnode, &lf_node);
4776 lf_graph_info_->num_inline_nodes_approximate +=
4777 group_lf_graph_info->num_inline_nodes_approximate;
4778 static const bool static_false =
false;
4779 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
4781 const int lf_input_index =
4782 mapping_->lf_input_index_for_output_bsocket_usage[bsocket->index_in_all_outputs()];
4783 if (lf_input_index != -1) {
4784 lf::InputSocket &lf_input = lf_node.input(lf_input_index);
4786 graph_params.socket_usage_inputs.add(&lf_input);
4791 const int lf_input_index = mapping_->lf_input_index_for_attribute_propagation_to_output
4792 [bsocket->index_in_all_outputs()];
4793 if (lf_input_index != -1) {
4794 lf::InputSocket &lf_input = lf_node.input(lf_input_index);
4795 graph_params.lf_attribute_set_input_by_output_geometry_bsocket.add(bsocket, &lf_input);
4800 this->build_group_node_socket_usage(bnode, lf_node, graph_params, *group_lf_graph_info);
4803 void build_group_node_socket_usage(
const bNode &bnode,
4804 lf::FunctionNode &lf_group_node,
4805 BuildGraphParams &graph_params,
4806 const GeometryNodesLazyFunctionGraphInfo &group_lf_graph_info)
4808 for (
const bNodeSocket *input_bsocket : bnode.input_sockets()) {
4809 const int input_index = input_bsocket->index();
4810 const InputUsageHint &input_usage_hint =
4811 group_lf_graph_info.mapping.group_input_usage_hints[input_index];
4812 switch (input_usage_hint.type) {
4819 for (
const int i : input_usage_hint.output_dependencies) {
4820 if (lf::OutputSocket *lf_socket = graph_params.usage_by_bsocket.lookup_default(
4821 &bnode.output_socket(i),
nullptr))
4823 output_usages.
append(lf_socket);
4826 graph_params.usage_by_bsocket.add(input_bsocket,
4827 this->or_socket_usages(output_usages, graph_params));
4831 graph_params.usage_by_bsocket.add(
4834 group_lf_graph_info.function.outputs.input_usages[input_index]));
4840 for (
const bNodeSocket *output_bsocket : bnode.output_sockets()) {
4841 const int lf_input_index =
4843 ->lf_input_index_for_output_bsocket_usage[output_bsocket->index_in_all_outputs()];
4845 lf::InputSocket &lf_socket = lf_group_node.
input(lf_input_index);
4846 if (lf::OutputSocket *lf_output_is_used = graph_params.usage_by_bsocket.lookup_default(
4847 output_bsocket,
nullptr))
4849 graph_params.lf_graph.add_link(*lf_output_is_used, lf_socket);
4852 static const bool static_false =
false;
4858 void build_geometry_node(
const bNode &bnode, BuildGraphParams &graph_params)
4860 auto &lazy_function = scope_.construct<LazyFunctionForGeometryNode>(bnode, *lf_graph_info_);
4861 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
4863 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
4864 const int lf_index = mapping_->lf_index_by_bsocket[bsocket->index_in_tree()];
4865 if (lf_index == -1) {
4868 lf::InputSocket &lf_socket = lf_node.input(lf_index);
4870 if (bsocket->is_multi_input()) {
4871 auto &multi_input_lazy_function = scope_.construct<LazyFunctionForMultiInput>(*bsocket);
4872 lf::Node &lf_multi_input_node = graph_params.lf_graph.add_function(
4873 multi_input_lazy_function);
4874 graph_params.lf_graph.add_link(lf_multi_input_node.
output(0), lf_socket);
4875 for (
const int i : multi_input_lazy_function.links.index_range()) {
4876 lf::InputSocket &lf_multi_input_socket = lf_multi_input_node.
input(i);
4877 const bNodeLink *link = multi_input_lazy_function.links[i];
4878 graph_params.lf_input_by_multi_input_link.add(link, &lf_multi_input_socket);
4879 mapping_->bsockets_by_lf_socket_map.add(&lf_multi_input_socket, bsocket);
4885 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
4886 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, bsocket);
4889 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
4890 const int lf_index = mapping_->lf_index_by_bsocket[bsocket->index_in_tree()];
4891 if (lf_index == -1) {
4894 lf::OutputSocket &lf_socket = lf_node.output(lf_index);
4895 graph_params.lf_output_by_bsocket.add_new(bsocket, &lf_socket);
4896 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, bsocket);
4899 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
4901 const int lf_input_index =
4902 mapping_->lf_input_index_for_output_bsocket_usage[bsocket->index_in_all_outputs()];
4903 if (lf_input_index != -1) {
4904 lf::InputSocket &lf_input_socket = lf_node.input(lf_input_index);
4905 if (lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(bsocket,
4908 graph_params.lf_graph.add_link(*lf_usage, lf_input_socket);
4911 static const bool static_false =
false;
4914 graph_params.socket_usage_inputs.add_new(&lf_node.input(lf_input_index));
4919 const int lf_input_index = mapping_->lf_input_index_for_attribute_propagation_to_output
4920 [bsocket->index_in_all_outputs()];
4921 if (lf_input_index != -1) {
4922 graph_params.lf_attribute_set_input_by_output_geometry_bsocket.add(
4923 bsocket, &lf_node.input(lf_input_index));
4928 this->build_standard_node_input_socket_usage(bnode, graph_params);
4931 void build_standard_node_input_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
4933 if (bnode.input_sockets().is_empty()) {
4938 for (
const bNodeSocket *output_socket : bnode.output_sockets()) {
4939 if (!output_socket->is_available()) {
4942 if (lf::OutputSocket *is_used_socket = graph_params.usage_by_bsocket.lookup_default(
4943 output_socket,
nullptr))
4950 lf::OutputSocket *lf_usage = this->or_socket_usages(output_usages, graph_params);
4951 if (lf_usage ==
nullptr) {
4955 for (
const bNodeSocket *input_socket : bnode.input_sockets()) {
4956 if (input_socket->is_available()) {
4957 graph_params.usage_by_bsocket.add(input_socket, lf_usage);
4962 void build_multi_function_node(
const bNode &bnode,
4963 const NodeMultiFunctions::Item &fn_item,
4964 BuildGraphParams &graph_params)
4966 auto &lazy_function = scope_.construct<LazyFunctionForMultiFunctionNode>(
4967 bnode, fn_item, mapping_->lf_index_by_bsocket);
4968 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(lazy_function);
4970 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
4971 const int lf_index = mapping_->lf_index_by_bsocket[bsocket->index_in_tree()];
4972 if (lf_index == -1) {
4976 lf::InputSocket &lf_socket = lf_node.input(lf_index);
4977 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
4978 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, bsocket);
4980 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
4981 const int lf_index = mapping_->lf_index_by_bsocket[bsocket->index_in_tree()];
4982 if (lf_index == -1) {
4985 lf::OutputSocket &lf_socket = lf_node.output(lf_index);
4986 graph_params.lf_output_by_bsocket.add(bsocket, &lf_socket);
4987 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, bsocket);
4990 this->build_standard_node_input_socket_usage(bnode, graph_params);
4993 void build_viewer_node(
const bNode &bnode, BuildGraphParams &graph_params)
4995 auto &lazy_function = scope_.construct<LazyFunctionForViewerNode>(
4996 bnode, mapping_->lf_index_by_bsocket);
4997 lf::FunctionNode &lf_viewer_node = graph_params.lf_graph.add_function(lazy_function);
4999 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
5000 const int lf_index = mapping_->lf_index_by_bsocket[bsocket->index_in_tree()];
5001 if (lf_index == -1) {
5004 lf::InputSocket &lf_socket = lf_viewer_node.input(lf_index);
5005 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
5006 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, bsocket);
5009 mapping_->possible_side_effect_node_map.add(&bnode, &lf_viewer_node);
5012 auto &usage_lazy_function = scope_.construct<LazyFunctionForViewerInputUsage>(
5014 lf::FunctionNode &lf_usage_node = graph_params.lf_graph.add_function(usage_lazy_function);
5016 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
5017 if (bsocket->is_available()) {
5018 graph_params.usage_by_bsocket.add(bsocket, &lf_usage_node.output(0));
5024 void build_gizmo_node(
const bNode &bnode, BuildGraphParams &graph_params)
5026 auto &lazy_function = scope_.construct<LazyFunctionForGizmoNode>(
5027 bnode, mapping_->lf_index_by_bsocket);
5028 lf::FunctionNode &lf_gizmo_node = graph_params.lf_graph.add_function(lazy_function);
5029 lazy_function.self_node = &lf_gizmo_node;
5031 for (
const int i : lazy_function.gizmo_links.index_range()) {
5032 const bNodeLink &link = *lazy_function.gizmo_links[i];
5033 lf::InputSocket &lf_socket = lf_gizmo_node.input(i);
5034 graph_params.lf_input_by_multi_input_link.add(&link, &lf_socket);
5036 for (
const int i : bnode.input_sockets().drop_front(1).index_range()) {
5037 lf::InputSocket &lf_socket = lf_gizmo_node.input(i + lazy_function.gizmo_links.size());
5038 const bNodeSocket &bsocket = bnode.input_socket(i + 1);
5039 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
5040 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
5042 for (
const int i : bnode.output_sockets().index_range()) {
5043 lf::OutputSocket &lf_socket = lf_gizmo_node.output(i);
5044 const bNodeSocket &bsocket = bnode.output_socket(i);
5045 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
5046 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
5049 this->build_gizmo_node_socket_usage(bnode, graph_params, lf_gizmo_node);
5051 mapping_->possible_side_effect_node_map.add(&bnode, &lf_gizmo_node);
5054 void build_gizmo_node_socket_usage(
const bNode &bnode,
5055 BuildGraphParams &graph_params,
5056 const lf::FunctionNode &lf_gizmo_node)
5058 const auto &usage_fn = scope_.construct<LazyFunctionForGizmoInputsUsage>(bnode, lf_gizmo_node);
5059 lf::FunctionNode &lf_usage_node = graph_params.lf_graph.add_function(usage_fn);
5060 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
5061 graph_params.usage_by_bsocket.add(bsocket, &lf_usage_node.output(0));
5067 BuildGraphParams &graph_params)
5077 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
5078 scope_.add(std::move(lazy_function));
5080 for (
const int i : bnode.input_sockets().index_range().drop_back(1)) {
5081 const bNodeSocket &bsocket = bnode.input_socket(i);
5082 lf::InputSocket &lf_socket = lf_node.
input(
5083 mapping_->lf_index_by_bsocket[bsocket.index_in_tree()]);
5084 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
5085 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
5087 for (
const int i : bnode.output_sockets().index_range().drop_back(1)) {
5088 const bNodeSocket &bsocket = bnode.output_socket(i);
5089 lf::OutputSocket &lf_socket = lf_node.
output(
5090 mapping_->lf_index_by_bsocket[bsocket.index_in_tree()]);
5091 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
5092 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
5097 lf::FunctionNode &insert_simulation_output_node(
const bNode &bnode,
5098 BuildGraphParams &graph_params)
5101 bnode, *lf_graph_info_);
5102 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
5103 scope_.add(std::move(lazy_function));
5105 for (
const int i : bnode.input_sockets().index_range().drop_back(1)) {
5106 const bNodeSocket &bsocket = bnode.input_socket(i);
5107 lf::InputSocket &lf_socket = lf_node.
input(
5108 mapping_->lf_index_by_bsocket[bsocket.index_in_tree()]);
5109 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
5110 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
5112 for (
const int i : bnode.output_sockets().index_range().drop_back(1)) {
5113 const bNodeSocket &bsocket = bnode.output_socket(i);
5114 lf::OutputSocket &lf_socket = lf_node.
output(
5115 mapping_->lf_index_by_bsocket[bsocket.index_in_tree()]);
5116 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
5117 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
5120 mapping_->possible_side_effect_node_map.add(&bnode, &lf_node);
5125 void build_bake_node(
const bNode &bnode, BuildGraphParams &graph_params)
5128 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
5129 scope_.add(std::move(lazy_function));
5131 for (
const int i : bnode.input_sockets().index_range().drop_back(1)) {
5132 const bNodeSocket &bsocket = bnode.input_socket(i);
5133 lf::InputSocket &lf_socket = lf_node.
input(
5134 mapping_->lf_index_by_bsocket[bsocket.index_in_tree()]);
5135 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
5136 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
5138 for (
const int i : bnode.output_sockets().index_range().drop_back(1)) {
5139 const bNodeSocket &bsocket = bnode.output_socket(i);
5140 lf::OutputSocket &lf_socket = lf_node.
output(
5141 mapping_->lf_index_by_bsocket[bsocket.index_in_tree()]);
5142 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
5143 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
5146 mapping_->possible_side_effect_node_map.add(&bnode, &lf_node);
5148 this->build_bake_node_socket_usage(bnode, graph_params);
5151 void build_bake_node_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
5153 const LazyFunction &usage_fn = scope_.construct<LazyFunctionForBakeInputsUsage>(bnode);
5154 lf::FunctionNode &lf_usage_node = graph_params.lf_graph.add_function(usage_fn);
5155 const int items_num = bnode.input_sockets().size() - 1;
5156 for (
const int i : IndexRange(items_num)) {
5157 graph_params.usage_by_bsocket.add(&bnode.input_socket(i), &lf_usage_node.output(0));
5161 void build_switch_node(
const bNode &bnode, BuildGraphParams &graph_params)
5164 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
5165 scope_.add(std::move(lazy_function));
5167 for (
const int i : bnode.input_sockets().index_range()) {
5168 graph_params.lf_inputs_by_bsocket.add(&bnode.input_socket(i), &lf_node.
input(i));
5169 mapping_->bsockets_by_lf_socket_map.add(&lf_node.
input(i), &bnode.input_socket(i));
5172 graph_params.lf_output_by_bsocket.add(&bnode.output_socket(0), &lf_node.
output(0));
5173 mapping_->bsockets_by_lf_socket_map.add(&lf_node.
output(0), &bnode.output_socket(0));
5175 this->build_switch_node_socket_usage(bnode, graph_params);
5178 void build_switch_node_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
5180 const bNodeSocket &switch_input_bsocket = bnode.input_socket(0);
5181 const bNodeSocket &false_input_bsocket = bnode.input_socket(1);
5182 const bNodeSocket &true_input_bsocket = bnode.input_socket(2);
5183 const bNodeSocket &output_bsocket = bnode.output_socket(0);
5184 lf::OutputSocket *output_is_used_socket = graph_params.usage_by_bsocket.
lookup_default(
5185 &output_bsocket,
nullptr);
5186 if (output_is_used_socket ==
nullptr) {
5189 graph_params.usage_by_bsocket.add(&switch_input_bsocket, output_is_used_socket);
5190 if (switch_input_bsocket.is_directly_linked()) {
5192 static const LazyFunctionForSwitchSocketUsage switch_socket_usage_fn;
5193 lf::Node &lf_node = graph_params.lf_graph.add_function(switch_socket_usage_fn);
5194 graph_params.lf_inputs_by_bsocket.add(&switch_input_bsocket, &lf_node.
input(0));
5195 graph_params.usage_by_bsocket.add(&false_input_bsocket, &lf_node.
output(0));
5196 graph_params.usage_by_bsocket.add(&true_input_bsocket, &lf_node.
output(1));
5200 graph_params.usage_by_bsocket.add(&true_input_bsocket, output_is_used_socket);
5203 graph_params.usage_by_bsocket.add(&false_input_bsocket, output_is_used_socket);
5208 void build_index_switch_node(
const bNode &bnode, BuildGraphParams &graph_params)
5211 bnode, *lf_graph_info_);
5212 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
5213 scope_.add(std::move(lazy_function));
5215 for (
const int i : bnode.input_sockets().drop_back(1).index_range()) {
5216 graph_params.lf_inputs_by_bsocket.add(&bnode.input_socket(i), &lf_node.
input(i));
5217 mapping_->bsockets_by_lf_socket_map.add(&lf_node.
input(i), &bnode.input_socket(i));
5220 graph_params.lf_output_by_bsocket.add(&bnode.output_socket(0), &lf_node.
output(0));
5221 mapping_->bsockets_by_lf_socket_map.add(&lf_node.
output(0), &bnode.output_socket(0));
5223 this->build_index_switch_node_socket_usage(bnode, graph_params);
5226 void build_index_switch_node_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
5228 const bNodeSocket &index_socket = bnode.input_socket(0);
5229 const int items_num = bnode.input_sockets().size() - 1;
5231 lf::OutputSocket *output_is_used = graph_params.usage_by_bsocket.
lookup_default(
5232 &bnode.output_socket(0),
nullptr);
5233 if (output_is_used ==
nullptr) {
5236 graph_params.usage_by_bsocket.add(&index_socket, output_is_used);
5237 if (index_socket.is_directly_linked()) {
5239 auto usage_fn = std::make_unique<LazyFunctionForIndexSwitchSocketUsage>(bnode);
5240 lf::Node &lf_node = graph_params.lf_graph.add_function(*usage_fn);
5241 scope_.add(std::move(usage_fn));
5243 graph_params.lf_inputs_by_bsocket.add(&index_socket, &lf_node.
input(0));
5244 for (
const int i : IndexRange(items_num)) {
5245 graph_params.usage_by_bsocket.add(&bnode.input_socket(i + 1), &lf_node.
output(i));
5250 if (IndexRange(items_num).contains(index)) {
5251 graph_params.usage_by_bsocket.add(&bnode.input_socket(index + 1), output_is_used);
5256 void build_warning_node(
const bNode &bnode, BuildGraphParams &graph_params)
5259 LazyFunction &lazy_function = *lazy_function_ptr;
5260 scope_.add(std::move(lazy_function_ptr));
5262 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
5264 for (
const int i : bnode.input_sockets().index_range()) {
5265 const bNodeSocket &bsocket = bnode.input_socket(i);
5266 lf::InputSocket &lf_socket = lf_node.
input(i);
5267 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
5268 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
5270 for (
const int i : bnode.output_sockets().index_range()) {
5271 const bNodeSocket &bsocket = bnode.output_socket(i);
5272 lf::OutputSocket &lf_socket = lf_node.
output(i);
5273 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
5274 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
5277 const bNodeSocket &output_bsocket = bnode.output_socket(0);
5279 lf::OutputSocket *lf_usage =
nullptr;
5280 if (output_bsocket.is_directly_linked()) {
5282 lf_usage = graph_params.usage_by_bsocket.lookup_default(&output_bsocket,
nullptr);
5286 lf_usage = this->or_socket_usages(group_output_used_sockets_, graph_params);
5289 for (
const bNodeSocket *socket : bnode.input_sockets()) {
5290 graph_params.usage_by_bsocket.add(socket, lf_usage);
5295 void build_menu_switch_node(
const bNode &bnode, BuildGraphParams &graph_params)
5298 bnode, *lf_graph_info_);
5299 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
5300 scope_.add(std::move(lazy_function));
5302 int input_index = 0;
5303 for (
const bNodeSocket *bsocket : bnode.input_sockets().drop_back(1)) {
5304 if (bsocket->is_available()) {
5305 lf::InputSocket &lf_socket = lf_node.
input(input_index);
5306 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
5307 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, bsocket);
5311 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
5312 if (bsocket->is_available()) {
5313 lf::OutputSocket &lf_socket = lf_node.
output(0);
5314 graph_params.lf_output_by_bsocket.add(bsocket, &lf_socket);
5315 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, bsocket);
5320 this->build_menu_switch_node_socket_usage(bnode, graph_params);
5323 void build_menu_switch_node_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
5328 const bNodeSocket *switch_input_bsocket = bnode.input_sockets()[0];
5330 for (
const int i : IndexRange(enum_def.
items_num)) {
5331 input_bsockets[i] = bnode.input_sockets()[i + 1];
5333 const bNodeSocket *output_bsocket = bnode.output_sockets()[0];
5335 lf::OutputSocket *output_is_used_socket = graph_params.usage_by_bsocket.lookup_default(
5336 output_bsocket,
nullptr);
5337 if (output_is_used_socket ==
nullptr) {
5340 graph_params.usage_by_bsocket.add(switch_input_bsocket, output_is_used_socket);
5341 if (switch_input_bsocket->is_directly_linked()) {
5343 std::unique_ptr<LazyFunction> lazy_function =
5345 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
5346 scope_.add(std::move(lazy_function));
5348 graph_params.lf_inputs_by_bsocket.add(switch_input_bsocket, &lf_node.
input(0));
5349 for (
const int i : IndexRange(enum_def.
items_num)) {
5350 graph_params.usage_by_bsocket.add(input_bsockets[i], &lf_node.
output(i));
5354 const int condition =
5356 for (
const int i : IndexRange(enum_def.
items_num)) {
5359 graph_params.usage_by_bsocket.add(input_bsockets[i], output_is_used_socket);
5366 void build_undefined_node(
const bNode &bnode, BuildGraphParams &graph_params)
5368 auto &lazy_function = scope_.construct<LazyFunctionForUndefinedNode>(
5369 bnode, mapping_->lf_index_by_bsocket);
5370 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(lazy_function);
5372 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
5373 const int lf_index = mapping_->lf_index_by_bsocket[bsocket->index_in_tree()];
5374 if (lf_index == -1) {
5377 lf::OutputSocket &lf_socket = lf_node.output(lf_index);
5378 graph_params.lf_output_by_bsocket.add(bsocket, &lf_socket);
5379 mapping_->bsockets_by_lf_socket_map.add(&lf_socket, bsocket);
5383 struct TypeWithLinks {
5384 const bke::bNodeSocketType *typeinfo;
5385 Vector<const bNodeLink *> links;
5388 void insert_links_from_socket(
const bNodeSocket &from_bsocket,
5389 lf::OutputSocket &from_lf_socket,
5390 BuildGraphParams &graph_params)
5392 if (from_bsocket.owner_node().is_dangling_reroute()) {
5396 const bke::bNodeSocketType &from_typeinfo = *from_bsocket.
typeinfo;
5401 for (
const TypeWithLinks &type_with_links : types_with_links) {
5402 if (type_with_links.typeinfo ==
nullptr) {
5405 if (type_with_links.typeinfo->geometry_nodes_cpp_type ==
nullptr) {
5408 const bke::bNodeSocketType &to_typeinfo = *type_with_links.typeinfo;
5409 const CPPType &
to_type = *to_typeinfo.geometry_nodes_cpp_type;
5410 const Span<const bNodeLink *> links = type_with_links.links;
5412 lf::OutputSocket *converted_from_lf_socket = this->insert_type_conversion_if_necessary(
5413 from_lf_socket, from_typeinfo, to_typeinfo, graph_params.lf_graph);
5418 if (converted_from_lf_socket ==
nullptr) {
5419 const void *default_value =
to_type.default_value();
5420 for (lf::InputSocket *to_lf_socket : lf_link_targets) {
5421 to_lf_socket->set_default_value(default_value);
5425 for (lf::InputSocket *to_lf_socket : lf_link_targets) {
5426 graph_params.lf_graph.add_link(*converted_from_lf_socket, *to_lf_socket);
5435 const Span<const bNodeLink *> links_from_bsocket = from_bsocket.directly_linked_links();
5437 for (
const bNodeLink *link : links_from_bsocket) {
5438 if (link->is_muted()) {
5441 if (!link->is_available()) {
5445 bool inserted =
false;
5446 for (TypeWithLinks &types_with_links : types_with_links) {
5447 if (types_with_links.typeinfo == to_bsocket.
typeinfo) {
5448 types_with_links.links.append(link);
5456 types_with_links.append({to_bsocket.
typeinfo, {link}});
5458 return types_with_links;
5462 const BuildGraphParams &graph_params)
5464 if (lf::InputSocket *lf_input_socket = graph_params.lf_input_by_border_link.lookup_default(
5467 return {lf_input_socket};
5471 if (to_bsocket.is_multi_input()) {
5474 for (
const bNodeLink *multi_input_link : to_bsocket.directly_linked_links()) {
5475 if (multi_input_link == &link) {
5478 if (multi_input_link->is_muted() || !multi_input_link->fromsock->is_available() ||
5479 multi_input_link->fromnode->is_dangling_reroute())
5485 if (to_bsocket.owner_node().is_muted()) {
5486 if (link_index == 0) {
5491 lf::InputSocket *lf_multi_input_socket =
5492 graph_params.lf_input_by_multi_input_link.lookup_default(&link,
nullptr);
5493 if (!lf_multi_input_socket) {
5496 return {lf_multi_input_socket};
5505 lf::OutputSocket *insert_type_conversion_if_necessary(lf::OutputSocket &from_socket,
5506 const bke::bNodeSocketType &from_typeinfo,
5507 const bke::bNodeSocketType &to_typeinfo,
5508 lf::Graph &lf_graph)
5510 if (from_typeinfo.type == to_typeinfo.type) {
5511 return &from_socket;
5513 if (from_typeinfo.base_cpp_type && to_typeinfo.base_cpp_type) {
5514 if (conversions_->is_convertible(*from_typeinfo.base_cpp_type, *to_typeinfo.base_cpp_type)) {
5515 const MultiFunction &multi_fn = *conversions_->get_conversion_multi_function(
5516 mf::DataType::ForSingle(*from_typeinfo.base_cpp_type),
5517 mf::DataType::ForSingle(*to_typeinfo.base_cpp_type));
5518 auto &fn = scope_.construct<LazyFunctionForMultiFunctionConversion>(multi_fn);
5520 lf_graph.
add_link(from_socket, conversion_node.input(0));
5521 return &conversion_node.output(0);
5527 void add_default_inputs(BuildGraphParams &graph_params)
5529 for (
auto item : graph_params.lf_inputs_by_bsocket.items()) {
5531 const Span<lf::InputSocket *> lf_sockets = item.value;
5532 for (lf::InputSocket *lf_socket : lf_sockets) {
5533 if (lf_socket->origin() !=
nullptr) {
5537 this->add_default_input(bsocket, *lf_socket, graph_params);
5542 void add_default_input(
const bNodeSocket &input_bsocket,
5543 lf::InputSocket &input_lf_socket,
5544 BuildGraphParams &graph_params)
5546 if (this->try_add_implicit_input(input_bsocket, input_lf_socket, graph_params)) {
5550 if (value.get() ==
nullptr) {
5555 if (!value.type()->is_trivially_destructible()) {
5556 scope_.add_destruct_call([value]()
mutable { value.destruct(); });
5560 bool try_add_implicit_input(
const bNodeSocket &input_bsocket,
5561 lf::InputSocket &input_lf_socket,
5562 BuildGraphParams &graph_params)
5564 const bNode &bnode = input_bsocket.owner_node();
5565 const SocketDeclaration *socket_decl = input_bsocket.
runtime->declaration;
5566 if (socket_decl ==
nullptr) {
5573 if (implicit_input_fn ==
nullptr) {
5576 std::function<void(
void *)> init_fn = [&bnode, implicit_input_fn](
void *r_value) {
5577 (*implicit_input_fn)(bnode, r_value);
5579 const CPPType &type = input_lf_socket.
type();
5580 auto &lazy_function = scope_.construct<LazyFunctionForImplicitInput>(type, std::move(init_fn));
5581 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
5582 graph_params.lf_graph.add_link(lf_node.output(0), input_lf_socket);
5591 void build_attribute_propagation_input_node(lf::Graph &lf_graph)
5593 const aal::RelationsInNode &tree_relations =
5594 btree_.runtime->anonymous_attribute_inferencing->tree_relations;
5595 Vector<int> output_indices;
5596 for (
const aal::PropagateRelation &relation : tree_relations.propagate_relations) {
5600 for (
const int i : output_indices.
index_range()) {
5601 const int output_index = output_indices[i];
5602 const char *name = btree_.interface_outputs()[output_index]->name;
5605 StringRef(
"Propagate: ") + (name ? name :
""));
5606 attribute_set_by_geometry_output_.add(output_index, &lf_socket);
5614 lf::OutputSocket *or_socket_usages(MutableSpan<lf::OutputSocket *> usages,
5615 BuildGraphParams &graph_params)
5620 if (usages.
size() == 1) {
5624 std::sort(usages.
begin(), usages.
end());
5625 return graph_params.socket_usages_combination_cache.lookup_or_add_cb_as(usages, [&]() {
5626 auto &logical_or_fn = scope_.construct<LazyFunctionForLogicalOr>(usages.
size());
5627 lf::Node &logical_or_node = graph_params.lf_graph.add_function(logical_or_fn);
5630 graph_params.lf_graph.add_link(*usages[i], logical_or_node.
input(i));
5632 return &logical_or_node.
output(0);
5636 void build_output_socket_usages(
const bNode &bnode, BuildGraphParams &graph_params)
5639 for (
const bNodeSocket *socket : bnode.output_sockets()) {
5640 if (!socket->is_available()) {
5645 for (
const bNodeLink *link : socket->directly_linked_links()) {
5646 if (!link->is_used()) {
5650 if (lf::OutputSocket *is_used_socket = graph_params.usage_by_bsocket.lookup_default(
5651 &target_socket,
nullptr))
5657 graph_params.usage_by_bsocket.add(socket,
5658 this->or_socket_usages(target_usages, graph_params));
5662 void build_group_input_usages(BuildGraphParams &graph_params)
5664 const Span<const bNode *> group_input_nodes = btree_.group_input_nodes();
5665 for (
const int i : btree_.interface_inputs().index_range()) {
5667 for (
const bNode *group_input_node : group_input_nodes) {
5668 if (lf::OutputSocket *lf_socket = graph_params.usage_by_bsocket.lookup_default(
5669 &group_input_node->output_socket(i),
nullptr))
5675 lf::OutputSocket *lf_socket = this->or_socket_usages(target_usages, graph_params);
5676 lf::InputSocket *lf_group_output =
const_cast<lf::InputSocket *
>(
5677 group_input_usage_sockets_[i]);
5678 InputUsageHint input_usage_hint;
5679 if (lf_socket ==
nullptr) {
5680 static const bool static_false =
false;
5685 graph_params.lf_graph.add_link(*lf_socket, *lf_group_output);
5690 input_usage_hint.output_dependencies = {
5691 group_output_used_sockets_.first_index_of(lf_socket)};
5697 lf_graph_info_->mapping.group_input_usage_hints.append(std::move(input_usage_hint));
5712 void fix_link_cycles(lf::Graph &lf_graph,
const Set<lf::InputSocket *> &socket_usage_inputs)
5715 const int sockets_num = lf_graph.
socket_num();
5717 struct SocketState {
5719 bool in_stack =
false;
5722 Array<SocketState> socket_states(sockets_num);
5725 for (lf::Node *lf_node : lf_graph.
nodes()) {
5726 if (lf_node->is_function()) {
5727 for (lf::OutputSocket *lf_socket : lf_node->outputs()) {
5728 if (lf_socket->
targets().is_empty()) {
5729 lf_sockets_to_check.
append(lf_socket);
5733 if (lf_node->outputs().is_empty()) {
5734 for (lf::InputSocket *lf_socket : lf_node->inputs()) {
5735 lf_sockets_to_check.
append(lf_socket);
5740 while (!lf_sockets_to_check.
is_empty()) {
5741 lf::Socket *lf_inout_socket = lf_sockets_to_check.
last();
5742 lf::Node &lf_node = lf_inout_socket->
node();
5745 if (!
state.in_stack) {
5746 lf_socket_stack.
append(lf_inout_socket);
5747 state.in_stack =
true;
5752 lf::InputSocket &lf_input_socket = lf_inout_socket->
as_input();
5753 if (lf::OutputSocket *lf_origin_socket = lf_input_socket.
origin()) {
5754 lf_origin_sockets.
append(lf_origin_socket);
5758 lf::OutputSocket &lf_output_socket = lf_inout_socket->
as_output();
5760 lf::FunctionNode &lf_function_node =
static_cast<lf::FunctionNode &
>(lf_node);
5761 const lf::LazyFunction &fn = lf_function_node.
function();
5763 lf_output_socket.
index(), [&](
const Span<int> input_indices) {
5764 for (const int input_index : input_indices) {
5765 lf_origin_sockets.append(&lf_node.input(input_index));
5771 bool pushed_socket =
false;
5772 bool detected_cycle =
false;
5773 for (lf::Socket *lf_origin_socket : lf_origin_sockets) {
5774 if (socket_states[lf_origin_socket->index_in_graph()].in_stack) {
5784 detected_cycle =
true;
5785 const int index_in_socket_stack = lf_socket_stack.
first_index_of(lf_origin_socket);
5786 const int index_in_sockets_to_check = lf_sockets_to_check.
first_index_of(
5788 const Span<lf::Socket *> cycle = lf_socket_stack.
as_span().drop_front(
5789 index_in_socket_stack);
5791 bool broke_cycle =
false;
5792 for (lf::Socket *lf_cycle_socket : cycle) {
5793 if (lf_cycle_socket->is_input() &&
5794 socket_usage_inputs.
contains(&lf_cycle_socket->as_input()))
5796 lf::InputSocket &lf_cycle_input_socket = lf_cycle_socket->as_input();
5798 static const bool static_true =
true;
5803 SocketState &lf_cycle_socket_state = socket_states[lf_cycle_socket->index_in_graph()];
5804 lf_cycle_socket_state.in_stack =
false;
5811 lf_socket_stack.
resize(index_in_socket_stack);
5813 lf_sockets_to_check.
resize(index_in_sockets_to_check + 1);
5816 else if (!socket_states[lf_origin_socket->index_in_graph()].done) {
5817 lf_sockets_to_check.
append(lf_origin_socket);
5818 pushed_socket =
true;
5821 if (detected_cycle) {
5824 if (pushed_socket) {
5829 state.in_stack =
false;