1891 std::optional<BuildGraphParams> root_graph_build_params_;
1925 reference_lifetimes_(*btree.runtime->reference_lifetimes_info),
1926 scope_(lf_graph_info.scope),
1928 lf_graph_info_(&lf_graph_info)
1934 btree_.ensure_topology_cache();
1935 btree_.ensure_interface_cache();
1937 mapping_ = &lf_graph_info_->mapping;
1939 tree_zones_ = btree_.zones();
1941 this->initialize_mapping_arrays();
1942 this->build_zone_functions();
1943 this->build_root_graph();
1944 this->build_geometry_nodes_group_function();
1948 void initialize_mapping_arrays()
1951 btree_.all_output_sockets().size());
1954 btree_.all_output_sockets().size());
1963 void build_zone_functions()
1967 const Array<int> zone_build_order = this->compute_zone_build_order();
1969 for (
const int zone_i : zone_build_order) {
1973 this->build_simulation_zone_function(zone);
1977 this->build_repeat_zone_function(zone);
1981 this->build_foreach_geometry_element_zone_function(zone);
1984 this->build_closure_zone_function(zone);
1994 Array<int> compute_zone_build_order()
1997 Array<int> zone_build_order(tree_zones_->
zones.size());
1998 array_utils::fill_index_range<int>(zone_build_order);
2000 zone_build_order.begin(), zone_build_order.end(), [&](
const int zone_a,
const int zone_b) {
2001 return tree_zones_->zones[zone_a]->depth > tree_zones_->zones[zone_b]->depth;
2003 return zone_build_order;
2010 void build_simulation_zone_function(
const bNodeTreeZone &zone)
2012 const int zone_i = zone.
index;
2013 ZoneBuildInfo &zone_info = zone_build_infos_[zone_i];
2014 lf::Graph &lf_graph = scope_.
construct<lf::Graph>();
2018 Vector<lf::GraphInputSocket *> lf_zone_inputs;
2019 Vector<lf::GraphOutputSocket *> lf_zone_outputs;
2030 this->build_zone_border_links_inputs(
2031 zone, lf_graph, lf_zone_inputs, zone_info.indices.inputs.border_links);
2032 this->build_zone_border_link_input_usages(
2033 zone, lf_graph, lf_zone_outputs, zone_info.indices.outputs.border_link_usages);
2042 lf::Node &lf_simulation_usage_node = [&]() -> lf::Node & {
2043 auto &lazy_function = scope_.
construct<LazyFunctionForSimulationInputsUsage>(
2045 lf::Node &lf_node = lf_graph.
add_function(lazy_function);
2047 for (
const int i : zone_info.indices.outputs.input_usages) {
2054 BuildGraphParams graph_params{lf_graph};
2056 lf::FunctionNode *lf_simulation_input =
nullptr;
2058 lf_simulation_input = this->insert_simulation_input_node(
2061 lf::FunctionNode &lf_simulation_output = this->insert_simulation_output_node(
2065 graph_params.usage_by_bsocket.add(bsocket, &lf_simulation_usage_node.
output(1));
2069 for (
const int i : IndexRange(sim_output_storage.items_num)) {
2070 lf::InputSocket &lf_to = lf_simulation_output.
input(
i + 1);
2071 if (lf_simulation_input) {
2072 lf::OutputSocket &lf_from = lf_simulation_input->
output(
i + 1);
2084 this->build_output_socket_usages(*zone.
input_node(), graph_params);
2086 for (
const auto item : graph_params.lf_output_by_bsocket.items()) {
2087 this->insert_links_from_socket(*item.key, *item.value, graph_params);
2090 this->link_border_link_inputs_and_usages(zone,
2092 zone_info.indices.inputs.border_links,
2094 zone_info.indices.outputs.border_link_usages,
2097 for (
const int i : zone_info.indices.inputs.main) {
2101 for (
const int i : zone_info.indices.outputs.main.index_range()) {
2103 *lf_zone_outputs[zone_info.indices.outputs.main[
i]]);
2106 this->add_default_inputs(graph_params);
2108 Map<ReferenceSetIndex, lf::OutputSocket *> lf_reference_sets;
2109 this->build_reference_set_for_zone(graph_params, lf_reference_sets);
2110 for (
const auto item : lf_reference_sets.
items()) {
2111 lf::OutputSocket &lf_attribute_set_socket = *item.value;
2113 zone_info.indices.inputs.reference_sets.add_new(
2117 this->link_reference_sets(graph_params, lf_reference_sets);
2118 this->fix_link_cycles(lf_graph, graph_params.socket_usage_inputs);
2122 auto &logger = scope_.
construct<GeometryNodesLazyFunctionLogger>(*lf_graph_info_);
2123 auto &side_effect_provider = scope_.
construct<GeometryNodesLazyFunctionSideEffectProvider>();
2125 const auto &lf_graph_fn = scope_.
construct<lf::GraphExecutor>(lf_graph,
2129 &side_effect_provider,
2131 const auto &zone_function = scope_.
construct<LazyFunctionForSimulationZone>(
2133 zone_info.lazy_function = &zone_function;
2142 void build_repeat_zone_function(
const bNodeTreeZone &zone)
2144 ZoneBuildInfo &zone_info = zone_build_infos_[zone.
index];
2146 ZoneBodyFunction &body_fn = this->build_zone_body_function(
2147 zone,
"Repeat Body", &scope_.
construct<GeometryNodesLazyFunctionSideEffectProvider>());
2150 zone_info.lazy_function = &zone_fn;
2153 void build_foreach_geometry_element_zone_function(
const bNodeTreeZone &zone)
2155 ZoneBuildInfo &zone_info = zone_build_infos_[zone.
index];
2157 ZoneBodyFunction &body_fn = this->build_zone_body_function(
2158 zone,
"Foreach Body", &scope_.
construct<GeometryNodesLazyFunctionSideEffectProvider>());
2161 scope_, btree_, zone, zone_info, body_fn);
2162 zone_info.lazy_function = &zone_fn;
2165 void build_closure_zone_function(
const bNodeTreeZone &zone)
2167 ZoneBuildInfo &zone_info = zone_build_infos_[zone.
index];
2169 ZoneBodyFunction &body_fn = this->build_zone_body_function(
2170 zone,
"Closure Body", &scope_.
construct<GeometryNodesLazyFunctionSideEffectProvider>());
2172 zone_info.lazy_function = &zone_fn;
2178 ZoneBodyFunction &build_zone_body_function(
2179 const bNodeTreeZone &zone,
2180 const StringRef
name,
2181 const lf::GraphExecutorSideEffectProvider *side_effect_provider)
2183 lf::Graph &lf_body_graph = scope_.
construct<lf::Graph>(
name);
2185 BuildGraphParams graph_params{lf_body_graph};
2187 Vector<lf::GraphInputSocket *> lf_body_inputs;
2188 Vector<lf::GraphOutputSocket *> lf_body_outputs;
2189 ZoneBodyFunction &body_fn = scope_.
construct<ZoneBodyFunction>();
2200 body_fn.indices.outputs.input_usages.append(
2202 graph_params.lf_output_by_bsocket.add_new(bsocket, &lf_input);
2205 this->build_zone_border_links_inputs(
2206 zone, lf_body_graph, lf_body_inputs, body_fn.indices.inputs.border_links);
2207 this->build_zone_border_link_input_usages(
2208 zone, lf_body_graph, lf_body_outputs, body_fn.indices.outputs.border_link_usages);
2218 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_output);
2219 graph_params.usage_by_bsocket.add(bsocket, &lf_output_usage);
2221 body_fn.indices.inputs.output_usages.append(
2227 this->build_output_socket_usages(*zone.
input_node(), graph_params);
2230 int valid_socket_i = 0;
2235 lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.
lookup_default(bsocket,
2238 *lf_body_outputs[body_fn.indices.outputs.input_usages[valid_socket_i]];
2240 lf_body_graph.
add_link(*lf_usage, lf_usage_output);
2243 static const bool static_false =
false;
2250 for (
const auto item : graph_params.lf_output_by_bsocket.items()) {
2251 this->insert_links_from_socket(*item.key, *item.value, graph_params);
2254 this->link_border_link_inputs_and_usages(zone,
2256 body_fn.indices.inputs.border_links,
2258 body_fn.indices.outputs.border_link_usages,
2261 this->add_default_inputs(graph_params);
2263 Map<int, lf::OutputSocket *> lf_reference_sets;
2264 this->build_reference_set_for_zone(graph_params, lf_reference_sets);
2265 for (
const auto item : lf_reference_sets.
items()) {
2266 lf::OutputSocket &lf_attribute_set_socket = *item.value;
2268 body_fn.indices.inputs.reference_sets.add_new(
2272 this->link_reference_sets(graph_params, lf_reference_sets);
2273 this->fix_link_cycles(lf_body_graph, graph_params.socket_usage_inputs);
2277 auto &logger = scope_.
construct<GeometryNodesLazyFunctionLogger>(*lf_graph_info_);
2279 body_fn.function = &scope_.
construct<lf::GraphExecutor>(lf_body_graph,
2283 side_effect_provider,
2293 void build_zone_border_links_inputs(
const bNodeTreeZone &zone,
2294 lf::Graph &lf_graph,
2295 Vector<lf::GraphInputSocket *> &r_lf_graph_inputs,
2296 Vector<int> &r_indices)
2301 StringRef(
"Link from ") + border_link->
fromsock->
name)));
2305 void build_zone_border_link_input_usages(
const bNodeTreeZone &zone,
2306 lf::Graph &lf_graph,
2307 Vector<lf::GraphOutputSocket *> &r_lf_graph_outputs,
2308 Vector<int> &r_indices)
2316 void build_reference_set_for_zone(BuildGraphParams &graph_params,
2317 Map<ReferenceSetIndex, lf::OutputSocket *> &lf_reference_sets)
2319 const Vector<ReferenceSetIndex> all_required_reference_sets =
2320 this->find_all_required_reference_sets(graph_params.lf_reference_set_input_by_output,
2321 graph_params.lf_reference_set_inputs);
2323 auto add_reference_set_zone_input = [&](
const ReferenceSetIndex reference_set_i) {
2326 lf_reference_sets.
add(reference_set_i, &lf_graph_input);
2329 VectorSet<ReferenceSetIndex> input_reference_sets;
2330 for (
const ReferenceSetIndex reference_set_i : all_required_reference_sets) {
2331 const ReferenceSetInfo &reference_set = reference_lifetimes_.
reference_sets[reference_set_i];
2332 switch (reference_set.type) {
2333 case ReferenceSetType::GroupOutputData:
2334 case ReferenceSetType::GroupInputReferenceSet: {
2335 add_reference_set_zone_input(reference_set_i);
2338 case ReferenceSetType::LocalReferenceSet:
2339 case ReferenceSetType::ClosureOutputData:
2340 case ReferenceSetType::ClosureInputReferenceSet: {
2341 const bNodeSocket &bsocket = *reference_set.socket;
2342 if (lf::OutputSocket *lf_socket = graph_params.lf_output_by_bsocket.lookup_default(
2345 lf::OutputSocket *lf_usage_socket = graph_params.usage_by_bsocket.
lookup_default(
2347 lf::OutputSocket &lf_reference_set_socket = this->get_extracted_reference_set(
2348 *lf_socket, lf_usage_socket, graph_params);
2349 lf_reference_sets.
add(reference_set_i, &lf_reference_set_socket);
2353 add_reference_set_zone_input(reference_set_i);
2365 void build_root_graph()
2367 lf::Graph &lf_graph = lf_graph_info_->graph;
2369 this->build_main_group_inputs(lf_graph);
2370 if (btree_.group_output_node() ==
nullptr) {
2371 this->build_fallback_group_outputs(lf_graph);
2377 StringRef(
"Usage: ") + (interface_input->name ? interface_input->name :
""));
2378 group_input_usage_sockets_.
append(&lf_socket);
2381 Vector<lf::GraphInputSocket *> lf_output_usages;
2385 StringRef(
"Usage: ") + (interface_output->name ? interface_output->name :
""));
2386 group_output_used_sockets_.
append(&lf_socket);
2387 lf_output_usages.
append(&lf_socket);
2390 BuildGraphParams &graph_params = root_graph_build_params_.emplace(lf_graph);
2391 if (
const bNode *group_output_bnode = btree_.group_output_node()) {
2392 for (
const bNodeSocket *bsocket : group_output_bnode->input_sockets().drop_back(1)) {
2393 graph_params.usage_by_bsocket.add(bsocket, lf_output_usages[bsocket->index()]);
2397 this->insert_nodes_and_zones(
2400 for (
const auto item : graph_params.lf_output_by_bsocket.items()) {
2401 this->insert_links_from_socket(*item.key, *item.value, graph_params);
2403 this->build_group_input_usages(graph_params);
2404 this->add_default_inputs(graph_params);
2406 this->build_root_reference_set_inputs(lf_graph);
2408 Map<ReferenceSetIndex, lf::OutputSocket *> lf_reference_sets;
2409 this->build_reference_sets_outside_of_zones(graph_params, lf_reference_sets);
2410 this->link_reference_sets(graph_params, lf_reference_sets);
2412 this->fix_link_cycles(lf_graph, graph_params.socket_usage_inputs);
2417 lf_graph_info_->num_inline_nodes_approximate += lf_graph.
nodes().size();
2424 void build_geometry_nodes_group_function()
2426 GeometryNodesGroupFunction &function = lf_graph_info_->function;
2428 Vector<const lf::GraphInputSocket *> lf_graph_inputs;
2429 Vector<const lf::GraphOutputSocket *> lf_graph_outputs;
2431 lf_graph_inputs.
extend(group_input_sockets_);
2434 lf_graph_inputs.
extend(group_output_used_sockets_);
2436 group_output_used_sockets_.
size());
2438 for (
auto [output_index, lf_socket] : reference_set_by_output_.
items()) {
2439 lf_graph_inputs.
append(lf_socket);
2440 function.inputs.references_to_propagate.geometry_outputs.append(output_index);
2443 reference_set_by_output_.
size());
2445 lf_graph_outputs.
extend(standard_group_output_sockets_);
2447 standard_group_output_sockets_.
size());
2449 lf_graph_outputs.
extend(group_input_usage_sockets_);
2451 group_input_usage_sockets_.
size());
2453 Vector<const lf::FunctionNode *> &local_side_effect_nodes =
2454 scope_.
construct<Vector<const lf::FunctionNode *>>();
2455 for (
const bNode *bnode : btree_.nodes_by_type(
"GeometryNodeWarning")) {
2456 if (bnode->output_socket(0).is_directly_linked()) {
2468 const lf::Socket *lf_socket = root_graph_build_params_->lf_inputs_by_bsocket.lookup(
2469 &bnode->input_socket(0))[0];
2470 const lf::FunctionNode &lf_node =
static_cast<const lf::FunctionNode &
>(lf_socket->
node());
2471 local_side_effect_nodes.
append(&lf_node);
2474 function.function = &scope_.
construct<lf::GraphExecutor>(
2475 lf_graph_info_->graph,
2476 std::move(lf_graph_inputs),
2477 std::move(lf_graph_outputs),
2478 &scope_.
construct<GeometryNodesLazyFunctionLogger>(*lf_graph_info_),
2479 &scope_.
construct<GeometryNodesLazyFunctionSideEffectProvider>(local_side_effect_nodes),
2483 void build_reference_sets_outside_of_zones(
2484 BuildGraphParams &graph_params,
2485 Map<ReferenceSetIndex, lf::OutputSocket *> &lf_reference_sets)
2487 const Vector<ReferenceSetIndex> all_required_reference_sets =
2488 this->find_all_required_reference_sets(graph_params.lf_reference_set_input_by_output,
2489 graph_params.lf_reference_set_inputs);
2490 for (
const ReferenceSetIndex reference_set_i : all_required_reference_sets) {
2491 const ReferenceSetInfo &reference_set = reference_lifetimes_.
reference_sets[reference_set_i];
2492 switch (reference_set.type) {
2493 case ReferenceSetType::LocalReferenceSet: {
2494 const bNodeSocket &bsocket = *reference_set.socket;
2495 lf::OutputSocket &lf_socket = *graph_params.lf_output_by_bsocket.lookup(&bsocket);
2496 lf::OutputSocket *lf_usage_socket = graph_params.usage_by_bsocket.
lookup_default(
2498 lf::OutputSocket &lf_reference_set_socket = this->get_extracted_reference_set(
2499 lf_socket, lf_usage_socket, graph_params);
2500 lf_reference_sets.
add_new(reference_set_i, &lf_reference_set_socket);
2503 case ReferenceSetType::GroupInputReferenceSet: {
2504 const int group_input_i = reference_set.index;
2506 lf::OutputSocket *lf_usage_socket = group_input_usage_sockets_[group_input_i]->origin();
2507 lf::OutputSocket &lf_reference_set_socket = this->get_extracted_reference_set(
2508 lf_socket, lf_usage_socket, graph_params);
2509 lf_reference_sets.
add_new(reference_set_i, &lf_reference_set_socket);
2512 case ReferenceSetType::GroupOutputData: {
2513 const int group_output_i = reference_set.index;
2516 lf_reference_sets.
add_new(reference_set_i, lf_reference_set_socket);
2519 case ReferenceSetType::ClosureOutputData:
2520 case ReferenceSetType::ClosureInputReferenceSet: {
2529 Vector<ReferenceSetIndex> find_all_required_reference_sets(
2530 const Map<const bNodeSocket *, lf::InputSocket *> &lf_reference_set_input_by_output,
2531 const MultiValueMap<ReferenceSetIndex, lf::InputSocket *> &lf_reference_set_inputs)
2533 BitVector<> all_required_reference_sets(reference_lifetimes_.
reference_sets.size(),
false);
2534 for (
const bNodeSocket *bsocket : lf_reference_set_input_by_output.
keys()) {
2535 all_required_reference_sets |=
2538 for (
const ReferenceSetIndex reference_set_i : lf_reference_set_inputs.
keys()) {
2539 all_required_reference_sets[reference_set_i].set();
2541 Vector<ReferenceSetIndex>
indices;
2542 bits::foreach_1_index(all_required_reference_sets,
2543 [&](
const int index) {
indices.append(index); });
2547 void link_reference_sets(BuildGraphParams &graph_params,
2548 const Map<ReferenceSetIndex, lf::OutputSocket *> &lf_reference_sets)
2552 for (
const auto &item : graph_params.lf_reference_set_input_by_output.items()) {
2554 lf::InputSocket &lf_reference_set_input = *item.value;
2556 Vector<lf::OutputSocket *> lf_reference_sets_to_join;
2557 const BoundedBitSpan required_reference_sets =
2559 bits::foreach_1_index(required_reference_sets, [&](
const ReferenceSetIndex reference_set_i) {
2560 const ReferenceSetInfo &reference_set =
2562 if (reference_set.type == ReferenceSetType::LocalReferenceSet) {
2563 if (&reference_set.socket->owner_node() == &output_bsocket.owner_node()) {
2568 lf_reference_sets_to_join.
append(lf_reference_sets.
lookup(reference_set_i));
2571 if (lf::OutputSocket *lf_joined_reference_set = this->join_reference_sets(
2572 lf_reference_sets_to_join,
2573 join_reference_sets_cache,
2574 graph_params.lf_graph,
2575 graph_params.socket_usage_inputs))
2577 graph_params.lf_graph.add_link(*lf_joined_reference_set, lf_reference_set_input);
2580 static const GeometryNodesReferenceSet empty_reference_set;
2586 for (
const auto &item : graph_params.lf_reference_set_inputs.items()) {
2588 lf::OutputSocket &lf_reference_set = *lf_reference_sets.
lookup(reference_set_i);
2589 for (lf::InputSocket *lf_reference_set_input : item.value) {
2590 graph_params.lf_graph.add_link(lf_reference_set, *lf_reference_set_input);
2595 void insert_nodes_and_zones(
const Span<const bNode *> bnodes,
2596 const Span<const bNodeTreeZone *> zones,
2597 BuildGraphParams &graph_params)
2599 Vector<const bNode *> nodes_to_insert = bnodes;
2600 Map<const bNode *, const bNodeTreeZone *> zone_by_output;
2601 for (
const bNodeTreeZone *zone : zones) {
2606 std::sort(nodes_to_insert.
begin(), nodes_to_insert.
end(), [](
const bNode *a,
const bNode *
b) {
2607 return a->runtime->toposort_right_to_left_index < b->runtime->toposort_right_to_left_index;
2610 for (
const bNode *bnode : nodes_to_insert) {
2611 this->build_output_socket_usages(*bnode, graph_params);
2612 if (
const bNodeTreeZone *zone = zone_by_output.
lookup_default(bnode,
nullptr)) {
2613 this->insert_child_zone_node(*zone, graph_params);
2616 this->insert_node_in_graph(*bnode, graph_params);
2621 void link_border_link_inputs_and_usages(
const bNodeTreeZone &zone,
2622 const Span<lf::GraphInputSocket *> lf_inputs,
2623 const Span<int> lf_border_link_input_indices,
2624 const Span<lf::GraphOutputSocket *> lf_usages,
2625 const Span<int> lf_border_link_usage_indices,
2626 BuildGraphParams &graph_params)
2628 lf::Graph &lf_graph = graph_params.lf_graph;
2629 for (
const int border_link_i : zone.
border_links.index_range()) {
2632 const Vector<lf::InputSocket *> lf_link_targets = this->find_link_targets(border_link,
2634 for (lf::InputSocket *lf_to : lf_link_targets) {
2635 lf_graph.
add_link(lf_from, *lf_to);
2638 *lf_usages[lf_border_link_usage_indices[border_link_i]];
2639 if (lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(
2640 border_link.
tosock,
nullptr))
2642 lf_graph.
add_link(*lf_usage, lf_usage_output);
2645 static const bool static_false =
false;
2651 lf::OutputSocket &get_extracted_reference_set(lf::OutputSocket &lf_field_socket,
2652 lf::OutputSocket *lf_usage_socket,
2653 BuildGraphParams &graph_params)
2655 auto &lazy_function = scope_.
construct<LazyFunctionForExtractingReferenceSet>();
2656 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
2657 lf::InputSocket &lf_use_input = lf_node.
input(0);
2658 lf::InputSocket &lf_field_input = lf_node.input(1);
2659 graph_params.socket_usage_inputs.add_new(&lf_use_input);
2660 if (lf_usage_socket) {
2661 graph_params.lf_graph.add_link(*lf_usage_socket, lf_use_input);
2664 static const bool static_false =
false;
2667 graph_params.lf_graph.add_link(lf_field_socket, lf_field_input);
2668 return lf_node.output(0);
2674 lf::OutputSocket *join_reference_sets(
const Span<lf::OutputSocket *> lf_reference_set_sockets,
2675 JoinReferenceSetsCache &cache,
2676 lf::Graph &lf_graph,
2677 Set<lf::InputSocket *> &socket_usage_inputs)
2679 if (lf_reference_set_sockets.
is_empty()) {
2682 if (lf_reference_set_sockets.
size() == 1) {
2683 return lf_reference_set_sockets[0];
2686 Vector<lf::OutputSocket *, 16> key = lf_reference_set_sockets;
2688 return cache.lookup_or_add_cb(key, [&]() {
2689 const auto &lazy_function = LazyFunctionForJoinReferenceSets::get_cached(
2690 lf_reference_set_sockets.
size(), scope_);
2691 lf::Node &lf_node = lf_graph.
add_function(lazy_function);
2692 for (
const int i : lf_reference_set_sockets.
index_range()) {
2693 lf::OutputSocket &lf_reference_set_socket = *lf_reference_set_sockets[
i];
2694 lf::InputSocket &lf_use_input = lf_node.
input(lazy_function.get_use_input(
i));
2698 static const bool static_true =
true;
2701 socket_usage_inputs.
add(&lf_use_input);
2702 lf::InputSocket &lf_reference_set_input = lf_node.
input(
2703 lazy_function.get_reference_set_input(
i));
2704 lf_graph.
add_link(lf_reference_set_socket, lf_reference_set_input);
2706 return &lf_node.
output(0);
2710 void insert_child_zone_node(
const bNodeTreeZone &child_zone, BuildGraphParams &graph_params)
2712 const int child_zone_i = child_zone.
index;
2713 ZoneBuildInfo &child_zone_info = zone_build_infos_[child_zone_i];
2714 lf::FunctionNode &child_zone_node = graph_params.lf_graph.add_function(
2715 *child_zone_info.lazy_function);
2716 mapping_->
zone_node_map.add_new(&child_zone, &child_zone_node);
2719 int valid_socket_i = 0;
2724 lf::InputSocket &lf_input_socket = child_zone_node.
input(
2725 child_zone_info.indices.inputs.main[valid_socket_i]);
2726 lf::OutputSocket &lf_usage_socket = child_zone_node.
output(
2727 child_zone_info.indices.outputs.input_usages[valid_socket_i]);
2729 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_input_socket);
2730 graph_params.usage_by_bsocket.add(bsocket, &lf_usage_socket);
2735 int valid_socket_i = 0;
2740 lf::OutputSocket &lf_output_socket = child_zone_node.
output(
2741 child_zone_info.indices.outputs.main[valid_socket_i]);
2742 lf::InputSocket &lf_usage_input = child_zone_node.
input(
2743 child_zone_info.indices.inputs.output_usages[valid_socket_i]);
2745 graph_params.lf_output_by_bsocket.add(bsocket, &lf_output_socket);
2746 graph_params.socket_usage_inputs.add(&lf_usage_input);
2747 if (lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(bsocket,
2750 graph_params.lf_graph.add_link(*lf_usage, lf_usage_input);
2753 static const bool static_false =
false;
2760 const Span<const bNodeLink *> child_border_links = child_zone.
border_links;
2761 for (
const int child_border_link_i : child_border_links.
index_range()) {
2762 lf::InputSocket &child_border_link_input = child_zone_node.
input(
2763 child_zone_info.indices.inputs.border_links[child_border_link_i]);
2764 const bNodeLink &link = *child_border_links[child_border_link_i];
2765 graph_params.lf_input_by_border_link.add(&link, &child_border_link_input);
2766 lf::OutputSocket &lf_usage = child_zone_node.
output(
2767 child_zone_info.indices.outputs.border_link_usages[child_border_link_i]);
2768 graph_params.lf_inputs_by_bsocket.add(link.
tosock, &child_border_link_input);
2769 graph_params.usage_by_bsocket.add(link.
tosock, &lf_usage);
2772 for (
const auto &item : child_zone_info.indices.inputs.reference_sets.items()) {
2774 const int child_zone_input_i = item.value;
2775 lf::InputSocket &lf_reference_set_input = child_zone_node.
input(child_zone_input_i);
2777 graph_params.lf_reference_set_inputs.add(reference_set_i, &lf_reference_set_input);
2781 void build_main_group_inputs(lf::Graph &lf_graph)
2783 const Span<const bNodeTreeInterfaceSocket *> interface_inputs = btree_.interface_inputs();
2787 group_input_sockets_.
append(&lf_socket);
2795 void build_fallback_group_outputs(lf::Graph &lf_graph)
2798 const bke::bNodeSocketType *typeinfo = interface_output->socket_typeinfo();
2801 interface_output->
name ? interface_output->name :
"");
2803 standard_group_output_sockets_.
append(&lf_socket);
2807 void insert_node_in_graph(
const bNode &bnode, BuildGraphParams &graph_params)
2809 const bke::bNodeType *node_type = bnode.
typeinfo;
2810 if (node_type ==
nullptr) {
2813 if (bnode.is_muted()) {
2814 this->build_muted_node(bnode, graph_params);
2817 if (bnode.is_group()) {
2820 this->build_group_node(bnode, graph_params);
2823 switch (node_type->type_legacy) {
2829 this->build_reroute_node(bnode, graph_params);
2833 this->handle_group_input_node(bnode, graph_params);
2837 this->build_group_output_node(bnode, graph_params);
2841 this->build_viewer_node(bnode, graph_params);
2845 this->build_switch_node(bnode, graph_params);
2849 this->build_index_switch_node(bnode, graph_params);
2853 this->build_warning_node(bnode, graph_params);
2859 this->build_gizmo_node(bnode, graph_params);
2863 this->build_bake_node(bnode, graph_params);
2867 this->build_menu_switch_node(bnode, graph_params);
2871 this->build_evaluate_closure_node(bnode, graph_params);
2875 if (node_type->geometry_node_execute) {
2876 this->build_geometry_node(bnode, graph_params);
2879 const NodeMultiFunctions::Item &fn_item = node_multi_functions_.
try_get(bnode);
2880 if (fn_item.fn !=
nullptr) {
2881 this->build_multi_function_node(bnode, fn_item, graph_params);
2884 if (bnode.is_type(
"NodeEnableOutput")) {
2885 this->build_enable_output_node(bnode, graph_params);
2888 if (bnode.is_undefined()) {
2889 this->build_undefined_node(bnode, graph_params);
2898 void build_muted_node(
const bNode &bnode, BuildGraphParams &graph_params)
2900 auto &lazy_function = scope_.
construct<LazyFunctionForMutedNode>(
2902 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
2903 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
2905 if (lf_index == -1) {
2908 lf::InputSocket &lf_socket = lf_node.input(lf_index);
2909 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
2912 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
2914 if (lf_index == -1) {
2917 lf::OutputSocket &lf_socket = lf_node.output(lf_index);
2918 graph_params.lf_output_by_bsocket.add_new(bsocket, &lf_socket);
2922 this->build_muted_node_usages(bnode, graph_params);
2928 void build_muted_node_usages(
const bNode &bnode, BuildGraphParams &graph_params)
2931 MultiValueMap<const bNodeSocket *, const bNodeSocket *> outputs_by_input;
2932 for (
const bNodeLink &blink : bnode.internal_links()) {
2933 outputs_by_input.
add(blink.fromsock, blink.tosock);
2935 for (
const auto item : outputs_by_input.
items()) {
2937 const Span<const bNodeSocket *> output_bsockets = item.value;
2940 Vector<lf::OutputSocket *> lf_socket_usages;
2941 for (
const bNodeSocket *output_bsocket : output_bsockets) {
2942 if (lf::OutputSocket *lf_socket = graph_params.usage_by_bsocket.lookup_default(
2943 output_bsocket,
nullptr))
2945 lf_socket_usages.
append(lf_socket);
2948 graph_params.usage_by_bsocket.add(&input_bsocket,
2949 this->or_socket_usages(lf_socket_usages, graph_params));
2953 void build_reroute_node(
const bNode &bnode, BuildGraphParams &graph_params)
2955 const bNodeSocket &input_bsocket = bnode.input_socket(0);
2956 const bNodeSocket &output_bsocket = bnode.output_socket(0);
2957 if (!input_bsocket.
typeinfo->geometry_nodes_default_value) {
2961 auto &lazy_function = scope_.
construct<LazyFunctionForRerouteNode>();
2962 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
2964 lf::InputSocket &lf_input = lf_node.input(0);
2965 lf::OutputSocket &lf_output = lf_node.output(0);
2966 graph_params.lf_inputs_by_bsocket.add(&input_bsocket, &lf_input);
2967 graph_params.lf_output_by_bsocket.add_new(&output_bsocket, &lf_output);
2971 if (lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(
2972 &bnode.output_socket(0),
nullptr))
2974 graph_params.usage_by_bsocket.add(&bnode.input_socket(0), lf_usage);
2978 void handle_group_input_node(
const bNode &bnode, BuildGraphParams &graph_params)
2980 for (
const int i : btree_.interface_inputs().index_range()) {
2983 group_input_sockets_[
i]);
2984 graph_params.lf_output_by_bsocket.add_new(&bsocket, &lf_socket);
2989 void build_group_output_node(
const bNode &bnode, BuildGraphParams &graph_params)
2991 Vector<lf::GraphOutputSocket *> lf_graph_outputs;
2993 for (
const int i : btree_.interface_outputs().index_range()) {
2998 lf_graph_outputs.
append(&lf_socket);
2999 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3003 if (&bnode == btree_.group_output_node()) {
3004 standard_group_output_sockets_ = lf_graph_outputs.
as_span();
3008 void build_group_node(
const bNode &bnode, BuildGraphParams &graph_params)
3011 if (group_btree ==
nullptr) {
3014 const GeometryNodesLazyFunctionGraphInfo *group_lf_graph_info =
3016 if (group_lf_graph_info ==
nullptr) {
3020 auto &lazy_function = scope_.
construct<LazyFunctionForGroupNode>(
3021 bnode, *group_lf_graph_info, *lf_graph_info_);
3022 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(lazy_function);
3024 for (
const int i : bnode.input_sockets().index_range()) {
3027 lf::InputSocket &lf_socket = lf_node.input(group_lf_graph_info->function.inputs.main[
i]);
3028 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3031 for (
const int i : bnode.output_sockets().index_range()) {
3033 lf::OutputSocket &lf_socket = lf_node.output(group_lf_graph_info->function.outputs.main[
i]);
3034 graph_params.lf_output_by_bsocket.add_new(&bsocket, &lf_socket);
3038 lf_graph_info_->num_inline_nodes_approximate +=
3039 group_lf_graph_info->num_inline_nodes_approximate;
3040 static const bool static_false =
false;
3041 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
3043 const int lf_input_index =
3045 if (lf_input_index != -1) {
3046 lf::InputSocket &lf_input = lf_node.input(lf_input_index);
3048 graph_params.socket_usage_inputs.add(&lf_input);
3053 const int lf_input_index =
3055 if (lf_input_index != -1) {
3056 lf::InputSocket &lf_input = lf_node.input(lf_input_index);
3057 graph_params.lf_reference_set_input_by_output.add(bsocket, &lf_input);
3062 this->build_group_node_socket_usage(bnode, lf_node, graph_params, *group_lf_graph_info);
3065 void build_group_node_socket_usage(
const bNode &bnode,
3066 lf::FunctionNode &lf_group_node,
3067 BuildGraphParams &graph_params,
3068 const GeometryNodesLazyFunctionGraphInfo &group_lf_graph_info)
3070 for (
const bNodeSocket *input_bsocket : bnode.input_sockets()) {
3071 const int input_index = input_bsocket->index();
3072 const InputUsageHint &input_usage_hint =
3073 group_lf_graph_info.mapping.group_input_usage_hints[input_index];
3074 switch (input_usage_hint.type) {
3075 case InputUsageHintType::Never: {
3079 case InputUsageHintType::DependsOnOutput: {
3080 Vector<lf::OutputSocket *> output_usages;
3081 for (
const int i : input_usage_hint.output_dependencies) {
3082 if (lf::OutputSocket *lf_socket = graph_params.usage_by_bsocket.lookup_default(
3083 &bnode.output_socket(
i),
nullptr))
3085 output_usages.
append(lf_socket);
3088 graph_params.usage_by_bsocket.add(input_bsocket,
3089 this->or_socket_usages(output_usages, graph_params));
3092 case InputUsageHintType::DynamicSocket: {
3093 graph_params.usage_by_bsocket.add(
3096 group_lf_graph_info.function.outputs.input_usages[input_index]));
3102 for (
const bNodeSocket *output_bsocket : bnode.output_sockets()) {
3103 const int lf_input_index =
3107 lf::InputSocket &lf_socket = lf_group_node.
input(lf_input_index);
3108 if (lf::OutputSocket *lf_output_is_used = graph_params.usage_by_bsocket.lookup_default(
3109 output_bsocket,
nullptr))
3111 graph_params.lf_graph.add_link(*lf_output_is_used, lf_socket);
3114 static const bool static_false =
false;
3120 void build_geometry_node(
const bNode &bnode, BuildGraphParams &graph_params)
3122 auto &lazy_function = scope_.
construct<LazyFunctionForGeometryNode>(bnode, *lf_graph_info_);
3123 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
3125 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
3127 if (lf_index == -1) {
3130 lf::InputSocket &lf_socket = lf_node.input(lf_index);
3132 if (bsocket->is_multi_input()) {
3133 auto &multi_input_lazy_function = scope_.
construct<LazyFunctionForMultiInput>(*bsocket);
3134 lf::Node &lf_multi_input_node = graph_params.lf_graph.add_function(
3135 multi_input_lazy_function);
3136 graph_params.lf_graph.add_link(lf_multi_input_node.
output(0), lf_socket);
3137 for (
const int i : multi_input_lazy_function.links.index_range()) {
3138 lf::InputSocket &lf_multi_input_socket = lf_multi_input_node.
input(
i);
3139 const bNodeLink *link = multi_input_lazy_function.links[
i];
3140 graph_params.lf_input_by_multi_input_link.add(link, &lf_multi_input_socket);
3142 lf_multi_input_socket.
set_default_value(bsocket->typeinfo->geometry_nodes_default_value);
3146 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
3150 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
3152 if (lf_index == -1) {
3155 lf::OutputSocket &lf_socket = lf_node.output(lf_index);
3156 graph_params.lf_output_by_bsocket.add_new(bsocket, &lf_socket);
3160 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
3162 const int lf_input_index =
3164 if (lf_input_index != -1) {
3165 lf::InputSocket &lf_input_socket = lf_node.input(lf_input_index);
3166 if (lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(bsocket,
3169 graph_params.lf_graph.add_link(*lf_usage, lf_input_socket);
3172 static const bool static_false =
false;
3175 graph_params.socket_usage_inputs.add_new(&lf_node.input(lf_input_index));
3180 const int lf_input_index =
3182 if (lf_input_index != -1) {
3183 graph_params.lf_reference_set_input_by_output.add(bsocket,
3184 &lf_node.input(lf_input_index));
3189 this->build_standard_node_input_socket_usage(bnode, graph_params);
3192 void build_standard_node_input_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
3194 if (bnode.input_sockets().is_empty()) {
3198 Vector<lf::OutputSocket *> output_usages;
3199 for (
const bNodeSocket *output_socket : bnode.output_sockets()) {
3200 if (!output_socket->is_available()) {
3203 if (lf::OutputSocket *is_used_socket = graph_params.usage_by_bsocket.lookup_default(
3204 output_socket,
nullptr))
3211 lf::OutputSocket *lf_usage = this->or_socket_usages(output_usages, graph_params);
3212 if (lf_usage ==
nullptr) {
3216 for (
const bNodeSocket *input_socket : bnode.input_sockets()) {
3217 if (input_socket->is_available()) {
3218 graph_params.usage_by_bsocket.add(input_socket, lf_usage);
3223 void build_multi_function_node(
const bNode &bnode,
3224 const NodeMultiFunctions::Item &fn_item,
3225 BuildGraphParams &graph_params)
3227 auto &lazy_function = scope_.
construct<LazyFunctionForMultiFunctionNode>(
3229 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(lazy_function);
3231 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
3233 if (lf_index == -1) {
3237 lf::InputSocket &lf_socket = lf_node.input(lf_index);
3238 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
3241 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
3243 if (lf_index == -1) {
3246 lf::OutputSocket &lf_socket = lf_node.output(lf_index);
3247 graph_params.lf_output_by_bsocket.add(bsocket, &lf_socket);
3251 this->build_standard_node_input_socket_usage(bnode, graph_params);
3254 void build_viewer_node(
const bNode &bnode, BuildGraphParams &graph_params)
3256 auto &lazy_function = scope_.
construct<LazyFunctionForViewerNode>(
3258 lf::FunctionNode &lf_viewer_node = graph_params.lf_graph.add_function(lazy_function);
3260 for (
const bNodeSocket *bsocket : bnode.input_sockets().drop_back(1)) {
3262 lf::InputSocket &lf_socket = lf_viewer_node.input(lf_index);
3263 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
3270 auto &usage_lazy_function = scope_.
construct<LazyFunctionForViewerInputUsage>(
3272 lf::FunctionNode &lf_usage_node = graph_params.lf_graph.add_function(usage_lazy_function);
3274 for (
const bNodeSocket *bsocket : bnode.input_sockets().drop_back(1)) {
3275 graph_params.usage_by_bsocket.add(bsocket, &lf_usage_node.output(0));
3280 void build_gizmo_node(
const bNode &bnode, BuildGraphParams &graph_params)
3282 auto &lazy_function = scope_.
construct<LazyFunctionForGizmoNode>(
3284 lf::FunctionNode &lf_gizmo_node = graph_params.lf_graph.add_function(lazy_function);
3285 lazy_function.self_node = &lf_gizmo_node;
3287 for (
const int i : lazy_function.gizmo_links.index_range()) {
3288 const bNodeLink &link = *lazy_function.gizmo_links[
i];
3289 lf::InputSocket &lf_socket = lf_gizmo_node.input(
i);
3290 graph_params.lf_input_by_multi_input_link.add(&link, &lf_socket);
3292 for (
const int i : bnode.input_sockets().drop_front(1).index_range()) {
3293 lf::InputSocket &lf_socket = lf_gizmo_node.input(
i + lazy_function.gizmo_links.size());
3294 const bNodeSocket &bsocket = bnode.input_socket(
i + 1);
3295 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3298 for (
const int i : bnode.output_sockets().index_range()) {
3299 lf::OutputSocket &lf_socket = lf_gizmo_node.output(
i);
3301 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
3305 this->build_gizmo_node_socket_usage(bnode, graph_params, lf_gizmo_node);
3310 void build_gizmo_node_socket_usage(
const bNode &bnode,
3311 BuildGraphParams &graph_params,
3312 const lf::FunctionNode &lf_gizmo_node)
3314 const auto &usage_fn = scope_.
construct<LazyFunctionForGizmoInputsUsage>(bnode, lf_gizmo_node);
3315 lf::FunctionNode &lf_usage_node = graph_params.lf_graph.add_function(usage_fn);
3316 for (
const bNodeSocket *bsocket : bnode.input_sockets()) {
3317 graph_params.usage_by_bsocket.add(bsocket, &lf_usage_node.output(0));
3321 lf::FunctionNode *insert_simulation_input_node(
const bNodeTree &node_tree,
3323 BuildGraphParams &graph_params)
3332 node_tree, bnode, *lf_graph_info_);
3333 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3334 scope_.
add(std::move(lazy_function));
3336 for (
const int i : bnode.input_sockets().index_range().drop_back(1)) {
3338 lf::InputSocket &lf_socket = lf_node.
input(
3340 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3343 for (
const int i : bnode.output_sockets().index_range().drop_back(1)) {
3345 lf::OutputSocket &lf_socket = lf_node.
output(
3347 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
3353 lf::FunctionNode &insert_simulation_output_node(
const bNode &bnode,
3354 BuildGraphParams &graph_params)
3357 bnode, *lf_graph_info_);
3358 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3359 scope_.
add(std::move(lazy_function));
3361 for (
const int i : bnode.input_sockets().index_range().drop_back(1)) {
3363 lf::InputSocket &lf_socket = lf_node.
input(
3365 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3368 for (
const int i : bnode.output_sockets().index_range().drop_back(1)) {
3370 lf::OutputSocket &lf_socket = lf_node.
output(
3372 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
3381 void build_bake_node(
const bNode &bnode, BuildGraphParams &graph_params)
3384 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3385 scope_.
add(std::move(lazy_function));
3387 for (
const int i : bnode.input_sockets().index_range().drop_back(1)) {
3389 lf::InputSocket &lf_socket = lf_node.
input(
3391 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3394 for (
const int i : bnode.output_sockets().index_range().drop_back(1)) {
3396 lf::OutputSocket &lf_socket = lf_node.
output(
3398 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
3404 this->build_bake_node_socket_usage(bnode, graph_params);
3407 void build_bake_node_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
3409 const LazyFunction &usage_fn = scope_.
construct<LazyFunctionForBakeInputsUsage>(bnode);
3410 lf::FunctionNode &lf_usage_node = graph_params.lf_graph.add_function(usage_fn);
3411 const int items_num = bnode.input_sockets().size() - 1;
3412 for (
const int i : IndexRange(items_num)) {
3413 graph_params.usage_by_bsocket.add(&bnode.input_socket(
i), &lf_usage_node.output(0));
3417 void build_switch_node(
const bNode &bnode, BuildGraphParams &graph_params)
3420 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3421 scope_.
add(std::move(lazy_function));
3423 for (
const int i : bnode.input_sockets().index_range()) {
3424 graph_params.lf_inputs_by_bsocket.add(&bnode.input_socket(
i), &lf_node.
input(
i));
3428 graph_params.lf_output_by_bsocket.add(&bnode.output_socket(0), &lf_node.
output(0));
3431 this->build_switch_node_socket_usage(bnode, graph_params);
3434 void build_switch_node_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
3436 const bNodeSocket &switch_input_bsocket = bnode.input_socket(0);
3437 const bNodeSocket &false_input_bsocket = bnode.input_socket(1);
3438 const bNodeSocket &true_input_bsocket = bnode.input_socket(2);
3439 const bNodeSocket &output_bsocket = bnode.output_socket(0);
3440 lf::OutputSocket *output_is_used_socket = graph_params.usage_by_bsocket.
lookup_default(
3441 &output_bsocket,
nullptr);
3442 if (output_is_used_socket ==
nullptr) {
3445 graph_params.usage_by_bsocket.add(&switch_input_bsocket, output_is_used_socket);
3446 if (switch_input_bsocket.is_directly_linked()) {
3448 static const LazyFunctionForSwitchSocketUsage switch_socket_usage_fn;
3449 lf::Node &lf_node = graph_params.lf_graph.add_function(switch_socket_usage_fn);
3450 graph_params.lf_inputs_by_bsocket.add(&switch_input_bsocket, &lf_node.
input(0));
3451 graph_params.usage_by_bsocket.add(&false_input_bsocket, &lf_node.
output(0));
3452 graph_params.usage_by_bsocket.add(&true_input_bsocket, &lf_node.
output(1));
3456 graph_params.usage_by_bsocket.add(&true_input_bsocket, output_is_used_socket);
3459 graph_params.usage_by_bsocket.add(&false_input_bsocket, output_is_used_socket);
3464 void build_enable_output_node(
const bNode &bnode, BuildGraphParams &graph_params)
3467 bnode, *lf_graph_info_);
3468 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3469 scope_.
add(std::move(lazy_function));
3471 for (
const int i : bnode.input_sockets().index_range()) {
3472 graph_params.lf_inputs_by_bsocket.add(&bnode.input_socket(
i), &lf_node.
input(
i));
3475 for (
const int i : bnode.output_sockets().index_range()) {
3476 graph_params.lf_output_by_bsocket.add(&bnode.output_socket(
i), &lf_node.
output(
i));
3480 this->build_enable_output_node_socket_usage(bnode, graph_params);
3483 void build_enable_output_node_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
3485 const bNodeSocket &enable_bsocket = *bnode.input_by_identifier(
"Enable");
3486 const bNodeSocket &value_input_bsocket = *bnode.input_by_identifier(
"Value");
3487 const bNodeSocket &output_bsocket = bnode.output_socket(0);
3488 lf::OutputSocket *output_is_used_socket = graph_params.usage_by_bsocket.lookup_default(
3489 &output_bsocket,
nullptr);
3490 if (!output_is_used_socket) {
3493 static LazyFunctionForEnableOutputSocketUsage socket_usage_fn;
3494 lf::Node &lf_node = graph_params.lf_graph.add_function(socket_usage_fn);
3495 graph_params.lf_inputs_by_bsocket.add(&enable_bsocket, &lf_node.
input(0));
3496 graph_params.usage_by_bsocket.add(&enable_bsocket, output_is_used_socket);
3497 graph_params.usage_by_bsocket.add(&value_input_bsocket, &lf_node.
output(0));
3500 void build_index_switch_node(
const bNode &bnode, BuildGraphParams &graph_params)
3503 bnode, *lf_graph_info_);
3504 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3505 scope_.
add(std::move(lazy_function));
3507 for (
const int i : bnode.input_sockets().drop_back(1).index_range()) {
3508 graph_params.lf_inputs_by_bsocket.add(&bnode.input_socket(
i), &lf_node.
input(
i));
3512 graph_params.lf_output_by_bsocket.add(&bnode.output_socket(0), &lf_node.
output(0));
3515 this->build_index_switch_node_socket_usage(bnode, graph_params);
3518 void build_index_switch_node_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
3520 const bNodeSocket &index_socket = bnode.input_socket(0);
3521 const int items_num = bnode.input_sockets().size() - 1;
3523 lf::OutputSocket *output_is_used = graph_params.usage_by_bsocket.
lookup_default(
3524 &bnode.output_socket(0),
nullptr);
3525 if (output_is_used ==
nullptr) {
3528 graph_params.usage_by_bsocket.add(&index_socket, output_is_used);
3529 if (index_socket.is_directly_linked()) {
3531 auto usage_fn = std::make_unique<LazyFunctionForIndexSwitchSocketUsage>(bnode);
3532 lf::Node &lf_node = graph_params.lf_graph.add_function(*usage_fn);
3533 scope_.
add(std::move(usage_fn));
3535 graph_params.lf_inputs_by_bsocket.add(&index_socket, &lf_node.
input(0));
3536 for (
const int i : IndexRange(items_num)) {
3537 graph_params.usage_by_bsocket.add(&bnode.input_socket(
i + 1), &lf_node.
output(
i));
3542 if (IndexRange(items_num).
contains(index)) {
3543 graph_params.usage_by_bsocket.add(&bnode.input_socket(index + 1), output_is_used);
3548 void build_warning_node(
const bNode &bnode, BuildGraphParams &graph_params)
3551 LazyFunction &lazy_function = *lazy_function_ptr;
3552 scope_.
add(std::move(lazy_function_ptr));
3554 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
3556 for (
const int i : bnode.input_sockets().index_range()) {
3558 lf::InputSocket &lf_socket = lf_node.
input(
i);
3559 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3562 for (
const int i : bnode.output_sockets().index_range()) {
3564 lf::OutputSocket &lf_socket = lf_node.
output(
i);
3565 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
3569 const bNodeSocket &output_bsocket = bnode.output_socket(0);
3571 lf::OutputSocket *lf_usage =
nullptr;
3572 if (output_bsocket.is_directly_linked()) {
3574 lf_usage = graph_params.usage_by_bsocket.lookup_default(&output_bsocket,
nullptr);
3578 lf_usage = this->or_socket_usages(group_output_used_sockets_, graph_params);
3581 for (
const bNodeSocket *socket : bnode.input_sockets()) {
3582 graph_params.usage_by_bsocket.add(socket, lf_usage);
3587 void build_menu_switch_node(
const bNode &bnode, BuildGraphParams &graph_params)
3590 bnode, *lf_graph_info_);
3591 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3592 scope_.
add(std::move(lazy_function));
3594 int input_index = 0;
3595 for (
const bNodeSocket *bsocket : bnode.input_sockets().drop_back(1)) {
3596 if (bsocket->is_available()) {
3597 lf::InputSocket &lf_socket = lf_node.
input(input_index);
3598 graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_socket);
3603 int output_index = 0;
3604 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
3605 if (bsocket->is_available()) {
3606 lf::OutputSocket &lf_socket = lf_node.
output(output_index);
3607 graph_params.lf_output_by_bsocket.add(bsocket, &lf_socket);
3613 this->build_menu_switch_node_socket_usage(bnode, graph_params);
3616 void build_menu_switch_node_socket_usage(
const bNode &bnode, BuildGraphParams &graph_params)
3621 const bNodeSocket *switch_input_bsocket = bnode.input_sockets()[0];
3622 Vector<const bNodeSocket *> input_bsockets(enum_def.
items_num);
3623 for (
const int i : IndexRange(enum_def.
items_num)) {
3624 input_bsockets[
i] = bnode.input_sockets()[
i + 1];
3626 const bNodeSocket *output_bsocket = bnode.output_sockets()[0];
3628 lf::OutputSocket *output_is_used_socket = graph_params.usage_by_bsocket.lookup_default(
3629 output_bsocket,
nullptr);
3630 if (output_is_used_socket ==
nullptr) {
3633 graph_params.usage_by_bsocket.add(switch_input_bsocket, output_is_used_socket);
3634 if (switch_input_bsocket->is_directly_linked()) {
3636 std::unique_ptr<LazyFunction> lazy_function =
3638 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*lazy_function);
3639 scope_.
add(std::move(lazy_function));
3641 graph_params.lf_inputs_by_bsocket.add(switch_input_bsocket, &lf_node.
input(0));
3642 for (
const int i : IndexRange(enum_def.
items_num)) {
3643 graph_params.usage_by_bsocket.add(input_bsockets[
i], &lf_node.
output(
i));
3647 const int condition =
3649 for (
const int i : IndexRange(enum_def.
items_num)) {
3652 graph_params.usage_by_bsocket.add(input_bsockets[
i], output_is_used_socket);
3659 void build_evaluate_closure_node(
const bNode &bnode, BuildGraphParams &graph_params)
3663 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(*function.lazy_function);
3664 const int inputs_num = bnode.input_sockets().size() - 1;
3665 const int outputs_num = bnode.output_sockets().size() - 1;
3666 BLI_assert(inputs_num == function.indices.inputs.main.size());
3667 BLI_assert(inputs_num == function.indices.outputs.input_usages.size());
3668 BLI_assert(outputs_num == function.indices.outputs.main.size());
3669 BLI_assert(outputs_num == function.indices.inputs.output_usages.size());
3673 for (
const int i : IndexRange(inputs_num)) {
3675 lf::InputSocket &lf_socket = lf_node.
input(function.indices.inputs.main[
i]);
3676 graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
3678 graph_params.usage_by_bsocket.add(&bsocket,
3679 &lf_node.
output(function.indices.outputs.input_usages[
i]));
3681 for (
const int i : IndexRange(outputs_num)) {
3683 lf::OutputSocket &lf_socket = lf_node.
output(function.indices.outputs.main[
i]);
3684 graph_params.lf_output_by_bsocket.add(&bsocket, &lf_socket);
3686 lf::InputSocket &lf_usage_socket = lf_node.
input(function.indices.inputs.output_usages[
i]);
3687 graph_params.socket_usage_inputs.add(&lf_usage_socket);
3688 if (lf::OutputSocket *output_is_used = graph_params.usage_by_bsocket.lookup(&bsocket)) {
3689 graph_params.lf_graph.add_link(*output_is_used, lf_usage_socket);
3692 static const bool static_false =
false;
3696 for (
const auto item : function.indices.inputs.reference_set_by_output.items()) {
3697 const bNodeSocket &bsocket = bnode.output_socket(item.key);
3698 lf_graph_info_->mapping
3699 .lf_input_index_for_reference_set_for_output[bsocket.index_in_all_outputs()] =
3701 graph_params.lf_reference_set_input_by_output.add(&bsocket, &lf_node.
input(item.value));
3705 void build_undefined_node(
const bNode &bnode, BuildGraphParams &graph_params)
3707 auto &lazy_function = scope_.
construct<LazyFunctionForUndefinedNode>(
3709 lf::FunctionNode &lf_node = graph_params.lf_graph.add_function(lazy_function);
3711 for (
const bNodeSocket *bsocket : bnode.output_sockets()) {
3713 if (lf_index == -1) {
3716 lf::OutputSocket &lf_socket = lf_node.output(lf_index);
3717 graph_params.lf_output_by_bsocket.add(bsocket, &lf_socket);
3722 struct TypeWithLinks {
3723 const bke::bNodeSocketType *typeinfo;
3724 Vector<const bNodeLink *> links;
3727 void insert_links_from_socket(
const bNodeSocket &from_bsocket,
3728 lf::OutputSocket &from_lf_socket,
3729 BuildGraphParams &graph_params)
3731 if (from_bsocket.owner_node().is_dangling_reroute()) {
3735 const bke::bNodeSocketType &from_typeinfo = *from_bsocket.
typeinfo;
3738 const Vector<TypeWithLinks> types_with_links = this->group_link_targets_by_type(from_bsocket);
3740 for (
const TypeWithLinks &type_with_links : types_with_links) {
3741 if (!type_with_links.typeinfo) {
3744 if (!type_with_links.typeinfo->geometry_nodes_default_value) {
3747 const bke::bNodeSocketType &to_typeinfo = *type_with_links.typeinfo;
3748 const Span<const bNodeLink *> links = type_with_links.links;
3750 lf::OutputSocket *converted_from_lf_socket = this->insert_type_conversion_if_necessary(
3751 from_lf_socket, from_typeinfo, to_typeinfo, graph_params.lf_graph);
3754 const Vector<lf::InputSocket *> lf_link_targets = this->find_link_targets(*link,
3756 if (converted_from_lf_socket ==
nullptr) {
3757 for (lf::InputSocket *to_lf_socket : lf_link_targets) {
3758 to_lf_socket->set_default_value(to_typeinfo.geometry_nodes_default_value);
3762 for (lf::InputSocket *to_lf_socket : lf_link_targets) {
3763 graph_params.lf_graph.add_link(*converted_from_lf_socket, *to_lf_socket);
3770 Vector<TypeWithLinks> group_link_targets_by_type(
const bNodeSocket &from_bsocket)
3772 const Span<const bNodeLink *> links_from_bsocket = from_bsocket.directly_linked_links();
3773 Vector<TypeWithLinks> types_with_links;
3774 for (
const bNodeLink *link : links_from_bsocket) {
3775 if (link->is_muted()) {
3778 if (!link->is_available()) {
3782 bool inserted =
false;
3783 for (TypeWithLinks &types_with_links : types_with_links) {
3784 if (types_with_links.typeinfo == to_bsocket.
typeinfo) {
3785 types_with_links.links.append(link);
3793 types_with_links.append({to_bsocket.
typeinfo, {link}});
3795 return types_with_links;
3798 Vector<lf::InputSocket *> find_link_targets(
const bNodeLink &link,
3799 const BuildGraphParams &graph_params)
3801 if (lf::InputSocket *lf_input_socket = graph_params.lf_input_by_border_link.lookup_default(
3804 return {lf_input_socket};
3808 if (to_bsocket.is_multi_input()) {
3811 for (
const bNodeLink *multi_input_link : to_bsocket.directly_linked_links()) {
3812 if (multi_input_link == &link) {
3815 if (multi_input_link->is_muted() || !multi_input_link->fromsock->is_available() ||
3816 multi_input_link->fromnode->is_dangling_reroute())
3822 if (to_bsocket.owner_node().is_muted()) {
3823 if (link_index == 0) {
3824 return Vector<lf::InputSocket *>(graph_params.lf_inputs_by_bsocket.lookup(&to_bsocket));
3828 lf::InputSocket *lf_multi_input_socket =
3829 graph_params.lf_input_by_multi_input_link.lookup_default(&link,
nullptr);
3830 if (!lf_multi_input_socket) {
3833 return {lf_multi_input_socket};
3837 return Vector<lf::InputSocket *>(graph_params.lf_inputs_by_bsocket.lookup(&to_bsocket));
3842 lf::OutputSocket *insert_type_conversion_if_necessary(lf::OutputSocket &from_socket,
3843 const bke::bNodeSocketType &from_typeinfo,
3844 const bke::bNodeSocketType &to_typeinfo,
3845 lf::Graph &lf_graph)
3847 if (from_typeinfo.type == to_typeinfo.type) {
3848 return &from_socket;
3851 from_typeinfo, to_typeinfo, scope_))
3853 lf::Node &conversion_node = lf_graph.
add_function(*conversion_fn);
3855 return &conversion_node.
output(0);
3860 void add_default_inputs(BuildGraphParams &graph_params)
3862 for (
auto item : graph_params.lf_inputs_by_bsocket.items()) {
3864 const Span<lf::InputSocket *> lf_sockets = item.value;
3865 for (lf::InputSocket *lf_socket : lf_sockets) {
3866 if (lf_socket->origin() !=
nullptr) {
3870 this->add_default_input(bsocket, *lf_socket, graph_params);
3875 void add_default_input(
const bNodeSocket &input_bsocket,
3876 lf::InputSocket &input_lf_socket,
3877 BuildGraphParams &graph_params)
3879 if (this->try_add_implicit_input(input_bsocket, input_lf_socket, graph_params)) {
3886 bool try_add_implicit_input(
const bNodeSocket &input_bsocket,
3887 lf::InputSocket &input_lf_socket,
3888 BuildGraphParams &graph_params)
3890 const bNode &bnode = input_bsocket.owner_node();
3891 const SocketDeclaration *socket_decl = input_bsocket.
runtime->declaration;
3892 if (socket_decl ==
nullptr) {
3900 if (!implicit_input_fn.has_value()) {
3903 std::function<void(
void *)> init_fn = [&bnode, implicit_input_fn](
void *r_value) {
3904 (*implicit_input_fn)(bnode, r_value);
3906 const CPPType &type = input_lf_socket.
type();
3907 auto &lazy_function = scope_.
construct<LazyFunctionForImplicitInput>(type, std::move(init_fn));
3908 lf::Node &lf_node = graph_params.lf_graph.add_function(lazy_function);
3909 graph_params.lf_graph.add_link(lf_node.output(0), input_lf_socket);
3918 void build_root_reference_set_inputs(lf::Graph &lf_graph)
3920 const aal::RelationsInNode &tree_relations = reference_lifetimes_.
tree_relations;
3921 Vector<int> output_indices;
3922 for (
const aal::PropagateRelation &relation : tree_relations.propagate_relations) {
3927 const int output_index = output_indices[
i];
3928 const char *
name = btree_.interface_outputs()[output_index]->name;
3931 StringRef(
"Propagate: ") + (
name ?
name :
""));
3932 reference_set_by_output_.
add(output_index, &lf_socket);
3940 lf::OutputSocket *or_socket_usages(
const Span<lf::OutputSocket *> usages,
3941 BuildGraphParams &graph_params)
3946 if (usages.
size() == 1) {
3951 Vector<lf::OutputSocket *> usages_sorted(usages);
3952 std::sort(usages_sorted.begin(), usages_sorted.end());
3953 return graph_params.socket_usages_combination_cache.lookup_or_add_cb(
3954 std::move(usages_sorted), [&]() {
3955 auto &logical_or_fn = scope_.
construct<LazyFunctionForLogicalOr>(usages.
size());
3956 lf::Node &logical_or_node = graph_params.lf_graph.add_function(logical_or_fn);
3958 for (
const int i : usages_sorted.index_range()) {
3959 graph_params.lf_graph.add_link(*usages_sorted[
i], logical_or_node.
input(
i));
3961 return &logical_or_node.
output(0);
3965 void build_output_socket_usages(
const bNode &bnode, BuildGraphParams &graph_params)
3968 for (
const bNodeSocket *socket : bnode.output_sockets()) {
3969 if (!socket->is_available()) {
3973 Vector<lf::OutputSocket *> target_usages;
3974 for (
const bNodeLink *link : socket->directly_linked_links()) {
3975 if (!link->is_used()) {
3979 if (lf::OutputSocket *is_used_socket = graph_params.usage_by_bsocket.lookup_default(
3980 &target_socket,
nullptr))
3986 graph_params.usage_by_bsocket.add(socket,
3987 this->or_socket_usages(target_usages, graph_params));
3991 void build_group_input_usages(BuildGraphParams &graph_params)
3993 const Span<const bNode *> group_input_nodes = btree_.group_input_nodes();
3994 for (
const int i : btree_.interface_inputs().index_range()) {
3995 Vector<lf::OutputSocket *> target_usages;
3996 for (
const bNode *group_input_node : group_input_nodes) {
3997 if (lf::OutputSocket *lf_socket = graph_params.usage_by_bsocket.lookup_default(
3998 &group_input_node->output_socket(
i),
nullptr))
4004 lf::OutputSocket *lf_socket = this->or_socket_usages(target_usages, graph_params);
4005 lf::InputSocket *lf_group_output =
const_cast<lf::InputSocket *
>(
4006 group_input_usage_sockets_[
i]);
4007 InputUsageHint input_usage_hint;
4008 if (lf_socket ==
nullptr) {
4009 static const bool static_false =
false;
4011 input_usage_hint.type = InputUsageHintType::Never;
4014 graph_params.lf_graph.add_link(*lf_socket, *lf_group_output);
4018 input_usage_hint.type = InputUsageHintType::DependsOnOutput;
4019 input_usage_hint.output_dependencies = {
4023 input_usage_hint.type = InputUsageHintType::DynamicSocket;
4026 lf_graph_info_->mapping.group_input_usage_hints.append(std::move(input_usage_hint));
4041 void fix_link_cycles(lf::Graph &lf_graph,
const Set<lf::InputSocket *> &socket_usage_inputs)
4044 const int sockets_num = lf_graph.
socket_num();
4046 struct SocketState {
4048 bool in_stack =
false;
4051 Array<SocketState> socket_states(sockets_num);
4053 Vector<lf::Socket *> lf_sockets_to_check;
4054 for (lf::Node *lf_node : lf_graph.
nodes()) {
4055 if (lf_node->is_function()) {
4056 for (lf::OutputSocket *lf_socket : lf_node->outputs()) {
4057 if (lf_socket->
targets().is_empty()) {
4058 lf_sockets_to_check.
append(lf_socket);
4062 if (lf_node->outputs().is_empty()) {
4063 for (lf::InputSocket *lf_socket : lf_node->inputs()) {
4064 lf_sockets_to_check.
append(lf_socket);
4068 Vector<lf::Socket *> lf_socket_stack;
4069 while (!lf_sockets_to_check.
is_empty()) {
4070 lf::Socket *lf_inout_socket = lf_sockets_to_check.
last();
4071 lf::Node &lf_node = lf_inout_socket->
node();
4074 if (!
state.in_stack) {
4075 lf_socket_stack.
append(lf_inout_socket);
4076 state.in_stack =
true;
4079 Vector<lf::Socket *, 16> lf_origin_sockets;
4081 lf::InputSocket &lf_input_socket = lf_inout_socket->
as_input();
4082 if (lf::OutputSocket *lf_origin_socket = lf_input_socket.
origin()) {
4083 lf_origin_sockets.
append(lf_origin_socket);
4087 lf::OutputSocket &lf_output_socket = lf_inout_socket->
as_output();
4089 lf::FunctionNode &lf_function_node =
static_cast<lf::FunctionNode &
>(lf_node);
4090 const lf::LazyFunction &fn = lf_function_node.
function();
4092 lf_output_socket.
index(), [&](
const Span<int> input_indices) {
4093 for (const int input_index : input_indices) {
4094 lf_origin_sockets.append(&lf_node.input(input_index));
4100 bool pushed_socket =
false;
4101 bool detected_cycle =
false;
4102 for (lf::Socket *lf_origin_socket : lf_origin_sockets) {
4103 if (socket_states[lf_origin_socket->index_in_graph()].in_stack) {
4113 detected_cycle =
true;
4114 const int index_in_socket_stack = lf_socket_stack.
first_index_of(lf_origin_socket);
4115 const int index_in_sockets_to_check = lf_sockets_to_check.
first_index_of(
4117 const Span<lf::Socket *> cycle = lf_socket_stack.
as_span().drop_front(
4118 index_in_socket_stack);
4120 bool broke_cycle =
false;
4121 for (lf::Socket *lf_cycle_socket : cycle) {
4122 if (lf_cycle_socket->is_input() &&
4123 socket_usage_inputs.
contains(&lf_cycle_socket->as_input()))
4125 lf::InputSocket &lf_cycle_input_socket = lf_cycle_socket->as_input();
4127 static const bool static_true =
true;
4132 SocketState &lf_cycle_socket_state = socket_states[lf_cycle_socket->index_in_graph()];
4133 lf_cycle_socket_state.in_stack =
false;
4140 lf_socket_stack.
resize(index_in_socket_stack);
4142 lf_sockets_to_check.
resize(index_in_sockets_to_check + 1);
4145 if (!socket_states[lf_origin_socket->index_in_graph()].done) {
4146 lf_sockets_to_check.
append(lf_origin_socket);
4147 pushed_socket =
true;
4150 if (detected_cycle) {
4153 if (pushed_socket) {
4158 state.in_stack =
false;