Fix: Geometry Nodes: wrong anonymous attribute lifetimes with fields in geometry bundles

This fixes missing anonymous attributes when a reference to them is
stored in a geometry bundle.

A regression test that checks for this has been added (it breaks without
this change).

Pull Request: https://projects.blender.org/blender/blender/pulls/159149
This commit is contained in:
Jacques Lucke 2026-05-27 15:12:28 +02:00
parent 3a7652f7fa
commit 4d3ce6cf62
5 changed files with 21 additions and 9 deletions

View file

@ -1495,7 +1495,7 @@ template<typename T>
return false;
}
const std::optional<std::string> key_str = io_item->lookup_str("key");
if (key_str) {
if (!key_str) {
return false;
}
const std::optional<StringRefNull> socket_idname = io_item->lookup_str("socket_idname");

View file

@ -56,7 +56,7 @@ std::ostream &operator<<(std::ostream &stream, const ReferenceSetInfo &info)
static bool socket_may_have_reference(const bNodeSocket &socket)
{
return socket.may_be_field() || ELEM(socket.type, SOCK_BUNDLE, SOCK_CLOSURE);
return socket.may_be_field() || ELEM(socket.type, SOCK_BUNDLE, SOCK_CLOSURE, SOCK_GEOMETRY);
}
static bool or_into_each_other_masked(MutableBoundedBitSpan a,
@ -84,7 +84,7 @@ static bool or_into_each_other(MutableBoundedBitSpan a, MutableBoundedBitSpan b)
bool can_contain_reference(const eNodeSocketDatatype socket_type)
{
return nodes::socket_type_supports_fields(socket_type) ||
ELEM(socket_type, SOCK_BUNDLE, SOCK_CLOSURE);
ELEM(socket_type, SOCK_GEOMETRY, SOCK_BUNDLE, SOCK_CLOSURE);
}
bool can_contain_referenced_data(const eNodeSocketDatatype socket_type)

View file

@ -15,6 +15,7 @@
#include "BKE_node.hh"
#include "BKE_node_runtime.hh"
#include "BKE_node_socket_value.hh"
#include "BKE_node_tree_reference_lifetimes.hh"
#include "RNA_access.hh"
@ -39,19 +40,17 @@ void build_node_declaration(const bke::bNodeType &typeinfo,
void NodeDeclarationBuilder::build_remaining_anonymous_attribute_relations()
{
auto is_data_socket_decl = [](const SocketDeclaration *socket_decl) {
return ELEM(socket_decl->socket_type, SOCK_GEOMETRY, SOCK_BUNDLE, SOCK_CLOSURE);
};
using bke::node_tree_reference_lifetimes::can_contain_referenced_data;
Vector<int> data_inputs;
for (const int i : declaration_.inputs.index_range()) {
if (is_data_socket_decl(declaration_.inputs[i])) {
if (can_contain_referenced_data(declaration_.inputs[i]->socket_type)) {
data_inputs.append(i);
}
}
Vector<int> data_outputs;
for (const int i : declaration_.outputs.index_range()) {
if (is_data_socket_decl(declaration_.outputs[i])) {
if (can_contain_referenced_data(declaration_.outputs[i]->socket_type)) {
data_outputs.append(i);
}
}
@ -79,7 +78,7 @@ void NodeDeclarationBuilder::build_remaining_anonymous_attribute_relations()
for (const int input_i : declaration_.inputs.index_range()) {
SocketDeclaration &input_socket_decl = *declaration_.inputs[input_i];
if (ELEM(input_socket_decl.structure_type, StructureType::Field, StructureType::Dynamic) ||
ELEM(input_socket_decl.socket_type, SOCK_BUNDLE, SOCK_CLOSURE))
ELEM(input_socket_decl.socket_type, SOCK_GEOMETRY, SOCK_BUNDLE, SOCK_CLOSURE))
{
relations.reference_propagations.append({input_i, reference_output});
}
@ -90,6 +89,7 @@ void NodeDeclarationBuilder::build_remaining_anonymous_attribute_relations()
const int data_output = socket_builder->decl_base_->index;
for (const int data_input : data_inputs) {
relations.data_propagations.append({data_input, data_output});
relations.reference_propagations.append({data_input, data_output});
}
}
if (socket_builder->propagate_all_input_data_from_geometry_) {
@ -98,6 +98,7 @@ void NodeDeclarationBuilder::build_remaining_anonymous_attribute_relations()
for (const int i : declaration_.inputs.index_range()) {
if (declaration_.inputs[i]->socket_type == SOCK_GEOMETRY) {
relations.data_propagations.append({i, data_output});
relations.reference_propagations.append({i, data_output});
}
}
}

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4a78a41be706f2656360a3a713d201c3c5b8f61c97895668333d10d51d1a6f11
size 101412

View file

@ -5,10 +5,18 @@
import os
import sys
import bpy
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
from modules.mesh_test import BlendFileTest
if "bake_anonymous_attribute_reference" in bpy.data.filepath:
if bpy.app.version_cycle == "alpha":
bpy.context.preferences.experimental.use_geometry_bundle = True
else:
print("Skipped because bundles and closures are still experimental.")
sys.exit(0)
geo_node_test = BlendFileTest("test_object", "expected_object", threshold=1e-4)
result = geo_node_test.run_test()