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) {
3591 const bNodeTreeZone &zone = *tree_zones_->
zones[zone_i];
3592 switch (zone.output_node->type) {
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>();
3634 zone.output_node->storage);
3636 Vector<lf::GraphInputSocket *> lf_zone_inputs;
3637 Vector<lf::GraphOutputSocket *> lf_zone_outputs;
3639 if (zone.input_node !=
nullptr) {
3640 for (
const bNodeSocket *bsocket : zone.input_node->input_sockets().drop_back(1)) {
3641 zone_info.indices.inputs.main.append(lf_zone_inputs.append_and_get_index(
3642 &lf_graph.add_input(*bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name)));
3643 zone_info.indices.outputs.input_usages.append(lf_zone_outputs.append_and_get_index(
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);
3653 for (
const bNodeSocket *bsocket : zone.output_node->output_sockets().drop_back(1)) {
3654 zone_info.indices.outputs.main.append(lf_zone_outputs.append_and_get_index(
3655 &lf_graph.add_output(*bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name)));
3656 zone_info.indices.inputs.output_usages.append(lf_zone_inputs.append_and_get_index(
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;
3675 if (zone.input_node) {
3676 lf_simulation_input = this->insert_simulation_input_node(
3677 btree_, *zone.input_node, graph_params);
3679 lf::FunctionNode &lf_simulation_output = this->insert_simulation_output_node(*zone.output_node,
3682 for (
const bNodeSocket *bsocket : zone.output_node->input_sockets().drop_back(1)) {
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);
3691 lf_graph.add_link(lf_from, lf_to);
3694 lf_to.set_default_value(lf_to.type().default_value());
3698 this->insert_nodes_and_zones(zone.child_nodes, zone.child_zones, graph_params);
3700 if (zone.input_node) {
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()) {
3719 lf_graph.add_link(lf_simulation_output.output(i),
3720 *lf_zone_outputs[zone_info.indices.outputs.main[i]]);
3723 this->add_default_inputs(graph_params);
3725 Map<int, lf::OutputSocket *> lf_attribute_set_by_field_source_index;
3726 Map<int, lf::OutputSocket *> lf_attribute_set_by_caller_propagation_index;
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;
3732 if (lf_attribute_set_socket.node().is_interface()) {
3733 zone_info.indices.inputs.attributes_by_field_source_index.
add_new(
3734 item.key, lf_zone_inputs.append_and_get_index(&lf_attribute_set_socket));
3737 for (
const auto item : lf_attribute_set_by_caller_propagation_index.items()) {
3738 lf::OutputSocket &lf_attribute_set_socket = *item.value;
3739 if (lf_attribute_set_socket.node().is_interface()) {
3740 zone_info.indices.inputs.attributes_by_caller_propagation_index.
add_new(
3741 item.key, lf_zone_inputs.append_and_get_index(&lf_attribute_set_socket));
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);
3750 lf_graph.update_node_indices();
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,
3756 lf_zone_inputs.as_span(),
3757 lf_zone_outputs.as_span(),
3759 &side_effect_provider,
3761 const auto &zone_function = scope_.
construct<LazyFunctionForSimulationZone>(*zone.output_node,
3763 zone_info.lazy_function = &zone_function;
3765 lf_graph_info_->debug_zone_body_graphs.add(zone.output_node->identifier, &lf_graph);
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};
3802 Vector<lf::GraphInputSocket *> lf_body_inputs;
3803 Vector<lf::GraphOutputSocket *> lf_body_outputs;
3804 ZoneBodyFunction &body_fn = scope_.
construct<ZoneBodyFunction>();
3806 for (
const bNodeSocket *bsocket : zone.input_node->output_sockets()) {
3811 *bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name);
3814 body_fn.indices.inputs.main.append(lf_body_inputs.append_and_get_index(&lf_input));
3815 body_fn.indices.outputs.input_usages.append(
3816 lf_body_outputs.append_and_get_index(&lf_input_usage));
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);
3825 for (
const bNodeSocket *bsocket : zone.output_node->input_sockets()) {
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);
3835 body_fn.indices.outputs.main.append(lf_body_outputs.append_and_get_index(&lf_output));
3836 body_fn.indices.inputs.output_usages.append(
3837 lf_body_inputs.append_and_get_index(&lf_output_usage));
3840 this->insert_nodes_and_zones(zone.child_nodes, zone.child_zones, graph_params);
3842 this->build_output_socket_usages(*zone.input_node, graph_params);
3845 int valid_socket_i = 0;
3846 for (
const bNodeSocket *bsocket : zone.input_node->output_sockets()) {
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;
3859 lf_usage_output.set_default_value(&static_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);
3878 Map<int, lf::OutputSocket *> lf_attribute_set_by_field_source_index;
3879 Map<int, lf::OutputSocket *> lf_attribute_set_by_caller_propagation_index;
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;
3886 if (lf_attribute_set_socket.node().is_interface()) {
3887 body_fn.indices.inputs.attributes_by_field_source_index.
add_new(
3888 item.key, lf_body_inputs.append_and_get_index(&lf_attribute_set_socket));
3891 for (
const auto item : lf_attribute_set_by_caller_propagation_index.items()) {
3892 lf::OutputSocket &lf_attribute_set_socket = *item.value;
3893 if (lf_attribute_set_socket.node().is_interface()) {
3894 body_fn.indices.inputs.attributes_by_caller_propagation_index.
add_new(
3895 item.key, lf_body_inputs.append_and_get_index(&lf_attribute_set_socket));
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);
3904 lf_body_graph.update_node_indices();
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,
3910 lf_body_inputs.as_span(),
3911 lf_body_outputs.as_span(),
3913 &side_effect_provider,
3916 lf_graph_info_->debug_zone_body_graphs.add(zone.output_node->identifier, &lf_body_graph);
3923 void build_zone_border_links_inputs(
const bNodeTreeZone &zone,
3924 lf::Graph &lf_graph,
3925 Vector<lf::GraphInputSocket *> &r_lf_graph_inputs,
3926 Vector<int> &r_indices)
3928 for (
const bNodeLink *border_link : zone.border_links) {
3929 r_indices.append(r_lf_graph_inputs.append_and_get_index(
3930 &lf_graph.add_input(*border_link->tosock->typeinfo->geometry_nodes_cpp_type,
3931 StringRef(
"Link from ") + border_link->fromsock->name)));
3935 void build_zone_border_link_input_usages(
const bNodeTreeZone &zone,
3936 lf::Graph &lf_graph,
3937 Vector<lf::GraphOutputSocket *> &r_lf_graph_outputs,
3938 Vector<int> &r_indices)
3940 for (
const bNodeLink *border_link : zone.border_links) {
3941 r_indices.append(r_lf_graph_outputs.append_and_get_index(&lf_graph.add_output(
3946 void build_attribute_set_inputs_for_zone(
3947 BuildGraphParams &graph_params,
3948 Map<int, lf::OutputSocket *> &lf_attribute_set_by_field_source_index,
3949 Map<int, lf::OutputSocket *> &lf_attribute_set_by_caller_propagation_index)
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 =
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());
3993 Vector<lf::GraphInputSocket *> attribute_set_inputs;
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);
4037 Vector<lf::GraphInputSocket *> lf_output_usages;
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(
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);
4064 Map<int, lf::OutputSocket *> lf_attribute_set_by_field_source_index;
4065 Map<int, lf::OutputSocket *> lf_attribute_set_by_caller_propagation_index;
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);
4079 lf_graph.update_node_indices();
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;
4091 Vector<const lf::GraphInputSocket *> lf_graph_inputs;
4092 Vector<const lf::GraphOutputSocket *> lf_graph_outputs;
4094 lf_graph_inputs.extend(group_input_sockets_);
4095 function.inputs.main = lf_graph_inputs.index_range().take_back(group_input_sockets_.
size());
4097 lf_graph_inputs.extend(group_output_used_sockets_);
4098 function.inputs.output_usages = lf_graph_inputs.index_range().take_back(
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);
4105 function.inputs.attributes_to_propagate.range = lf_graph_inputs.index_range().take_back(
4106 attribute_set_by_geometry_output_.
size());
4108 lf_graph_outputs.extend(standard_group_output_sockets_);
4109 function.outputs.main = lf_graph_outputs.index_range().take_back(
4110 standard_group_output_sockets_.
size());
4112 lf_graph_outputs.extend(group_input_usage_sockets_);
4113 function.outputs.input_usages = lf_graph_outputs.index_range().take_back(
4114 group_input_usage_sockets_.
size());
4116 Vector<const lf::FunctionNode *> &local_side_effect_nodes =
4117 scope_.
construct<Vector<const lf::FunctionNode *>>();
4118 for (
const bNode *bnode : btree_.nodes_by_type(
"GeometryNodeWarning")) {
4119 if (bnode->output_socket(0).is_directly_linked()) {
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,
4148 Map<int, lf::OutputSocket *> &lf_attribute_set_by_field_source_index,
4149 Map<int, lf::OutputSocket *> &lf_attribute_set_by_caller_propagation_index)
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 =
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 =
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(
4200 const Map<const bNodeSocket *, lf::InputSocket *>
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_
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(
4222 const Map<const bNodeSocket *, lf::InputSocket *>
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(
4230 lf_attribute_set_input_by_output_geometry_bsocket.keys())
4232 all_required_caller_propagation_indices |=
4233 attribute_inferencing_
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,
4251 const Map<int, lf::OutputSocket *> &lf_attribute_set_by_field_source_index,
4252 const Map<int, lf::OutputSocket *> &lf_attribute_set_by_caller_propagation_index)
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;
4262 Vector<lf::OutputSocket *> lf_attribute_set_sockets;
4264 const BoundedBitSpan required_fields =
4265 attribute_inferencing_
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_
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;
4299 lf_attribute_set_input.set_default_value(&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;
4327 Map<const bNode *, const bNodeTreeZone *> zone_by_output;
4328 for (
const bNodeTreeZone *zone : zones) {
4329 nodes_to_insert.append(zone->output_node);
4330 zone_by_output.add(zone->output_node, zone);
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()) {
4357 const bNodeLink &border_link = *zone.border_links[border_link_i];
4359 const Vector<lf::InputSocket *> lf_link_targets = this->find_link_targets(border_link,
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;
4393 lf_use_input.set_default_value(&static_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];
4414 Vector<lf::OutputSocket *, 16> key = lf_attribute_set_sockets;
4415 std::sort(key.begin(), key.end());
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;
4427 lf_use_input.set_default_value(&static_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;
4448 for (
const bNodeSocket *bsocket : child_zone.input_node->input_sockets()) {
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]);
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;
4464 for (
const bNodeSocket *bsocket : child_zone.output_node->output_sockets()) {
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]);
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;
4482 lf_usage_input.set_default_value(&static_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) {
4546 lf_socket.set_default_value(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>(
4637 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
4638 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
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);
4647 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
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);
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;
4675 Vector<lf::OutputSocket *> lf_socket_usages;
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);
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);
4725 void build_group_output_node(
const bNode &bnode, BuildGraphParams &graph_params)
4727 Vector<lf::GraphOutputSocket *> lf_graph_outputs;
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);
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);
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);
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 =
4783 if (lf_input_index != -1) {
4784 lf::InputSocket &lf_input = lf_node.input(lf_input_index);
4785 lf_input.set_default_value(&static_false);
4786 graph_params.socket_usage_inputs.add(&lf_input);
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) {
4818 Vector<lf::OutputSocket *> output_usages;
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(
4833 &lf_group_node.output(
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 =
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;
4853 lf_socket.set_default_value(&static_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()) {
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);
4880 const void *default_value = lf_multi_input_socket.type().default_value();
4881 lf_multi_input_socket.set_default_value(default_value);
4885 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
4889 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
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);
4899 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
4901 const int lf_input_index =
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;
4912 lf_input_socket.set_default_value(&static_false);
4914 graph_params.socket_usage_inputs.add_new(&lf_node.input(lf_input_index));
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()) {
4937 Vector<lf::OutputSocket *> output_usages;
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))
4945 output_usages.append_non_duplicates(is_used_socket);
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>(
4968 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(lazy_function);
4970 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
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);
4980 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
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);
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>(
4997 lf::FunctionNode &lf_viewer_node = graph_params.lf_graph.add_function(lazy_function);
4999 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
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);
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>(
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);
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);
5049 this->build_gizmo_node_socket_usage(bnode, graph_params, 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(
5084 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
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(
5091 graph_params.lf_output_by_bsocket.
add(&bsocket, &lf_socket);
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(
5109 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
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(
5116 graph_params.lf_output_by_bsocket.
add(&bsocket, &lf_socket);
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(
5135 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
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(
5142 graph_params.lf_output_by_bsocket.
add(&bsocket, &lf_socket);
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));
5172 graph_params.lf_output_by_bsocket.add(&bnode.output_socket(0), &lf_node.output(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));
5220 graph_params.lf_output_by_bsocket.add(&bnode.output_socket(0), &lf_node.output(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);
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);
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);
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);
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];
5329 Vector<const bNodeSocket *> input_bsockets(enum_def.
items_num);
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>(
5370 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(lazy_function);
5372 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
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);
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;
5399 const Vector<TypeWithLinks> types_with_links = this->group_link_targets_by_type(from_bsocket);
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);
5416 const Vector<lf::InputSocket *> lf_link_targets = this->find_link_targets(*link,
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);
5433 Vector<TypeWithLinks> group_link_targets_by_type(
const bNodeSocket &from_bsocket)
5435 const Span<const bNodeLink *> links_from_bsocket = from_bsocket.directly_linked_links();
5436 Vector<TypeWithLinks> types_with_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;
5461 Vector<lf::InputSocket *> find_link_targets(
const bNodeLink &link,
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)) {
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);
5519 lf::Node &conversion_node = lf_graph.add_function(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) {
5554 input_lf_socket.set_default_value(value.get());
5555 if (!value.type()->is_trivially_destructible()) {
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) {
5597 output_indices.append_non_duplicates(relation.to_geometry_output);
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)
5617 if (usages.is_empty()) {
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);
5629 for (
const int i : usages.index_range()) {
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()) {
5644 Vector<lf::OutputSocket *> target_usages;
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))
5653 target_usages.append_non_duplicates(is_used_socket);
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()) {
5666 Vector<lf::OutputSocket *> target_usages;
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))
5671 target_usages.append_non_duplicates(lf_socket);
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;
5681 lf_group_output->set_default_value(&static_false);
5685 graph_params.lf_graph.add_link(*lf_socket, *lf_group_output);
5686 if (lf_socket->node().is_interface()) {
5690 input_usage_hint.output_dependencies = {
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)
5714 lf_graph.update_socket_indices();
5715 const int sockets_num = lf_graph.socket_num();
5717 struct SocketState {
5719 bool in_stack =
false;
5722 Array<SocketState> socket_states(sockets_num);
5724 Vector<lf::Socket *> lf_sockets_to_check;
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);
5739 Vector<lf::Socket *> lf_socket_stack;
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();
5743 SocketState &
state = socket_states[lf_inout_socket->index_in_graph()];
5745 if (!
state.in_stack) {
5746 lf_socket_stack.append(lf_inout_socket);
5747 state.in_stack =
true;
5750 Vector<lf::Socket *, 16> lf_origin_sockets;
5751 if (lf_inout_socket->is_input()) {
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();
5759 if (lf_node.is_function()) {
5760 lf::FunctionNode &lf_function_node =
static_cast<lf::FunctionNode &
>(lf_node);
5761 const lf::LazyFunction &fn = lf_function_node.function();
5762 fn.possible_output_dependencies(
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();
5797 lf_graph.clear_origin(lf_cycle_input_socket);
5798 static const bool static_true =
true;
5799 lf_cycle_input_socket.set_default_value(&static_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;
5830 lf_sockets_to_check.pop_last();
5831 lf_socket_stack.pop_last();