Fix #115782: Support dangling Reroute nodes as border links of zones #116920

Closed
Iliya Katushenock wants to merge 4 commits from mod_moder:fix_reroute_zone into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
1 changed files with 149 additions and 137 deletions

View File

@ -1445,9 +1445,9 @@ struct BuildGraphParams {
struct ZoneFunctionIndices {
struct {
IndexRange main;
IndexRange border_links;
IndexRange output_usages;
Vector<int> main;
Vector<int> border_links;
Vector<int> output_usages;
/**
* Some attribute sets are input into the body of a zone from the outside. These two
* maps indicate which zone function inputs corresponds to attribute set. Attribute sets are
@ -1457,9 +1457,9 @@ struct ZoneFunctionIndices {
Map<int, int> attributes_by_caller_propagation_index;
} inputs;
struct {
IndexRange main;
IndexRange border_link_usages;
IndexRange input_usages;
Vector<int> main;
Vector<int> border_link_usages;
Vector<int> input_usages;
} outputs;
};
@ -1566,57 +1566,70 @@ struct RepeatEvalStorage {
class LazyFunctionForRepeatZone : public LazyFunction {
private:
const bNodeTree &btree_;
const bNodeTreeZone &zone_;
const bNode &repeat_output_bnode_;
const ZoneBuildInfo &zone_info_;
const ZoneBodyFunction &body_fn_;
public:
LazyFunctionForRepeatZone(const bNodeTreeZone &zone,
LazyFunctionForRepeatZone(const bNodeTree &btree,
const bNodeTreeZone &zone,
ZoneBuildInfo &zone_info,
const ZoneBodyFunction &body_fn)
: zone_(zone),
: btree_(btree),
zone_(zone),
repeat_output_bnode_(*zone.output_node),
zone_info_(zone_info),
body_fn_(body_fn)
{
debug_name_ = "Repeat Zone";
inputs_.append_as("Iterations", CPPType::get<SocketValueVariant>(), lf::ValueUsage::Used);
const int iteration_input_index = inputs_.append_and_get_index_as(
"Iterations", CPPType::get<SocketValueVariant>(), lf::ValueUsage::Used);
zone_info.indices.inputs.main.append(iteration_input_index);
for (const bNodeSocket *socket : zone.input_node->input_sockets().drop_front(1).drop_back(1)) {
inputs_.append_as(
const int input_index = inputs_.append_and_get_index_as(
socket->name, *socket->typeinfo->geometry_nodes_cpp_type, lf::ValueUsage::Maybe);
zone_info.indices.inputs.main.append(input_index);
}
zone_info.indices.inputs.main = inputs_.index_range();
for (const bNodeLink *link : zone.border_links) {
inputs_.append_as(link->fromsock->name,
*link->tosock->typeinfo->geometry_nodes_cpp_type,
lf::ValueUsage::Maybe);
if (bke::nodeIsDanglingReroute(&btree_, link->fromnode)) {
continue;
}
const int border_link_index = inputs_.append_and_get_index_as(
link->fromsock->name,
*link->tosock->typeinfo->geometry_nodes_cpp_type,
lf::ValueUsage::Maybe);
zone_info.indices.inputs.border_links.append(border_link_index);
}
zone_info.indices.inputs.border_links = inputs_.index_range().take_back(
zone.border_links.size());
for (const bNodeSocket *socket : zone.output_node->output_sockets().drop_back(1)) {
inputs_.append_as("Usage", CPPType::get<bool>(), lf::ValueUsage::Maybe);
outputs_.append_as(socket->name, *socket->typeinfo->geometry_nodes_cpp_type);
const int output_usage_index = inputs_.append_and_get_index_as(
"Usage", CPPType::get<bool>(), lf::ValueUsage::Maybe);
zone_info.indices.inputs.output_usages.append(output_usage_index);
const int output_index = outputs_.append_and_get_index_as(
socket->name, *socket->typeinfo->geometry_nodes_cpp_type);
zone_info.indices.outputs.main.append(output_index);
}
zone_info.indices.inputs.output_usages = inputs_.index_range().take_back(
zone.output_node->output_sockets().drop_back(1).size());
zone_info.indices.outputs.main = outputs_.index_range();
for ([[maybe_unused]] const bNodeSocket *socket :
zone.input_node->input_sockets().drop_back(1))
{
outputs_.append_as("Usage", CPPType::get<bool>());
const int input_usage_index = outputs_.append_and_get_index_as("Usage",
CPPType::get<bool>());
zone_info.indices.outputs.input_usages.append(input_usage_index);
}
zone_info.indices.outputs.input_usages = outputs_.index_range().take_back(
zone.input_node->input_sockets().drop_back(1).size());
for ([[maybe_unused]] const bNodeLink *link : zone.border_links) {
outputs_.append_as("Border Link Usage", CPPType::get<bool>());
for (const bNodeLink *link : zone.border_links) {
if (bke::nodeIsDanglingReroute(&btree_, link->fromnode)) {
continue;
}
const int border_link_usage_index = outputs_.append_and_get_index_as("Border Link Usage",
CPPType::get<bool>());
zone_info.indices.outputs.border_link_usages.append(border_link_usage_index);
}
zone_info.indices.outputs.border_link_usages = outputs_.index_range().take_back(
zone.border_links.size());
for (const auto item : body_fn_.indices.inputs.attributes_by_field_source_index.items()) {
const int index = inputs_.append_and_get_index_as(
@ -2181,38 +2194,41 @@ struct GeometryNodesLazyFunctionBuilder {
const auto &sim_output_storage = *static_cast<const NodeGeometrySimulationOutput *>(
zone.output_node->storage);
Vector<lf::GraphInputSocket *> lf_zone_main_inputs;
Vector<lf::GraphOutputSocket *> lf_zone_main_input_usages;
Vector<lf::GraphInputSocket *> lf_zone_inputs;
Vector<lf::GraphOutputSocket *> lf_zone_outputs;
if (zone.input_node != nullptr) {
for (const bNodeSocket *bsocket : zone.input_node->input_sockets().drop_back(1)) {
lf_zone_main_inputs.append(
const int input_index = lf_zone_inputs.append_and_get_index(
&lf_graph.add_input(*bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name));
lf_zone_main_input_usages.append(
zone_info.indices.inputs.main.append(input_index);
const int input_usage_index = lf_zone_outputs.append_and_get_index(
&lf_graph.add_output(CPPType::get<bool>(), "Usage: " + StringRef(bsocket->name)));
zone_info.indices.outputs.input_usages.append(input_usage_index);
}
}
Vector<lf::GraphInputSocket *> lf_border_link_inputs = this->build_zone_border_links_inputs(
zone, lf_graph);
Vector<lf::GraphOutputSocket *> lf_zone_main_outputs;
Vector<lf::GraphInputSocket *> lf_zone_main_output_usages;
this->build_zone_border_links_inputs(
zone, lf_graph, lf_zone_inputs, zone_info.indices.inputs.border_links);
this->build_zone_border_link_input_usages(
zone, lf_graph, lf_zone_outputs, zone_info.indices.outputs.border_link_usages);
for (const bNodeSocket *bsocket : zone.output_node->output_sockets().drop_back(1)) {
lf_zone_main_outputs.append(
const int output_index = lf_zone_outputs.append_and_get_index(
&lf_graph.add_output(*bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name));
lf_zone_main_output_usages.append(
zone_info.indices.outputs.main.append(output_index);
const int output_usage_index = lf_zone_inputs.append_and_get_index(
&lf_graph.add_input(CPPType::get<bool>(), "Usage: " + StringRef(bsocket->name)));
zone_info.indices.inputs.output_usages.append(output_usage_index);
}
Vector<lf::GraphOutputSocket *> lf_border_link_usages =
this->build_zone_border_link_input_usages(zone, lf_graph);
lf::Node &lf_simulation_usage_node = [&]() -> lf::Node & {
auto &lazy_function = scope_.construct<LazyFunctionForSimulationInputsUsage>(
*zone.output_node);
lf::Node &lf_node = lf_graph.add_function(lazy_function);
for (const int i : lf_zone_main_input_usages.index_range()) {
lf_graph.add_link(lf_node.output(0), *lf_zone_main_input_usages[i]);
for (const int i : zone_info.indices.outputs.input_usages) {
lf_graph.add_link(lf_node.output(0), *lf_zone_outputs[i]);
}
return lf_node;
@ -2253,30 +2269,24 @@ struct GeometryNodesLazyFunctionBuilder {
this->insert_links_from_socket(*item.key, *item.value, graph_params);
}
this->link_border_link_inputs_and_usages(
zone, lf_border_link_inputs, lf_border_link_usages, graph_params);
this->link_border_link_inputs_and_usages(zone,
lf_zone_inputs,
zone_info.indices.inputs.border_links,
lf_zone_outputs,
zone_info.indices.outputs.border_link_usages,
graph_params);
for (const int i : lf_zone_main_inputs.index_range()) {
lf_graph.add_link(*lf_zone_main_inputs[i], lf_simulation_input->input(i));
for (const int i : zone_info.indices.inputs.main) {
lf_graph.add_link(*lf_zone_inputs[i], lf_simulation_input->input(i));
}
for (const int i : lf_zone_main_outputs.index_range()) {
lf_graph.add_link(lf_simulation_output.output(i), *lf_zone_main_outputs[i]);
for (const int i : zone_info.indices.outputs.main.index_range()) {
lf_graph.add_link(lf_simulation_output.output(i),
*lf_zone_outputs[zone_info.indices.outputs.main[i]]);
}
this->add_default_inputs(graph_params);
Vector<const lf::GraphInputSocket *, 16> lf_zone_inputs;
lf_zone_inputs.extend(lf_zone_main_inputs);
zone_info.indices.inputs.main = lf_zone_inputs.index_range();
lf_zone_inputs.extend(lf_border_link_inputs);
zone_info.indices.inputs.border_links = lf_zone_inputs.index_range().take_back(
lf_border_link_inputs.size());
lf_zone_inputs.extend(lf_zone_main_output_usages);
zone_info.indices.inputs.output_usages = lf_zone_inputs.index_range().take_back(
lf_zone_main_output_usages.size());
Map<int, lf::OutputSocket *> lf_attribute_set_by_field_source_index;
Map<int, lf::OutputSocket *> lf_attribute_set_by_caller_propagation_index;
this->build_attribute_set_inputs_for_zone(graph_params,
@ -2304,25 +2314,17 @@ struct GeometryNodesLazyFunctionBuilder {
lf_attribute_set_by_caller_propagation_index);
this->fix_link_cycles(lf_graph, graph_params.socket_usage_inputs);
Vector<const lf::GraphOutputSocket *, 16> lf_zone_outputs;
lf_zone_outputs.extend(lf_zone_main_outputs);
zone_info.indices.outputs.main = lf_zone_outputs.index_range();
lf_zone_outputs.extend(lf_zone_main_input_usages);
zone_info.indices.outputs.input_usages = lf_zone_outputs.index_range().take_back(
lf_zone_main_input_usages.size());
lf_zone_outputs.extend(lf_border_link_usages);
zone_info.indices.outputs.border_link_usages = lf_zone_outputs.index_range().take_back(
lf_border_link_usages.size());
lf_graph.update_node_indices();
auto &logger = scope_.construct<GeometryNodesLazyFunctionLogger>(*lf_graph_info_);
auto &side_effect_provider = scope_.construct<GeometryNodesLazyFunctionSideEffectProvider>();
const auto &lf_graph_fn = scope_.construct<lf::GraphExecutor>(
lf_graph, lf_zone_inputs, lf_zone_outputs, &logger, &side_effect_provider, nullptr);
const auto &lf_graph_fn = scope_.construct<lf::GraphExecutor>(lf_graph,
lf_zone_inputs.as_span(),
lf_zone_outputs.as_span(),
&logger,
&side_effect_provider,
nullptr);
const auto &zone_function = scope_.construct<LazyFunctionForSimulationZone>(*zone.output_node,
lf_graph_fn);
zone_info.lazy_function = &zone_function;
@ -2339,7 +2341,7 @@ struct GeometryNodesLazyFunctionBuilder {
/* Build a function for the loop body. */
ZoneBodyFunction &body_fn = this->build_zone_body_function(zone);
/* Wrap the loop body by another function that implements the repeat behavior. */
auto &zone_fn = scope_.construct<LazyFunctionForRepeatZone>(zone, zone_info, body_fn);
auto &zone_fn = scope_.construct<LazyFunctionForRepeatZone>(btree_, zone, zone_info, body_fn);
zone_info.lazy_function = &zone_fn;
}
@ -2352,32 +2354,26 @@ struct GeometryNodesLazyFunctionBuilder {
BuildGraphParams graph_params{lf_body_graph};
Vector<const lf::GraphInputSocket *, 16> lf_body_inputs;
Vector<const lf::GraphOutputSocket *, 16> lf_body_outputs;
Vector<lf::GraphInputSocket *> lf_body_inputs;
Vector<lf::GraphOutputSocket *> lf_body_outputs;
ZoneBodyFunction &body_fn = scope_.construct<ZoneBodyFunction>();
Vector<lf::GraphInputSocket *> lf_main_inputs;
Vector<lf::GraphOutputSocket *> lf_main_input_usages;
for (const bNodeSocket *bsocket : zone.input_node->output_sockets().drop_back(1)) {
lf::GraphInputSocket &lf_input = lf_body_graph.add_input(
*bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name);
lf::GraphOutputSocket &lf_input_usage = lf_body_graph.add_output(
CPPType::get<bool>(), "Usage: " + StringRef(bsocket->name));
lf_main_inputs.append(&lf_input);
lf_main_input_usages.append(&lf_input_usage);
const int input_index = lf_body_inputs.append_and_get_index(&lf_input);
body_fn.indices.inputs.main.append(input_index);
const int input_usage = lf_body_outputs.append_and_get_index(&lf_input_usage);
body_fn.indices.outputs.input_usages.append(input_usage);
graph_params.lf_output_by_bsocket.add_new(bsocket, &lf_input);
}
lf_body_inputs.extend(lf_main_inputs);
body_fn.indices.inputs.main = lf_body_inputs.index_range().take_back(lf_main_inputs.size());
lf_body_outputs.extend(lf_main_input_usages);
body_fn.indices.outputs.input_usages = lf_body_outputs.index_range().take_back(
lf_main_input_usages.size());
Vector<lf::GraphOutputSocket *> lf_main_outputs;
Vector<lf::GraphInputSocket *> lf_main_output_usages;
this->build_zone_border_links_inputs(
zone, lf_body_graph, lf_body_inputs, body_fn.indices.inputs.border_links);
this->build_zone_border_link_input_usages(
zone, lf_body_graph, lf_body_outputs, body_fn.indices.outputs.border_link_usages);
for (const bNodeSocket *bsocket : zone.output_node->input_sockets().drop_back(1)) {
lf::GraphOutputSocket &lf_output = lf_body_graph.add_output(
@ -2386,36 +2382,20 @@ struct GeometryNodesLazyFunctionBuilder {
CPPType::get<bool>(), "Usage: " + StringRef(bsocket->name));
graph_params.lf_inputs_by_bsocket.add(bsocket, &lf_output);
graph_params.usage_by_bsocket.add(bsocket, &lf_output_usage);
lf_main_outputs.append(&lf_output);
lf_main_output_usages.append(&lf_output_usage);
const int output_index = lf_body_outputs.append_and_get_index(&lf_output);
body_fn.indices.outputs.main.append(output_index);
const int output_usage_index = lf_body_inputs.append_and_get_index(&lf_output_usage);
body_fn.indices.inputs.output_usages.append(output_usage_index);
}
lf_body_outputs.extend(lf_main_outputs);
body_fn.indices.outputs.main = lf_body_outputs.index_range().take_back(lf_main_outputs.size());
lf_body_inputs.extend(lf_main_output_usages);
body_fn.indices.inputs.output_usages = lf_body_inputs.index_range().take_back(
lf_main_output_usages.size());
Vector<lf::GraphInputSocket *> lf_border_link_inputs = this->build_zone_border_links_inputs(
zone, lf_body_graph);
lf_body_inputs.extend(lf_border_link_inputs);
body_fn.indices.inputs.border_links = lf_body_inputs.index_range().take_back(
lf_border_link_inputs.size());
Vector<lf::GraphOutputSocket *> lf_border_link_usages =
this->build_zone_border_link_input_usages(zone, lf_body_graph);
lf_body_outputs.extend(lf_border_link_usages);
body_fn.indices.outputs.border_link_usages = lf_body_outputs.index_range().take_back(
lf_border_link_usages.size());
this->insert_nodes_and_zones(zone.child_nodes, zone.child_zones, graph_params);
this->build_output_socket_usages(*zone.input_node, graph_params);
for (const int i : zone.input_node->output_sockets().drop_back(1).index_range()) {
const bNodeSocket &bsocket = zone.input_node->output_socket(i);
lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(&bsocket, nullptr);
lf::GraphOutputSocket &lf_usage_output = *lf_main_input_usages[i];
lf::GraphOutputSocket &lf_usage_output =
*lf_body_outputs[body_fn.indices.outputs.input_usages[i]];
if (lf_usage) {
lf_body_graph.add_link(*lf_usage, lf_usage_output);
}
@ -2429,8 +2409,12 @@ struct GeometryNodesLazyFunctionBuilder {
this->insert_links_from_socket(*item.key, *item.value, graph_params);
}
this->link_border_link_inputs_and_usages(
zone, lf_border_link_inputs, lf_border_link_usages, graph_params);
this->link_border_link_inputs_and_usages(zone,
lf_body_inputs,
body_fn.indices.inputs.border_links,
lf_body_outputs,
body_fn.indices.outputs.border_link_usages,
graph_params);
this->add_default_inputs(graph_params);
@ -2466,35 +2450,48 @@ struct GeometryNodesLazyFunctionBuilder {
auto &logger = scope_.construct<GeometryNodesLazyFunctionLogger>(*lf_graph_info_);
auto &side_effect_provider = scope_.construct<GeometryNodesLazyFunctionSideEffectProvider>();
body_fn.function = &scope_.construct<lf::GraphExecutor>(
lf_body_graph, lf_body_inputs, lf_body_outputs, &logger, &side_effect_provider, nullptr);
body_fn.function = &scope_.construct<lf::GraphExecutor>(lf_body_graph,
lf_body_inputs.as_span(),
lf_body_outputs.as_span(),
&logger,
&side_effect_provider,
nullptr);
// std::cout << "\n\n" << lf_body_graph.to_dot() << "\n\n";
return body_fn;
}
Vector<lf::GraphInputSocket *> build_zone_border_links_inputs(const bNodeTreeZone &zone,
lf::Graph &lf_graph)
void build_zone_border_links_inputs(const bNodeTreeZone &zone,
lf::Graph &lf_graph,
Vector<lf::GraphInputSocket *> &r_lf_graph_inputs,
Vector<int> &r_indices)
{
Vector<lf::GraphInputSocket *> lf_graph_inputs;
for (const bNodeLink *border_link : zone.border_links) {
lf_graph_inputs.append(
if (bke::nodeIsDanglingReroute(&btree_, border_link->fromnode)) {
continue;
}
const int input_index = r_lf_graph_inputs.append_and_get_index(
&lf_graph.add_input(*border_link->tosock->typeinfo->geometry_nodes_cpp_type,
StringRef("Link from ") + border_link->fromsock->name));
r_indices.append(input_index);
}
return lf_graph_inputs;
}
Vector<lf::GraphOutputSocket *> build_zone_border_link_input_usages(const bNodeTreeZone &zone,
lf::Graph &lf_graph)
void build_zone_border_link_input_usages(const bNodeTreeZone &zone,
lf::Graph &lf_graph,
Vector<lf::GraphOutputSocket *> &r_lf_graph_outputs,
Vector<int> &r_indices)
{
Vector<lf::GraphOutputSocket *> lf_graph_outputs;
for (const bNodeLink *border_link : zone.border_links) {
lf_graph_outputs.append(&lf_graph.add_output(
if (bke::nodeIsDanglingReroute(&btree_, border_link->fromnode)) {
continue;
}
const int input_usage_index = r_lf_graph_outputs.append_and_get_index(&lf_graph.add_output(
CPPType::get<bool>(), StringRef("Usage: Link from ") + border_link->fromsock->name));
r_indices.append(input_usage_index);
}
return lf_graph_outputs;
}
void build_attribute_set_inputs_for_zone(
@ -2878,22 +2875,28 @@ struct GeometryNodesLazyFunctionBuilder {
}
}
void link_border_link_inputs_and_usages(
const bNodeTreeZone &zone,
const Span<lf::GraphInputSocket *> lf_border_link_inputs,
const Span<lf::GraphOutputSocket *> lf_border_link_usages,
BuildGraphParams &graph_params)
void link_border_link_inputs_and_usages(const bNodeTreeZone &zone,
const Span<lf::GraphInputSocket *> lf_inputs,
const Span<int> lf_border_link_input_indices,
const Span<lf::GraphOutputSocket *> lf_usages,
const Span<int> lf_border_link_usage_indices,
BuildGraphParams &graph_params)
{
lf::Graph &lf_graph = graph_params.lf_graph;
int border_link_index = 0;
for (const int border_link_i : zone.border_links.index_range()) {
const bNodeLink &border_link = *zone.border_links[border_link_i];
lf::GraphInputSocket &lf_from = *lf_border_link_inputs[border_link_i];
if (bke::nodeIsDanglingReroute(&btree_, border_link.fromnode)) {
continue;
}
lf::GraphInputSocket &lf_from = *lf_inputs[lf_border_link_input_indices[border_link_index]];
const Vector<lf::InputSocket *> lf_link_targets = this->find_link_targets(border_link,
graph_params);
for (lf::InputSocket *lf_to : lf_link_targets) {
lf_graph.add_link(lf_from, *lf_to);
}
lf::GraphOutputSocket &lf_usage_output = *lf_border_link_usages[border_link_i];
lf::GraphOutputSocket &lf_usage_output =
*lf_usages[lf_border_link_usage_indices[border_link_index]];
if (lf::OutputSocket *lf_usage = graph_params.usage_by_bsocket.lookup_default(
border_link.tosock, nullptr))
{
@ -2903,6 +2906,7 @@ struct GeometryNodesLazyFunctionBuilder {
static const bool static_false = false;
lf_usage_output.set_default_value(&static_false);
}
border_link_index++;
}
}
@ -3005,15 +3009,20 @@ struct GeometryNodesLazyFunctionBuilder {
}
const Span<const bNodeLink *> child_border_links = child_zone.border_links;
int child_border_link_index = 0;
for (const int child_border_link_i : child_border_links.index_range()) {
lf::InputSocket &child_border_link_input = child_zone_node.input(
child_zone_info.indices.inputs.border_links[child_border_link_i]);
const bNodeLink &link = *child_border_links[child_border_link_i];
if (bke::nodeIsDanglingReroute(&btree_, link.fromnode)) {
continue;
}
lf::InputSocket &child_border_link_input = child_zone_node.input(
child_zone_info.indices.inputs.border_links[child_border_link_index]);
graph_params.lf_input_by_border_link.add(&link, &child_border_link_input);
lf::OutputSocket &lf_usage = child_zone_node.output(
child_zone_info.indices.outputs.border_link_usages[child_border_link_i]);
child_zone_info.indices.outputs.border_link_usages[child_border_link_index]);
graph_params.lf_inputs_by_bsocket.add(link.tosock, &child_border_link_input);
graph_params.usage_by_bsocket.add(link.tosock, &lf_usage);
child_border_link_index++;
}
for (const auto item : child_zone_info.indices.inputs.attributes_by_field_source_index.items())
@ -3874,6 +3883,9 @@ struct GeometryNodesLazyFunctionBuilder {
{
for (auto item : graph_params.lf_inputs_by_bsocket.items()) {
const bNodeSocket &bsocket = *item.key;
if (bke::nodeIsDanglingReroute(&btree_, &bsocket.owner_node())) {
continue;
}
const Span<lf::InputSocket *> lf_sockets = item.value;
for (lf::InputSocket *lf_socket : lf_sockets) {
if (lf_socket->origin() != nullptr) {