1975 std::optional<BuildGraphParams> root_graph_build_params_;
2009 reference_lifetimes_(*btree.runtime->reference_lifetimes_info),
2010 scope_(lf_graph_info.scope),
2012 lf_graph_info_(&lf_graph_info)
2018 btree_.ensure_topology_cache();
2019 btree_.ensure_interface_cache();
2021 mapping_ = &lf_graph_info_->mapping;
2023 tree_zones_ = btree_.zones();
2025 this->initialize_mapping_arrays();
2026 this->build_zone_functions();
2027 this->build_root_graph();
2028 this->build_geometry_nodes_group_function();
2032 void initialize_mapping_arrays()
2035 btree_.all_output_sockets().size());
2038 btree_.all_output_sockets().size());
2047 void build_zone_functions()
2051 const Array<int> zone_build_order = this->compute_zone_build_order();
2053 for (
const int zone_i : zone_build_order) {
2057 this->build_simulation_zone_function(zone);
2061 this->build_repeat_zone_function(zone);
2065 this->build_foreach_geometry_element_zone_function(zone);
2068 this->build_closure_zone_function(zone);
2078 Array<int> compute_zone_build_order()
2081 Array<int> zone_build_order(tree_zones_->
zones.size());
2082 array_utils::fill_index_range<int>(zone_build_order);
2084 zone_build_order.begin(), zone_build_order.end(), [&](
const int zone_a,
const int zone_b) {
2085 return tree_zones_->zones[zone_a]->depth > tree_zones_->zones[zone_b]->depth;
2087 return zone_build_order;
2094 void build_simulation_zone_function(
const bNodeTreeZone &zone)
2096 const int zone_i = zone.
index;
2097 ZoneBuildInfo &zone_info = zone_build_infos_[zone_i];
2098 lf::Graph &lf_graph = scope_.
construct<lf::Graph>();
2108 &lf_graph.
add_input(*bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name)));
2114 this->build_zone_border_links_inputs(
2115 zone, lf_graph, lf_zone_inputs, zone_info.indices.inputs.border_links);
2116 this->build_zone_border_link_input_usages(
2117 zone, lf_graph, lf_zone_outputs, zone_info.indices.outputs.border_link_usages);
2121 &lf_graph.
add_output(*bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name)));
2126 lf::Node &lf_simulation_usage_node = [&]() -> lf::Node & {
2127 auto &lazy_function = scope_.
construct<LazyFunctionForSimulationInputsUsage>(
2129 lf::Node &lf_node = lf_graph.
add_function(lazy_function);
2131 for (
const int i : zone_info.indices.outputs.input_usages) {
2138 BuildGraphParams graph_params{lf_graph};
2140 lf::FunctionNode *lf_simulation_input =
nullptr;
2142 lf_simulation_input = this->insert_simulation_input_node(
2145 lf::FunctionNode &lf_simulation_output = this->insert_simulation_output_node(
2149 graph_params.usage_by_bsocket.add(bsocket, &lf_simulation_usage_node.
output(1));
2153 for (
const int i : IndexRange(sim_output_storage.items_num)) {
2154 lf::InputSocket &lf_to = lf_simulation_output.
input(
i + 1);
2155 if (lf_simulation_input) {
2156 lf::OutputSocket &lf_from = lf_simulation_input->
output(
i + 1);
2167 this->build_output_socket_usages(*zone.
input_node(), graph_params);
2169 for (
const auto item : graph_params.lf_output_by_bsocket.items()) {
2170 this->insert_links_from_socket(*item.key, *item.value, graph_params);
2173 this->link_border_link_inputs_and_usages(zone,
2175 zone_info.indices.inputs.border_links,
2177 zone_info.indices.outputs.border_link_usages,
2180 for (
const int i : zone_info.indices.inputs.main) {
2184 for (
const int i : zone_info.indices.outputs.main.index_range()) {
2186 *lf_zone_outputs[zone_info.indices.outputs.main[
i]]);
2189 this->add_default_inputs(graph_params);
2191 Map<ReferenceSetIndex, lf::OutputSocket *> lf_reference_sets;
2192 this->build_reference_set_for_zone(graph_params, lf_reference_sets);
2193 for (
const auto item : lf_reference_sets.
items()) {
2194 lf::OutputSocket &lf_attribute_set_socket = *item.value;
2196 zone_info.indices.inputs.reference_sets.add_new(
2200 this->link_reference_sets(graph_params, lf_reference_sets);
2201 this->fix_link_cycles(lf_graph, graph_params.socket_usage_inputs);
2205 auto &logger = scope_.
construct<GeometryNodesLazyFunctionLogger>(*lf_graph_info_);
2206 auto &side_effect_provider = scope_.
construct<GeometryNodesLazyFunctionSideEffectProvider>();
2208 const auto &lf_graph_fn = scope_.
construct<lf::GraphExecutor>(lf_graph,
2212 &side_effect_provider,
2214 const auto &zone_function = scope_.
construct<LazyFunctionForSimulationZone>(
2216 zone_info.lazy_function = &zone_function;
2225 void build_repeat_zone_function(
const bNodeTreeZone &zone)
2227 ZoneBuildInfo &zone_info = zone_build_infos_[zone.
index];
2229 ZoneBodyFunction &body_fn = this->build_zone_body_function(
2230 zone,
"Repeat Body", &scope_.
construct<GeometryNodesLazyFunctionSideEffectProvider>());
2233 zone_info.lazy_function = &zone_fn;
2236 void build_foreach_geometry_element_zone_function(
const bNodeTreeZone &zone)
2238 ZoneBuildInfo &zone_info = zone_build_infos_[zone.
index];
2240 ZoneBodyFunction &body_fn = this->build_zone_body_function(
2241 zone,
"Foreach Body", &scope_.
construct<GeometryNodesLazyFunctionSideEffectProvider>());
2244 scope_, btree_, zone, zone_info, body_fn);
2245 zone_info.lazy_function = &zone_fn;
2248 void build_closure_zone_function(
const bNodeTreeZone &zone)
2250 ZoneBuildInfo &zone_info = zone_build_infos_[zone.
index];
2252 ZoneBodyFunction &body_fn = this->build_zone_body_function(
2253 zone,
"Closure Body", &scope_.
construct<GeometryNodesLazyFunctionSideEffectProvider>());
2255 zone_info.lazy_function = &zone_fn;
2261 ZoneBodyFunction &build_zone_body_function(
2262 const bNodeTreeZone &zone,
2263 const StringRef name,
2264 const lf::GraphExecutorSideEffectProvider *side_effect_provider)
2266 lf::Graph &lf_body_graph = scope_.
construct<lf::Graph>(name);
2268 BuildGraphParams graph_params{lf_body_graph};
2272 ZoneBodyFunction &body_fn = scope_.
construct<ZoneBodyFunction>();
2279 *bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name);
2283 body_fn.indices.outputs.input_usages.append(
2285 graph_params.lf_output_by_bsocket.add_new(bsocket, &lf_input);
2288 this->build_zone_border_links_inputs(
2289 zone, lf_body_graph, lf_body_inputs, body_fn.indices.inputs.border_links);
2290 this->build_zone_border_link_input_usages(
2291 zone, lf_body_graph, lf_body_outputs, body_fn.indices.outputs.border_link_usages);
2298 *bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name);
2301 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_output);
2302 graph_params.usage_by_bsocket.add(bsocket, &lf_output_usage);
2304 body_fn.indices.inputs.output_usages.append(
2310 this->build_output_socket_usages(*zone.
input_node(), graph_params);
2313 int valid_socket_i = 0;
2318 lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.
lookup_default(bsocket,
2321 *lf_body_outputs[body_fn.indices.outputs.input_usages[valid_socket_i]];
2323 lf_body_graph.
add_link(*lf_usage, lf_usage_output);
2326 static const bool static_false =
false;
2333 for (
const auto item : graph_params.lf_output_by_bsocket.items()) {
2334 this->insert_links_from_socket(*item.key, *item.value, graph_params);
2337 this->link_border_link_inputs_and_usages(zone,
2339 body_fn.indices.inputs.border_links,
2341 body_fn.indices.outputs.border_link_usages,
2344 this->add_default_inputs(graph_params);
2346 Map<int, lf::OutputSocket *> lf_reference_sets;
2347 this->build_reference_set_for_zone(graph_params, lf_reference_sets);
2348 for (
const auto item : lf_reference_sets.
items()) {
2349 lf::OutputSocket &lf_attribute_set_socket = *item.value;
2351 body_fn.indices.inputs.reference_sets.add_new(
2355 this->link_reference_sets(graph_params, lf_reference_sets);
2356 this->fix_link_cycles(lf_body_graph, graph_params.socket_usage_inputs);
2360 auto &logger = scope_.
construct<GeometryNodesLazyFunctionLogger>(*lf_graph_info_);
2362 body_fn.function = &scope_.
construct<lf::GraphExecutor>(lf_body_graph,
2366 side_effect_provider,
2376 void build_zone_border_links_inputs(
const bNodeTreeZone &zone,
2377 lf::Graph &lf_graph,
2379 Vector<int> &r_indices)
2384 StringRef(
"Link from ") + border_link->
fromsock->
name)));
2388 void build_zone_border_link_input_usages(
const bNodeTreeZone &zone,
2389 lf::Graph &lf_graph,
2391 Vector<int> &r_indices)
2399 void build_reference_set_for_zone(BuildGraphParams &graph_params,
2400 Map<ReferenceSetIndex, lf::OutputSocket *> &lf_reference_sets)
2403 this->find_all_required_reference_sets(graph_params.lf_reference_set_input_by_output,
2404 graph_params.lf_reference_set_inputs);
2406 auto add_reference_set_zone_input = [&](
const ReferenceSetIndex reference_set_i) {
2409 lf_reference_sets.
add(reference_set_i, &lf_graph_input);
2412 VectorSet<ReferenceSetIndex> input_reference_sets;
2413 for (
const ReferenceSetIndex reference_set_i : all_required_reference_sets) {
2414 const ReferenceSetInfo &reference_set = reference_lifetimes_.
reference_sets[reference_set_i];
2415 switch (reference_set.type) {
2416 case ReferenceSetType::GroupOutputData:
2417 case ReferenceSetType::GroupInputReferenceSet: {
2418 add_reference_set_zone_input(reference_set_i);
2421 case ReferenceSetType::LocalReferenceSet:
2422 case ReferenceSetType::ClosureOutputData:
2423 case ReferenceSetType::ClosureInputReferenceSet: {
2424 const bNodeSocket &bsocket = *reference_set.socket;
2425 if (lf::OutputSocket *lf_socket = graph_params.lf_output_by_bsocket.lookup_default(
2428 lf::OutputSocket *lf_usage_socket = graph_params.usage_by_bsocket.
lookup_default(
2430 lf::OutputSocket &lf_reference_set_socket = this->get_extracted_reference_set(
2431 *lf_socket, lf_usage_socket, graph_params);
2432 lf_reference_sets.
add(reference_set_i, &lf_reference_set_socket);
2436 add_reference_set_zone_input(reference_set_i);
2448 void build_root_graph()
2450 lf::Graph &lf_graph = lf_graph_info_->graph;
2452 this->build_main_group_inputs(lf_graph);
2453 if (btree_.group_output_node() ==
nullptr) {
2454 this->build_fallback_group_outputs(lf_graph);
2460 StringRef(
"Usage: ") + (interface_input->name ? interface_input->name :
""));
2461 group_input_usage_sockets_.
append(&lf_socket);
2468 StringRef(
"Usage: ") + (interface_output->name ? interface_output->name :
""));
2469 group_output_used_sockets_.
append(&lf_socket);
2470 lf_output_usages.
append(&lf_socket);
2473 BuildGraphParams &graph_params = root_graph_build_params_.emplace(lf_graph);
2474 if (
const bNode *group_output_bnode = btree_.group_output_node()) {
2475 for (
const bNodeSocket *bsocket : group_output_bnode->input_sockets().drop_back(1)) {
2476 graph_params.usage_by_bsocket.add(bsocket, lf_output_usages[bsocket->index()]);
2480 this->insert_nodes_and_zones(
2483 for (
const auto item : graph_params.lf_output_by_bsocket.items()) {
2484 this->insert_links_from_socket(*item.key, *item.value, graph_params);
2486 this->build_group_input_usages(graph_params);
2487 this->add_default_inputs(graph_params);
2489 this->build_root_reference_set_inputs(lf_graph);
2491 Map<ReferenceSetIndex, lf::OutputSocket *> lf_reference_sets;
2492 this->build_reference_sets_outside_of_zones(graph_params, lf_reference_sets);
2493 this->link_reference_sets(graph_params, lf_reference_sets);
2495 this->fix_link_cycles(lf_graph, graph_params.socket_usage_inputs);
2500 lf_graph_info_->num_inline_nodes_approximate += lf_graph.
nodes().size();
2507 void build_geometry_nodes_group_function()
2509 GeometryNodesGroupFunction &function = lf_graph_info_->function;
2514 lf_graph_inputs.
extend(group_input_sockets_);
2517 lf_graph_inputs.
extend(group_output_used_sockets_);
2519 group_output_used_sockets_.
size());
2521 for (
auto [output_index, lf_socket] : reference_set_by_output_.
items()) {
2522 lf_graph_inputs.
append(lf_socket);
2523 function.inputs.references_to_propagate.geometry_outputs.append(output_index);
2526 reference_set_by_output_.
size());
2528 lf_graph_outputs.
extend(standard_group_output_sockets_);
2530 standard_group_output_sockets_.
size());
2532 lf_graph_outputs.
extend(group_input_usage_sockets_);
2534 group_input_usage_sockets_.
size());
2538 for (
const bNode *bnode : btree_.nodes_by_type(
"GeometryNodeWarning")) {
2539 if (bnode->output_socket(0).is_directly_linked()) {
2551 const lf::Socket *lf_socket = root_graph_build_params_->lf_inputs_by_bsocket.lookup(
2552 &bnode->input_socket(0))[0];
2553 const lf::FunctionNode &lf_node =
static_cast<const lf::FunctionNode &
>(lf_socket->
node());
2554 local_side_effect_nodes.
append(&lf_node);
2557 function.function = &scope_.
construct<lf::GraphExecutor>(
2558 lf_graph_info_->graph,
2559 std::move(lf_graph_inputs),
2560 std::move(lf_graph_outputs),
2561 &scope_.
construct<GeometryNodesLazyFunctionLogger>(*lf_graph_info_),
2562 &scope_.
construct<GeometryNodesLazyFunctionSideEffectProvider>(local_side_effect_nodes),
2566 void build_reference_sets_outside_of_zones(
2567 BuildGraphParams &graph_params,
2568 Map<ReferenceSetIndex, lf::OutputSocket *> &lf_reference_sets)
2571 this->find_all_required_reference_sets(graph_params.lf_reference_set_input_by_output,
2572 graph_params.lf_reference_set_inputs);
2573 for (
const ReferenceSetIndex reference_set_i : all_required_reference_sets) {
2574 const ReferenceSetInfo &reference_set = reference_lifetimes_.
reference_sets[reference_set_i];
2575 switch (reference_set.type) {
2576 case ReferenceSetType::LocalReferenceSet: {
2577 const bNodeSocket &bsocket = *reference_set.socket;
2578 lf::OutputSocket &lf_socket = *graph_params.lf_output_by_bsocket.lookup(&bsocket);
2579 lf::OutputSocket *lf_usage_socket = graph_params.usage_by_bsocket.
lookup_default(
2581 lf::OutputSocket &lf_reference_set_socket = this->get_extracted_reference_set(
2582 lf_socket, lf_usage_socket, graph_params);
2583 lf_reference_sets.
add_new(reference_set_i, &lf_reference_set_socket);
2586 case ReferenceSetType::GroupInputReferenceSet: {
2587 const int group_input_i = reference_set.index;
2589 lf::OutputSocket *lf_usage_socket = group_input_usage_sockets_[group_input_i]->origin();
2590 lf::OutputSocket &lf_reference_set_socket = this->get_extracted_reference_set(
2591 lf_socket, lf_usage_socket, graph_params);
2592 lf_reference_sets.
add_new(reference_set_i, &lf_reference_set_socket);
2595 case ReferenceSetType::GroupOutputData: {
2596 const int group_output_i = reference_set.index;
2599 lf_reference_sets.
add_new(reference_set_i, lf_reference_set_socket);
2602 case ReferenceSetType::ClosureOutputData:
2603 case ReferenceSetType::ClosureInputReferenceSet: {
2613 const Map<const bNodeSocket *, lf::InputSocket *> &lf_reference_set_input_by_output,
2614 const MultiValueMap<ReferenceSetIndex, lf::InputSocket *> &lf_reference_set_inputs)
2616 BitVector<> all_required_reference_sets(reference_lifetimes_.
reference_sets.size(),
false);
2617 for (
const bNodeSocket *bsocket : lf_reference_set_input_by_output.
keys()) {
2618 all_required_reference_sets |=
2621 for (
const ReferenceSetIndex reference_set_i : lf_reference_set_inputs.
keys()) {
2622 all_required_reference_sets[reference_set_i].set();
2625 bits::foreach_1_index(all_required_reference_sets,
2626 [&](
const int index) {
indices.append(index); });
2630 void link_reference_sets(BuildGraphParams &graph_params,
2631 const Map<ReferenceSetIndex, lf::OutputSocket *> &lf_reference_sets)
2635 for (
const auto &item : graph_params.lf_reference_set_input_by_output.items()) {
2637 lf::InputSocket &lf_reference_set_input = *item.value;
2640 const BoundedBitSpan required_reference_sets =
2642 bits::foreach_1_index(required_reference_sets, [&](
const ReferenceSetIndex reference_set_i) {
2643 const ReferenceSetInfo &reference_set =
2645 if (reference_set.type == ReferenceSetType::LocalReferenceSet) {
2646 if (&reference_set.socket->owner_node() == &output_bsocket.owner_node()) {
2651 lf_reference_sets_to_join.
append(lf_reference_sets.
lookup(reference_set_i));
2654 if (lf::OutputSocket *lf_joined_reference_set = this->join_reference_sets(
2655 lf_reference_sets_to_join,
2656 join_reference_sets_cache,
2657 graph_params.lf_graph,
2658 graph_params.socket_usage_inputs))
2660 graph_params.lf_graph.add_link(*lf_joined_reference_set, lf_reference_set_input);
2663 static const GeometryNodesReferenceSet empty_reference_set;
2669 for (
const auto &item : graph_params.lf_reference_set_inputs.items()) {
2671 lf::OutputSocket &lf_reference_set = *lf_reference_sets.
lookup(reference_set_i);
2672 for (lf::InputSocket *lf_reference_set_input : item.value) {
2673 graph_params.lf_graph.add_link(lf_reference_set, *lf_reference_set_input);
2678 void insert_nodes_and_zones(
const Span<const bNode *> bnodes,
2679 const Span<const bNodeTreeZone *> zones,
2680 BuildGraphParams &graph_params)
2682 Vector<const bNode *> nodes_to_insert = bnodes;
2683 Map<const bNode *, const bNodeTreeZone *> zone_by_output;
2684 for (
const bNodeTreeZone *zone : zones) {
2689 std::sort(nodes_to_insert.
begin(), nodes_to_insert.
end(), [](
const bNode *a,
const bNode *
b) {
2690 return a->runtime->toposort_right_to_left_index < b->runtime->toposort_right_to_left_index;
2693 for (
const bNode *bnode : nodes_to_insert) {
2694 this->build_output_socket_usages(*bnode, graph_params);
2695 if (
const bNodeTreeZone *zone = zone_by_output.
lookup_default(bnode,
nullptr)) {
2696 this->insert_child_zone_node(*zone, graph_params);
2699 this->insert_node_in_graph(*bnode, graph_params);
2704 void link_border_link_inputs_and_usages(
const bNodeTreeZone &zone,
2705 const Span<lf::GraphInputSocket *> lf_inputs,
2706 const Span<int> lf_border_link_input_indices,
2707 const Span<lf::GraphOutputSocket *> lf_usages,
2708 const Span<int> lf_border_link_usage_indices,
2709 BuildGraphParams &graph_params)
2711 lf::Graph &lf_graph = graph_params.lf_graph;
2712 for (
const int border_link_i : zone.
border_links.index_range()) {
2717 for (lf::InputSocket *lf_to : lf_link_targets) {
2718 lf_graph.
add_link(lf_from, *lf_to);
2721 *lf_usages[lf_border_link_usage_indices[border_link_i]];
2722 if (lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(
2723 border_link.
tosock,
nullptr))
2725 lf_graph.
add_link(*lf_usage, lf_usage_output);
2728 static const bool static_false =
false;
2734 lf::OutputSocket &get_extracted_reference_set(lf::OutputSocket &lf_field_socket,
2735 lf::OutputSocket *lf_usage_socket,
2736 BuildGraphParams &graph_params)
2738 auto &lazy_function = scope_.
construct<LazyFunctionForExtractingReferenceSet>();
2739 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
2740 lf::InputSocket &lf_use_input = lf_node.
input(0);
2741 lf::InputSocket &lf_field_input = lf_node.input(1);
2742 graph_params.socket_usage_inputs.add_new(&lf_use_input);
2743 if (lf_usage_socket) {
2744 graph_params.lf_graph.add_link(*lf_usage_socket, lf_use_input);
2747 static const bool static_false =
false;
2750 graph_params.lf_graph.add_link(lf_field_socket, lf_field_input);
2751 return lf_node.output(0);
2757 lf::OutputSocket *join_reference_sets(
const Span<lf::OutputSocket *> lf_reference_set_sockets,
2758 JoinReferenceSetsCache &cache,
2759 lf::Graph &lf_graph,
2760 Set<lf::InputSocket *> &socket_usage_inputs)
2762 if (lf_reference_set_sockets.
is_empty()) {
2765 if (lf_reference_set_sockets.
size() == 1) {
2766 return lf_reference_set_sockets[0];
2771 return cache.lookup_or_add_cb(key, [&]() {
2772 const auto &lazy_function = LazyFunctionForJoinReferenceSets::get_cached(
2773 lf_reference_set_sockets.
size(), scope_);
2774 lf::Node &lf_node = lf_graph.
add_function(lazy_function);
2775 for (
const int i : lf_reference_set_sockets.
index_range()) {
2776 lf::OutputSocket &lf_reference_set_socket = *lf_reference_set_sockets[
i];
2777 lf::InputSocket &lf_use_input = lf_node.
input(lazy_function.get_use_input(
i));
2781 static const bool static_true =
true;
2784 socket_usage_inputs.
add(&lf_use_input);
2785 lf::InputSocket &lf_reference_set_input = lf_node.
input(
2786 lazy_function.get_reference_set_input(
i));
2787 lf_graph.
add_link(lf_reference_set_socket, lf_reference_set_input);
2789 return &lf_node.
output(0);
2793 void insert_child_zone_node(
const bNodeTreeZone &child_zone, BuildGraphParams &graph_params)
2795 const int child_zone_i = child_zone.
index;
2796 ZoneBuildInfo &child_zone_info = zone_build_infos_[child_zone_i];
2797 lf::FunctionNode &child_zone_node = graph_params.lf_graph.add_function(
2798 *child_zone_info.lazy_function);
2799 mapping_->
zone_node_map.add_new(&child_zone, &child_zone_node);
2802 int valid_socket_i = 0;
2807 lf::InputSocket &lf_input_socket = child_zone_node.
input(
2808 child_zone_info.indices.inputs.main[valid_socket_i]);
2809 lf::OutputSocket &lf_usage_socket = child_zone_node.
output(
2810 child_zone_info.indices.outputs.input_usages[valid_socket_i]);
2812 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_input_socket);
2813 graph_params.usage_by_bsocket.add(bsocket, &lf_usage_socket);
2818 int valid_socket_i = 0;
2823 lf::OutputSocket &lf_output_socket = child_zone_node.
output(
2824 child_zone_info.indices.outputs.main[valid_socket_i]);
2825 lf::InputSocket &lf_usage_input = child_zone_node.
input(
2826 child_zone_info.indices.inputs.output_usages[valid_socket_i]);
2828 graph_params.lf_output_by_bsocket.add(bsocket, &lf_output_socket);
2829 graph_params.socket_usage_inputs.add(&lf_usage_input);
2830 if (lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(bsocket,
2833 graph_params.lf_graph.add_link(*lf_usage, lf_usage_input);
2836 static const bool static_false =
false;
2843 const Span<const bNodeLink *> child_border_links = child_zone.
border_links;
2844 for (
const int child_border_link_i : child_border_links.
index_range()) {
2845 lf::InputSocket &child_border_link_input = child_zone_node.
input(
2846 child_zone_info.indices.inputs.border_links[child_border_link_i]);
2847 const bNodeLink &link = *child_border_links[child_border_link_i];
2848 graph_params.lf_input_by_border_link.add(&link, &child_border_link_input);
2849 lf::OutputSocket &lf_usage = child_zone_node.
output(
2850 child_zone_info.indices.outputs.border_link_usages[child_border_link_i]);
2851 graph_params.lf_inputs_by_bsocket.add(link.
tosock, &child_border_link_input);
2852 graph_params.usage_by_bsocket.add(link.
tosock, &lf_usage);
2855 for (
const auto &item : child_zone_info.indices.inputs.reference_sets.items()) {
2857 const int child_zone_input_i = item.value;
2858 lf::InputSocket &lf_reference_set_input = child_zone_node.
input(child_zone_input_i);
2860 graph_params.lf_reference_set_inputs.add(reference_set_i, &lf_reference_set_input);
2864 void build_main_group_inputs(lf::Graph &lf_graph)
2866 const Span<const bNodeTreeInterfaceSocket *> interface_inputs = btree_.interface_inputs();
2868 const bke::bNodeSocketType *typeinfo = interface_input->socket_typeinfo();
2870 *typeinfo->geometry_nodes_cpp_type, interface_input->name ? interface_input->name :
"");
2871 group_input_sockets_.
append(&lf_socket);
2879 void build_fallback_group_outputs(lf::Graph &lf_graph)
2882 const bke::bNodeSocketType *typeinfo = interface_output->socket_typeinfo();
2883 const CPPType &type = *typeinfo->geometry_nodes_cpp_type;
2885 type, interface_output->name ? interface_output->name :
"");
2886 const void *default_value = typeinfo->geometry_nodes_default_cpp_value;
2887 if (default_value ==
nullptr) {
2891 standard_group_output_sockets_.
append(&lf_socket);
2895 void insert_node_in_graph(
const bNode &bnode, BuildGraphParams &graph_params)
2897 const bke::bNodeType *node_type = bnode.
typeinfo;
2898 if (node_type ==
nullptr) {
2901 if (bnode.is_muted()) {
2902 this->build_muted_node(bnode, graph_params);
2905 if (bnode.is_group()) {
2908 this->build_group_node(bnode, graph_params);
2911 switch (node_type->type_legacy) {
2917 this->build_reroute_node(bnode, graph_params);
2921 this->handle_group_input_node(bnode, graph_params);
2925 this->build_group_output_node(bnode, graph_params);
2929 this->build_viewer_node(bnode, graph_params);
2933 this->build_switch_node(bnode, graph_params);
2937 this->build_index_switch_node(bnode, graph_params);
2941 this->build_warning_node(bnode, graph_params);
2947 this->build_gizmo_node(bnode, graph_params);
2951 this->build_bake_node(bnode, graph_params);
2955 this->build_menu_switch_node(bnode, graph_params);
2959 this->build_evaluate_closure_node(bnode, graph_params);
2963 if (node_type->geometry_node_execute) {
2964 this->build_geometry_node(bnode, graph_params);
2967 const NodeMultiFunctions::Item &fn_item = node_multi_functions_.
try_get(bnode);
2968 if (fn_item.fn !=
nullptr) {
2969 this->build_multi_function_node(bnode, fn_item, graph_params);
2972 if (bnode.is_undefined()) {
2973 this->build_undefined_node(bnode, graph_params);
2982 void build_muted_node(
const bNode &bnode, BuildGraphParams &graph_params)
2984 auto &lazy_function = scope_.
construct<LazyFunctionForMutedNode>(
2986 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
2987 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
2989 if (lf_index == -1) {
2992 lf::InputSocket &lf_socket = lf_node.input(lf_index);
2993 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
2996 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
2998 if (lf_index == -1) {
3001 lf::OutputSocket &lf_socket = lf_node.output(lf_index);
3002 graph_params.lf_output_by_bsocket.add_new(bsocket, &lf_socket);
3006 this->build_muted_node_usages(bnode, graph_params);
3012 void build_muted_node_usages(
const bNode &bnode, BuildGraphParams &graph_params)
3015 MultiValueMap<const bNodeSocket *, const bNodeSocket *> outputs_by_input;
3016 for (
const bNodeLink &blink : bnode.internal_links()) {
3017 outputs_by_input.
add(blink.fromsock, blink.tosock);
3019 for (
const auto item : outputs_by_input.
items()) {
3021 const Span<const bNodeSocket *> output_bsockets = item.value;
3025 for (
const bNodeSocket *output_bsocket : output_bsockets) {
3026 if (lf::OutputSocket *lf_socket = graph_params.usage_by_bsocket.lookup_default(
3027 output_bsocket,
nullptr))
3029 lf_socket_usages.
append(lf_socket);
3032 graph_params.usage_by_bsocket.add(&input_bsocket,
3033 this->or_socket_usages(lf_socket_usages, graph_params));
3037 void build_reroute_node(
const bNode &bnode, BuildGraphParams &graph_params)
3039 const bNodeSocket &input_bsocket = bnode.input_socket(0);
3040 const bNodeSocket &output_bsocket = bnode.output_socket(0);
3042 if (type ==
nullptr) {
3046 auto &lazy_function = scope_.
construct<LazyFunctionForRerouteNode>(*type);
3047 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
3049 lf::InputSocket &lf_input = lf_node.
input(0);
3050 lf::OutputSocket &lf_output = lf_node.
output(0);
3051 graph_params.lf_inputs_by_bsocket.add(&input_bsocket, &lf_input);
3052 graph_params.lf_output_by_bsocket.add_new(&output_bsocket, &lf_output);
3056 if (lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(
3057 &bnode.output_socket(0),
nullptr))
3059 graph_params.usage_by_bsocket.add(&bnode.input_socket(0), lf_usage);
3063 void handle_group_input_node(
const bNode &bnode, BuildGraphParams &graph_params)
3065 for (
const int i : btree_.interface_inputs().index_range()) {
3068 group_input_sockets_[
i]);
3069 graph_params.lf_output_by_bsocket.add_new(&bsocket, &lf_socket);
3074 void build_group_output_node(
const bNode &bnode, BuildGraphParams &graph_params)
3078 for (
const int i : btree_.interface_outputs().index_range()) {
3081 const bke::bNodeSocketType *typeinfo = interface_output.socket_typeinfo();
3082 const CPPType &type = *typeinfo->geometry_nodes_cpp_type;
3084 type, interface_output.
name ? interface_output.
name :
"");
3085 lf_graph_outputs.
append(&lf_socket);
3086 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3090 if (&bnode == btree_.group_output_node()) {
3091 standard_group_output_sockets_ = lf_graph_outputs.
as_span();
3095 void build_group_node(
const bNode &bnode, BuildGraphParams &graph_params)
3098 if (group_btree ==
nullptr) {
3101 const GeometryNodesLazyFunctionGraphInfo *group_lf_graph_info =
3103 if (group_lf_graph_info ==
nullptr) {
3107 auto &lazy_function = scope_.
construct<LazyFunctionForGroupNode>(
3108 bnode, *group_lf_graph_info, *lf_graph_info_);
3109 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(lazy_function);
3111 for (
const int i : bnode.input_sockets().index_range()) {
3114 lf::InputSocket &lf_socket = lf_node.input(group_lf_graph_info->function.inputs.main[
i]);
3115 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3118 for (
const int i : bnode.output_sockets().index_range()) {
3120 lf::OutputSocket &lf_socket = lf_node.output(group_lf_graph_info->function.outputs.main[
i]);
3121 graph_params.lf_output_by_bsocket.add_new(&bsocket, &lf_socket);
3125 lf_graph_info_->num_inline_nodes_approximate +=
3126 group_lf_graph_info->num_inline_nodes_approximate;
3127 static const bool static_false =
false;
3128 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
3130 const int lf_input_index =
3132 if (lf_input_index != -1) {
3133 lf::InputSocket &lf_input = lf_node.input(lf_input_index);
3135 graph_params.socket_usage_inputs.add(&lf_input);
3140 const int lf_input_index =
3142 if (lf_input_index != -1) {
3143 lf::InputSocket &lf_input = lf_node.input(lf_input_index);
3144 graph_params.lf_reference_set_input_by_output.add(bsocket, &lf_input);
3149 this->build_group_node_socket_usage(bnode, lf_node, graph_params, *group_lf_graph_info);
3152 void build_group_node_socket_usage(
const bNode &bnode,
3153 lf::FunctionNode &lf_group_node,
3154 BuildGraphParams &graph_params,
3155 const GeometryNodesLazyFunctionGraphInfo &group_lf_graph_info)
3157 for (
const bNodeSocket *input_bsocket : bnode.input_sockets()) {
3158 const int input_index = input_bsocket->index();
3159 const InputUsageHint &input_usage_hint =
3160 group_lf_graph_info.mapping.group_input_usage_hints[input_index];
3161 switch (input_usage_hint.type) {
3162 case InputUsageHintType::Never: {
3166 case InputUsageHintType::DependsOnOutput: {
3168 for (
const int i : input_usage_hint.output_dependencies) {
3169 if (lf::OutputSocket *lf_socket = graph_params.usage_by_bsocket.lookup_default(
3170 &bnode.output_socket(
i),
nullptr))
3172 output_usages.
append(lf_socket);
3175 graph_params.usage_by_bsocket.add(input_bsocket,
3176 this->or_socket_usages(output_usages, graph_params));
3179 case InputUsageHintType::DynamicSocket: {
3180 graph_params.usage_by_bsocket.add(
3183 group_lf_graph_info.function.outputs.input_usages[input_index]));
3189 for (
const bNodeSocket *output_bsocket : bnode.output_sockets()) {
3190 const int lf_input_index =
3194 lf::InputSocket &lf_socket = lf_group_node.
input(lf_input_index);
3195 if (lf::OutputSocket *lf_output_is_used = graph_params.usage_by_bsocket.lookup_default(
3196 output_bsocket,
nullptr))
3198 graph_params.lf_graph.add_link(*lf_output_is_used, lf_socket);
3201 static const bool static_false =
false;
3207 void build_geometry_node(
const bNode &bnode, BuildGraphParams &graph_params)
3209 auto &lazy_function = scope_.
construct<LazyFunctionForGeometryNode>(bnode, *lf_graph_info_);
3210 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
3212 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
3214 if (lf_index == -1) {
3217 lf::InputSocket &lf_socket = lf_node.input(lf_index);
3219 if (bsocket->is_multi_input()) {
3220 auto &multi_input_lazy_function = scope_.
construct<LazyFunctionForMultiInput>(*bsocket);
3221 lf::Node &lf_multi_input_node = graph_params.lf_graph.add_function(
3222 multi_input_lazy_function);
3223 graph_params.lf_graph.add_link(lf_multi_input_node.
output(0), lf_socket);
3224 for (
const int i : multi_input_lazy_function.links.index_range()) {
3225 lf::InputSocket &lf_multi_input_socket = lf_multi_input_node.
input(
i);
3226 const bNodeLink *link = multi_input_lazy_function.links[
i];
3227 graph_params.lf_input_by_multi_input_link.add(link, &lf_multi_input_socket);
3234 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
3238 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
3240 if (lf_index == -1) {
3243 lf::OutputSocket &lf_socket = lf_node.output(lf_index);
3244 graph_params.lf_output_by_bsocket.add_new(bsocket, &lf_socket);
3248 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
3250 const int lf_input_index =
3252 if (lf_input_index != -1) {
3253 lf::InputSocket &lf_input_socket = lf_node.input(lf_input_index);
3254 if (lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(bsocket,
3257 graph_params.lf_graph.add_link(*lf_usage, lf_input_socket);
3260 static const bool static_false =
false;
3263 graph_params.socket_usage_inputs.add_new(&lf_node.input(lf_input_index));
3268 const int lf_input_index =
3270 if (lf_input_index != -1) {
3271 graph_params.lf_reference_set_input_by_output.add(bsocket,
3272 &lf_node.input(lf_input_index));
3277 this->build_standard_node_input_socket_usage(bnode, graph_params);
3280 void build_standard_node_input_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
3282 if (bnode.input_sockets().is_empty()) {
3287 for (
const bNodeSocket *output_socket : bnode.output_sockets()) {
3288 if (!output_socket->is_available()) {
3291 if (lf::OutputSocket *is_used_socket = graph_params.usage_by_bsocket.lookup_default(
3292 output_socket,
nullptr))
3299 lf::OutputSocket *lf_usage = this->or_socket_usages(output_usages, graph_params);
3300 if (lf_usage ==
nullptr) {
3304 for (
const bNodeSocket *input_socket : bnode.input_sockets()) {
3305 if (input_socket->is_available()) {
3306 graph_params.usage_by_bsocket.add(input_socket, lf_usage);
3311 void build_multi_function_node(
const bNode &bnode,
3312 const NodeMultiFunctions::Item &fn_item,
3313 BuildGraphParams &graph_params)
3315 auto &lazy_function = scope_.
construct<LazyFunctionForMultiFunctionNode>(
3317 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(lazy_function);
3319 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
3321 if (lf_index == -1) {
3325 lf::InputSocket &lf_socket = lf_node.input(lf_index);
3326 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
3329 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
3331 if (lf_index == -1) {
3334 lf::OutputSocket &lf_socket = lf_node.output(lf_index);
3335 graph_params.lf_output_by_bsocket.add(bsocket, &lf_socket);
3339 this->build_standard_node_input_socket_usage(bnode, graph_params);
3342 void build_viewer_node(
const bNode &bnode, BuildGraphParams &graph_params)
3344 auto &lazy_function = scope_.
construct<LazyFunctionForViewerNode>(
3346 lf::FunctionNode &lf_viewer_node = graph_params.lf_graph.add_function(lazy_function);
3348 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
3350 if (lf_index == -1) {
3353 lf::InputSocket &lf_socket = lf_viewer_node.input(lf_index);
3354 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
3361 auto &usage_lazy_function = scope_.
construct<LazyFunctionForViewerInputUsage>(
3363 lf::FunctionNode &lf_usage_node = graph_params.lf_graph.add_function(usage_lazy_function);
3365 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
3366 if (bsocket->is_available()) {
3367 graph_params.usage_by_bsocket.add(bsocket, &lf_usage_node.output(0));
3373 void build_gizmo_node(
const bNode &bnode, BuildGraphParams &graph_params)
3375 auto &lazy_function = scope_.
construct<LazyFunctionForGizmoNode>(
3377 lf::FunctionNode &lf_gizmo_node = graph_params.lf_graph.add_function(lazy_function);
3378 lazy_function.self_node = &lf_gizmo_node;
3380 for (
const int i : lazy_function.gizmo_links.index_range()) {
3381 const bNodeLink &link = *lazy_function.gizmo_links[
i];
3382 lf::InputSocket &lf_socket = lf_gizmo_node.input(
i);
3383 graph_params.lf_input_by_multi_input_link.add(&link, &lf_socket);
3385 for (
const int i : bnode.input_sockets().drop_front(1).index_range()) {
3386 lf::InputSocket &lf_socket = lf_gizmo_node.input(
i + lazy_function.gizmo_links.size());
3387 const bNodeSocket &bsocket = bnode.input_socket(
i + 1);
3388 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3391 for (
const int i : bnode.output_sockets().index_range()) {
3392 lf::OutputSocket &lf_socket = lf_gizmo_node.output(
i);
3394 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
3398 this->build_gizmo_node_socket_usage(bnode, graph_params, lf_gizmo_node);
3403 void build_gizmo_node_socket_usage(
const bNode &bnode,
3404 BuildGraphParams &graph_params,
3405 const lf::FunctionNode &lf_gizmo_node)
3407 const auto &usage_fn = scope_.
construct<LazyFunctionForGizmoInputsUsage>(bnode, lf_gizmo_node);
3408 lf::FunctionNode &lf_usage_node = graph_params.lf_graph.add_function(usage_fn);
3409 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
3410 graph_params.usage_by_bsocket.add(bsocket, &lf_usage_node.output(0));
3414 lf::FunctionNode *insert_simulation_input_node(
const bNodeTree &node_tree,
3416 BuildGraphParams &graph_params)
3425 node_tree, bnode, *lf_graph_info_);
3426 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3427 scope_.
add(std::move(lazy_function));
3429 for (
const int i : bnode.input_sockets().index_range().drop_back(1)) {
3431 lf::InputSocket &lf_socket = lf_node.
input(
3433 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3436 for (
const int i : bnode.output_sockets().index_range().drop_back(1)) {
3438 lf::OutputSocket &lf_socket = lf_node.
output(
3440 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
3446 lf::FunctionNode &insert_simulation_output_node(
const bNode &bnode,
3447 BuildGraphParams &graph_params)
3450 bnode, *lf_graph_info_);
3451 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3452 scope_.
add(std::move(lazy_function));
3454 for (
const int i : bnode.input_sockets().index_range().drop_back(1)) {
3456 lf::InputSocket &lf_socket = lf_node.
input(
3458 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3461 for (
const int i : bnode.output_sockets().index_range().drop_back(1)) {
3463 lf::OutputSocket &lf_socket = lf_node.
output(
3465 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
3474 void build_bake_node(
const bNode &bnode, BuildGraphParams &graph_params)
3477 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3478 scope_.
add(std::move(lazy_function));
3480 for (
const int i : bnode.input_sockets().index_range().drop_back(1)) {
3482 lf::InputSocket &lf_socket = lf_node.
input(
3484 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3487 for (
const int i : bnode.output_sockets().index_range().drop_back(1)) {
3489 lf::OutputSocket &lf_socket = lf_node.
output(
3491 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
3497 this->build_bake_node_socket_usage(bnode, graph_params);
3500 void build_bake_node_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
3502 const LazyFunction &usage_fn = scope_.
construct<LazyFunctionForBakeInputsUsage>(bnode);
3503 lf::FunctionNode &lf_usage_node = graph_params.lf_graph.add_function(usage_fn);
3504 const int items_num = bnode.input_sockets().size() - 1;
3505 for (
const int i : IndexRange(items_num)) {
3506 graph_params.usage_by_bsocket.add(&bnode.input_socket(
i), &lf_usage_node.output(0));
3510 void build_switch_node(
const bNode &bnode, BuildGraphParams &graph_params)
3513 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3514 scope_.
add(std::move(lazy_function));
3516 for (
const int i : bnode.input_sockets().index_range()) {
3517 graph_params.lf_inputs_by_bsocket.add(&bnode.input_socket(
i), &lf_node.
input(
i));
3521 graph_params.lf_output_by_bsocket.add(&bnode.output_socket(0), &lf_node.
output(0));
3524 this->build_switch_node_socket_usage(bnode, graph_params);
3527 void build_switch_node_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
3529 const bNodeSocket &switch_input_bsocket = bnode.input_socket(0);
3530 const bNodeSocket &false_input_bsocket = bnode.input_socket(1);
3531 const bNodeSocket &true_input_bsocket = bnode.input_socket(2);
3532 const bNodeSocket &output_bsocket = bnode.output_socket(0);
3533 lf::OutputSocket *output_is_used_socket = graph_params.usage_by_bsocket.
lookup_default(
3534 &output_bsocket,
nullptr);
3535 if (output_is_used_socket ==
nullptr) {
3538 graph_params.usage_by_bsocket.add(&switch_input_bsocket, output_is_used_socket);
3539 if (switch_input_bsocket.is_directly_linked()) {
3541 static const LazyFunctionForSwitchSocketUsage switch_socket_usage_fn;
3542 lf::Node &lf_node = graph_params.lf_graph.add_function(switch_socket_usage_fn);
3543 graph_params.lf_inputs_by_bsocket.add(&switch_input_bsocket, &lf_node.
input(0));
3544 graph_params.usage_by_bsocket.add(&false_input_bsocket, &lf_node.
output(0));
3545 graph_params.usage_by_bsocket.add(&true_input_bsocket, &lf_node.
output(1));
3549 graph_params.usage_by_bsocket.add(&true_input_bsocket, output_is_used_socket);
3552 graph_params.usage_by_bsocket.add(&false_input_bsocket, output_is_used_socket);
3557 void build_index_switch_node(
const bNode &bnode, BuildGraphParams &graph_params)
3560 bnode, *lf_graph_info_);
3561 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3562 scope_.
add(std::move(lazy_function));
3564 for (
const int i : bnode.input_sockets().drop_back(1).index_range()) {
3565 graph_params.lf_inputs_by_bsocket.add(&bnode.input_socket(
i), &lf_node.
input(
i));
3569 graph_params.lf_output_by_bsocket.add(&bnode.output_socket(0), &lf_node.
output(0));
3572 this->build_index_switch_node_socket_usage(bnode, graph_params);
3575 void build_index_switch_node_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
3577 const bNodeSocket &index_socket = bnode.input_socket(0);
3578 const int items_num = bnode.input_sockets().size() - 1;
3580 lf::OutputSocket *output_is_used = graph_params.usage_by_bsocket.
lookup_default(
3581 &bnode.output_socket(0),
nullptr);
3582 if (output_is_used ==
nullptr) {
3585 graph_params.usage_by_bsocket.add(&index_socket, output_is_used);
3586 if (index_socket.is_directly_linked()) {
3588 auto usage_fn = std::make_unique<LazyFunctionForIndexSwitchSocketUsage>(bnode);
3589 lf::Node &lf_node = graph_params.lf_graph.add_function(*usage_fn);
3590 scope_.
add(std::move(usage_fn));
3592 graph_params.lf_inputs_by_bsocket.add(&index_socket, &lf_node.
input(0));
3593 for (
const int i : IndexRange(items_num)) {
3594 graph_params.usage_by_bsocket.add(&bnode.input_socket(
i + 1), &lf_node.
output(
i));
3599 if (IndexRange(items_num).contains(index)) {
3600 graph_params.usage_by_bsocket.add(&bnode.input_socket(index + 1), output_is_used);
3605 void build_warning_node(
const bNode &bnode, BuildGraphParams &graph_params)
3608 LazyFunction &lazy_function = *lazy_function_ptr;
3609 scope_.
add(std::move(lazy_function_ptr));
3611 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
3613 for (
const int i : bnode.input_sockets().index_range()) {
3615 lf::InputSocket &lf_socket = lf_node.
input(
i);
3616 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3619 for (
const int i : bnode.output_sockets().index_range()) {
3621 lf::OutputSocket &lf_socket = lf_node.
output(
i);
3622 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
3626 const bNodeSocket &output_bsocket = bnode.output_socket(0);
3628 lf::OutputSocket *lf_usage =
nullptr;
3629 if (output_bsocket.is_directly_linked()) {
3631 lf_usage = graph_params.usage_by_bsocket.lookup_default(&output_bsocket,
nullptr);
3635 lf_usage = this->or_socket_usages(group_output_used_sockets_, graph_params);
3638 for (
const bNodeSocket *socket : bnode.input_sockets()) {
3639 graph_params.usage_by_bsocket.add(socket, lf_usage);
3644 void build_menu_switch_node(
const bNode &bnode, BuildGraphParams &graph_params)
3647 bnode, *lf_graph_info_);
3648 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3649 scope_.
add(std::move(lazy_function));
3651 int input_index = 0;
3652 for (
const bNodeSocket *bsocket : bnode.input_sockets().drop_back(1)) {
3653 if (bsocket->is_available()) {
3654 lf::InputSocket &lf_socket = lf_node.
input(input_index);
3655 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
3660 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
3661 if (bsocket->is_available()) {
3662 lf::OutputSocket &lf_socket = lf_node.
output(0);
3663 graph_params.lf_output_by_bsocket.add(bsocket, &lf_socket);
3669 this->build_menu_switch_node_socket_usage(bnode, graph_params);
3672 void build_menu_switch_node_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
3677 const bNodeSocket *switch_input_bsocket = bnode.input_sockets()[0];
3678 Vector<const bNodeSocket *> input_bsockets(enum_def.
items_num);
3679 for (
const int i : IndexRange(enum_def.
items_num)) {
3680 input_bsockets[
i] = bnode.input_sockets()[
i + 1];
3682 const bNodeSocket *output_bsocket = bnode.output_sockets()[0];
3684 lf::OutputSocket *output_is_used_socket = graph_params.usage_by_bsocket.lookup_default(
3685 output_bsocket,
nullptr);
3686 if (output_is_used_socket ==
nullptr) {
3689 graph_params.usage_by_bsocket.add(switch_input_bsocket, output_is_used_socket);
3690 if (switch_input_bsocket->is_directly_linked()) {
3692 std::unique_ptr<LazyFunction> lazy_function =
3694 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3695 scope_.
add(std::move(lazy_function));
3697 graph_params.lf_inputs_by_bsocket.add(switch_input_bsocket, &lf_node.
input(0));
3698 for (
const int i : IndexRange(enum_def.
items_num)) {
3699 graph_params.usage_by_bsocket.add(input_bsockets[
i], &lf_node.
output(
i));
3703 const int condition =
3705 for (
const int i : IndexRange(enum_def.
items_num)) {
3708 graph_params.usage_by_bsocket.add(input_bsockets[
i], output_is_used_socket);
3715 void build_evaluate_closure_node(
const bNode &bnode, BuildGraphParams &graph_params)
3719 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*function.lazy_function);
3720 const int inputs_num = bnode.input_sockets().size() - 1;
3721 const int outputs_num = bnode.output_sockets().size() - 1;
3722 BLI_assert(inputs_num == function.indices.inputs.main.size());
3723 BLI_assert(inputs_num == function.indices.outputs.input_usages.size());
3724 BLI_assert(outputs_num == function.indices.outputs.main.size());
3725 BLI_assert(outputs_num == function.indices.inputs.output_usages.size());
3729 for (
const int i : IndexRange(inputs_num)) {
3731 lf::InputSocket &lf_socket = lf_node.
input(function.indices.inputs.main[
i]);
3732 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3734 graph_params.usage_by_bsocket.add(&bsocket,
3735 &lf_node.
output(function.indices.outputs.input_usages[
i]));
3737 for (
const int i : IndexRange(outputs_num)) {
3739 lf::OutputSocket &lf_socket = lf_node.
output(function.indices.outputs.main[
i]);
3740 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
3742 lf::InputSocket &lf_usage_socket = lf_node.
input(function.indices.inputs.output_usages[
i]);
3743 graph_params.socket_usage_inputs.add(&lf_usage_socket);
3744 if (lf::OutputSocket *output_is_used = graph_params.usage_by_bsocket.lookup(&bsocket)) {
3745 graph_params.lf_graph.add_link(*output_is_used, lf_usage_socket);
3748 static const bool static_false =
false;
3752 for (
const auto item : function.indices.inputs.reference_set_by_output.items()) {
3753 const bNodeSocket &bsocket = bnode.output_socket(item.key);
3754 lf_graph_info_->mapping
3755 .lf_input_index_for_reference_set_for_output[bsocket.index_in_all_outputs()] =
3757 graph_params.lf_reference_set_input_by_output.add(&bsocket, &lf_node.
input(item.value));
3761 void build_undefined_node(
const bNode &bnode, BuildGraphParams &graph_params)
3763 auto &lazy_function = scope_.
construct<LazyFunctionForUndefinedNode>(
3765 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(lazy_function);
3767 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
3769 if (lf_index == -1) {
3772 lf::OutputSocket &lf_socket = lf_node.output(lf_index);
3773 graph_params.lf_output_by_bsocket.add(bsocket, &lf_socket);
3778 struct TypeWithLinks {
3779 const bke::bNodeSocketType *typeinfo;
3780 Vector<const bNodeLink *> links;
3783 void insert_links_from_socket(
const bNodeSocket &from_bsocket,
3784 lf::OutputSocket &from_lf_socket,
3785 BuildGraphParams &graph_params)
3787 if (from_bsocket.owner_node().is_dangling_reroute()) {
3791 const bke::bNodeSocketType &from_typeinfo = *from_bsocket.
typeinfo;
3796 for (
const TypeWithLinks &type_with_links : types_with_links) {
3797 if (type_with_links.typeinfo ==
nullptr) {
3800 if (type_with_links.typeinfo->geometry_nodes_cpp_type ==
nullptr) {
3803 const bke::bNodeSocketType &to_typeinfo = *type_with_links.typeinfo;
3804 const CPPType &to_type = *to_typeinfo.geometry_nodes_cpp_type;
3805 const Span<const bNodeLink *> links = type_with_links.links;
3807 lf::OutputSocket *converted_from_lf_socket = this->insert_type_conversion_if_necessary(
3808 from_lf_socket, from_typeinfo, to_typeinfo, graph_params.lf_graph);
3813 if (converted_from_lf_socket ==
nullptr) {
3815 for (lf::InputSocket *to_lf_socket : lf_link_targets) {
3816 to_lf_socket->set_default_value(default_value);
3820 for (lf::InputSocket *to_lf_socket : lf_link_targets) {
3821 graph_params.lf_graph.add_link(*converted_from_lf_socket, *to_lf_socket);
3830 const Span<const bNodeLink *> links_from_bsocket = from_bsocket.directly_linked_links();
3832 for (
const bNodeLink *link : links_from_bsocket) {
3833 if (link->is_muted()) {
3836 if (!link->is_available()) {
3840 bool inserted =
false;
3841 for (TypeWithLinks &types_with_links : types_with_links) {
3842 if (types_with_links.typeinfo == to_bsocket.
typeinfo) {
3843 types_with_links.links.append(link);
3851 types_with_links.append({to_bsocket.
typeinfo, {link}});
3853 return types_with_links;
3857 const BuildGraphParams &graph_params)
3859 if (lf::InputSocket *lf_input_socket = graph_params.lf_input_by_border_link.lookup_default(
3862 return {lf_input_socket};
3866 if (to_bsocket.is_multi_input()) {
3869 for (
const bNodeLink *multi_input_link : to_bsocket.directly_linked_links()) {
3870 if (multi_input_link == &link) {
3873 if (multi_input_link->is_muted() || !multi_input_link->fromsock->is_available() ||
3874 multi_input_link->fromnode->is_dangling_reroute())
3880 if (to_bsocket.owner_node().is_muted()) {
3881 if (link_index == 0) {
3886 lf::InputSocket *lf_multi_input_socket =
3887 graph_params.lf_input_by_multi_input_link.lookup_default(&link,
nullptr);
3888 if (!lf_multi_input_socket) {
3891 return {lf_multi_input_socket};
3900 lf::OutputSocket *insert_type_conversion_if_necessary(lf::OutputSocket &from_socket,
3901 const bke::bNodeSocketType &from_typeinfo,
3902 const bke::bNodeSocketType &to_typeinfo,
3903 lf::Graph &lf_graph)
3905 if (from_typeinfo.type == to_typeinfo.type) {
3906 return &from_socket;
3909 from_typeinfo, to_typeinfo, scope_))
3911 lf::Node &conversion_node = lf_graph.
add_function(*conversion_fn);
3913 return &conversion_node.
output(0);
3918 void add_default_inputs(BuildGraphParams &graph_params)
3920 for (
auto item : graph_params.lf_inputs_by_bsocket.items()) {
3922 const Span<lf::InputSocket *> lf_sockets = item.value;
3923 for (lf::InputSocket *lf_socket : lf_sockets) {
3924 if (lf_socket->origin() !=
nullptr) {
3928 this->add_default_input(bsocket, *lf_socket, graph_params);
3933 void add_default_input(
const bNodeSocket &input_bsocket,
3934 lf::InputSocket &input_lf_socket,
3935 BuildGraphParams &graph_params)
3937 if (this->try_add_implicit_input(input_bsocket, input_lf_socket, graph_params)) {
3941 if (value.get() ==
nullptr) {
3946 if (!value.type()->is_trivially_destructible) {
3951 bool try_add_implicit_input(
const bNodeSocket &input_bsocket,
3952 lf::InputSocket &input_lf_socket,
3953 BuildGraphParams &graph_params)
3955 const bNode &bnode = input_bsocket.owner_node();
3956 const SocketDeclaration *socket_decl = input_bsocket.
runtime->declaration;
3957 if (socket_decl ==
nullptr) {
3965 if (!implicit_input_fn.has_value()) {
3968 std::function<void(
void *)> init_fn = [&bnode, implicit_input_fn](
void *r_value) {
3969 (*implicit_input_fn)(bnode, r_value);
3971 const CPPType &type = input_lf_socket.
type();
3972 auto &lazy_function = scope_.
construct<LazyFunctionForImplicitInput>(type, std::move(init_fn));
3973 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
3974 graph_params.lf_graph.add_link(lf_node.output(0), input_lf_socket);
3983 void build_root_reference_set_inputs(lf::Graph &lf_graph)
3985 const aal::RelationsInNode &tree_relations = reference_lifetimes_.
tree_relations;
3986 Vector<int> output_indices;
3987 for (
const aal::PropagateRelation &relation : tree_relations.propagate_relations) {
3992 const int output_index = output_indices[
i];
3993 const char *name = btree_.interface_outputs()[output_index]->name;
3996 StringRef(
"Propagate: ") + (name ? name :
""));
3997 reference_set_by_output_.
add(output_index, &lf_socket);
4005 lf::OutputSocket *or_socket_usages(
const Span<lf::OutputSocket *> usages,
4006 BuildGraphParams &graph_params)
4011 if (usages.
size() == 1) {
4017 std::sort(usages_sorted.begin(), usages_sorted.end());
4018 return graph_params.socket_usages_combination_cache.lookup_or_add_cb(
4019 std::move(usages_sorted), [&]() {
4020 auto &logical_or_fn = scope_.
construct<LazyFunctionForLogicalOr>(usages.
size());
4021 lf::Node &logical_or_node = graph_params.lf_graph.add_function(logical_or_fn);
4023 for (
const int i : usages_sorted.index_range()) {
4024 graph_params.lf_graph.add_link(*usages_sorted[
i], logical_or_node.
input(
i));
4026 return &logical_or_node.
output(0);
4030 void build_output_socket_usages(
const bNode &bnode, BuildGraphParams &graph_params)
4033 for (
const bNodeSocket *socket : bnode.output_sockets()) {
4034 if (!socket->is_available()) {
4039 for (
const bNodeLink *link : socket->directly_linked_links()) {
4040 if (!link->is_used()) {
4044 if (lf::OutputSocket *is_used_socket = graph_params.usage_by_bsocket.lookup_default(
4045 &target_socket,
nullptr))
4051 graph_params.usage_by_bsocket.add(socket,
4052 this->or_socket_usages(target_usages, graph_params));
4056 void build_group_input_usages(BuildGraphParams &graph_params)
4058 const Span<const bNode *> group_input_nodes = btree_.group_input_nodes();
4059 for (
const int i : btree_.interface_inputs().index_range()) {
4061 for (
const bNode *group_input_node : group_input_nodes) {
4062 if (lf::OutputSocket *lf_socket = graph_params.usage_by_bsocket.lookup_default(
4063 &group_input_node->output_socket(
i),
nullptr))
4069 lf::OutputSocket *lf_socket = this->or_socket_usages(target_usages, graph_params);
4070 lf::InputSocket *lf_group_output =
const_cast<lf::InputSocket *
>(
4071 group_input_usage_sockets_[
i]);
4072 InputUsageHint input_usage_hint;
4073 if (lf_socket ==
nullptr) {
4074 static const bool static_false =
false;
4076 input_usage_hint.type = InputUsageHintType::Never;
4079 graph_params.lf_graph.add_link(*lf_socket, *lf_group_output);
4083 input_usage_hint.type = InputUsageHintType::DependsOnOutput;
4084 input_usage_hint.output_dependencies = {
4088 input_usage_hint.type = InputUsageHintType::DynamicSocket;
4091 lf_graph_info_->mapping.group_input_usage_hints.append(std::move(input_usage_hint));
4106 void fix_link_cycles(lf::Graph &lf_graph,
const Set<lf::InputSocket *> &socket_usage_inputs)
4109 const int sockets_num = lf_graph.
socket_num();
4111 struct SocketState {
4113 bool in_stack =
false;
4116 Array<SocketState> socket_states(sockets_num);
4119 for (lf::Node *lf_node : lf_graph.
nodes()) {
4120 if (lf_node->is_function()) {
4121 for (lf::OutputSocket *lf_socket : lf_node->outputs()) {
4122 if (lf_socket->
targets().is_empty()) {
4123 lf_sockets_to_check.
append(lf_socket);
4127 if (lf_node->outputs().is_empty()) {
4128 for (lf::InputSocket *lf_socket : lf_node->inputs()) {
4129 lf_sockets_to_check.
append(lf_socket);
4134 while (!lf_sockets_to_check.
is_empty()) {
4135 lf::Socket *lf_inout_socket = lf_sockets_to_check.
last();
4136 lf::Node &lf_node = lf_inout_socket->
node();
4139 if (!
state.in_stack) {
4140 lf_socket_stack.
append(lf_inout_socket);
4141 state.in_stack =
true;
4146 lf::InputSocket &lf_input_socket = lf_inout_socket->
as_input();
4147 if (lf::OutputSocket *lf_origin_socket = lf_input_socket.
origin()) {
4148 lf_origin_sockets.
append(lf_origin_socket);
4152 lf::OutputSocket &lf_output_socket = lf_inout_socket->
as_output();
4154 lf::FunctionNode &lf_function_node =
static_cast<lf::FunctionNode &
>(lf_node);
4155 const lf::LazyFunction &fn = lf_function_node.
function();
4157 lf_output_socket.
index(), [&](
const Span<int> input_indices) {
4158 for (const int input_index : input_indices) {
4159 lf_origin_sockets.append(&lf_node.input(input_index));
4165 bool pushed_socket =
false;
4166 bool detected_cycle =
false;
4167 for (lf::Socket *lf_origin_socket : lf_origin_sockets) {
4168 if (socket_states[lf_origin_socket->index_in_graph()].in_stack) {
4178 detected_cycle =
true;
4179 const int index_in_socket_stack = lf_socket_stack.
first_index_of(lf_origin_socket);
4180 const int index_in_sockets_to_check = lf_sockets_to_check.
first_index_of(
4182 const Span<lf::Socket *> cycle = lf_socket_stack.
as_span().drop_front(
4183 index_in_socket_stack);
4185 bool broke_cycle =
false;
4186 for (lf::Socket *lf_cycle_socket : cycle) {
4187 if (lf_cycle_socket->is_input() &&
4188 socket_usage_inputs.
contains(&lf_cycle_socket->as_input()))
4190 lf::InputSocket &lf_cycle_input_socket = lf_cycle_socket->as_input();
4192 static const bool static_true =
true;
4197 SocketState &lf_cycle_socket_state = socket_states[lf_cycle_socket->index_in_graph()];
4198 lf_cycle_socket_state.in_stack =
false;
4205 lf_socket_stack.
resize(index_in_socket_stack);
4207 lf_sockets_to_check.
resize(index_in_sockets_to_check + 1);
4210 if (!socket_states[lf_origin_socket->index_in_graph()].done) {
4211 lf_sockets_to_check.
append(lf_origin_socket);
4212 pushed_socket =
true;
4215 if (detected_cycle) {
4218 if (pushed_socket) {
4223 state.in_stack =
false;