diff options
author | Jacques Lucke <jacques@blender.org> | 2022-04-07 10:40:37 +0300 |
---|---|---|
committer | Fabian Schempp <fabianschempp@googlemail.com> | 2022-04-11 01:31:59 +0300 |
commit | b0516864a3e4ae06fb824aab7dec76a20f89b88b (patch) | |
tree | aaacd68f5fb09250968d36a9f662425ed0621ac9 /source | |
parent | b2ad149c7481a3a82d4d3d46e0678df0b6daab32 (diff) |
Geometry Nodes: avoid data copy in store named attribute node
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc index 5b0816fa3e3..1d1446ce1bd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc @@ -91,18 +91,34 @@ static void try_capture_field_on_geometry(GeometryComponent &component, const int domain_size = component.attribute_domain_size(domain); const IndexMask mask{IndexMask(domain_size)}; - const CustomDataType data_type = bke::cpp_type_to_custom_data_type(field.cpp_type()); + const CPPType &type = field.cpp_type(); + const CustomDataType data_type = bke::cpp_type_to_custom_data_type(type); + + /* Could avoid allocating a new buffer if: + * - We are writing to an attribute that exists already. + * - The field does not depend on that attribute (we can't easily check for that yet). */ + void *buffer = MEM_mallocN(type.size() * domain_size, __func__); - /* Don't use #add_with_destination because the field might depend on an attribute - * with that name, and changing it as part of evaluation might affect the result. */ fn::FieldEvaluator evaluator{field_context, &mask}; - evaluator.add(field); + evaluator.add_with_destination(field, GMutableSpan{type, buffer, domain_size}); evaluator.evaluate(); - const GVArray &result = evaluator.get_evaluated(0); - OutputAttribute attribute = component.attribute_try_get_for_output_only(name, domain, data_type); - if (attribute) { - result.materialize(attribute.as_span().data()); - attribute.save(); + + component.attribute_try_delete(name); + if (component.attribute_exists(name)) { + WriteAttributeLookup write_attribute = component.attribute_try_get_for_write(name); + if (write_attribute && write_attribute.domain == domain && + write_attribute.varray.type() == type) { + write_attribute.varray.set_all(buffer); + write_attribute.tag_modified_fn(); + } + else { + /* Cannot change type of built-in attribute. */ + } + type.destruct_n(buffer, domain_size); + MEM_freeN(buffer); + } + else { + component.attribute_try_create(name, domain, data_type, AttributeInitMove{buffer}); } } |