Fix #132408: crash when outputting anonymous attribute from foreach zone

The issue was that the propagation of referenced anonymous attributes treated
geometry outputs of the foreach zone as "normal". That means that every
anonymous attributes referenced by the input socket would also be referenced by
the output socket.

However, just like in the repeat zone, this so called "propagate relation" needs
some special behavior, because anonymous attributes references created inside a
zone have to remain inside that zone. Instead, the output node creates a new
anonymous attribute reference that is used outside of the zone.

Pull Request: https://projects.blender.org/blender/blender/pulls/132560
This commit is contained in:
Jacques Lucke
2025-01-03 18:42:09 +01:00
parent b79af08ade
commit e948279818
2 changed files with 20 additions and 6 deletions

View File

@@ -414,6 +414,8 @@ static bool pass_left_to_right(const bNodeTree &tree,
}
const bNode *input_node = zone->input_node;
const bNode *output_node = node;
const auto *storage = static_cast<const NodeGeometryForeachGeometryElementOutput *>(
node->storage);
const int src_index = input_node->input_socket(0).index_in_tree();
for (const bNodeSocket *output_socket : output_node->output_sockets()) {
if (output_socket->type == SOCK_GEOMETRY) {
@@ -421,6 +423,24 @@ static bool pass_left_to_right(const bNodeTree &tree,
r_potential_data_by_socket[dst_index] |= r_potential_data_by_socket[src_index];
}
}
/* Propagate references from the inside to the outside. Like in the repeat zone, new
* references created in the zone stay local inside the zone and are not propagated to the
* outside. Instead, the foreach-element output node creates new references. */
const BitVector<> outside_references = get_references_coming_from_outside_zone(
*zone, r_potential_data_by_socket, r_potential_reference_by_socket);
for (const int item_i : IndexRange(storage->generation_items.items_num)) {
const int src_index =
node->input_socket(storage->main_items.items_num + item_i).index_in_tree();
const int dst_index =
node->output_socket(1 + storage->main_items.items_num + item_i).index_in_tree();
bits::inplace_or_masked(r_potential_data_by_socket[dst_index],
outside_references,
r_potential_data_by_socket[src_index]);
bits::inplace_or_masked(r_potential_reference_by_socket[dst_index],
outside_references,
r_potential_reference_by_socket[src_index]);
}
break;
}
case GEO_NODE_REPEAT_OUTPUT: {

View File

@@ -236,8 +236,6 @@ static void node_declare(NodeDeclarationBuilder &b)
"The original input geometry with potentially new attributes that are output by the "
"zone");
aal::RelationsInNode &relations = b.get_anonymous_attribute_relations();
const bNode *node = b.node_or_null();
const bNodeTree *tree = b.tree_or_null();
if (node && tree) {
@@ -284,10 +282,6 @@ static void node_declare(NodeDeclarationBuilder &b)
if (socket_type == SOCK_GEOMETRY) {
previous_input_geometry_index = input_decl.index();
previous_output_geometry_index = output_decl.index();
aal::PropagateRelation relation;
relation.from_geometry_input = input_decl.index();
relation.to_geometry_output = output_decl.index();
relations.propagate_relations.append(relation);
input_decl.description(
"Geometry generated in the current iteration. Will be joined with geometries from all "