From 9ee45646b432b7d9b9c4f9b2f6aa853dd8785586 Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Tue, 12 Mar 2024 16:42:16 +0100 Subject: [PATCH] Fix #119239: Use attribute names after free Fix of error introduced in c31718649dba9308cbd2. Attribute names will be freed on domain resizing. This mean, ref-names which is attribute ids is will be invalid. To avoid this, make sure names will be gathered only after resize. To avoid unnecessary topology map computation before mesh resize, check if attributes on required domain exists, instead of gathering them and check if span is not empty. Pull Request: https://projects.blender.org/blender/blender/pulls/119242 --- .../geometry/nodes/node_geo_extrude_mesh.cc | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index 9bf4c850484..b26585be511 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -284,6 +284,27 @@ static IDsByDomain attribute_ids_by_domain(const AttributeAccessor attributes, return ids_by_domain; } +static bool is_empty_domain(const AttributeAccessor attributes, + const Set &skip, + const AttrDomain domain) +{ + bool is_empty = true; + attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { + if (meta_data.data_type == CD_PROP_STRING) { + return true; + } + if (meta_data.domain != domain) { + return true; + } + if (skip.contains(id.name())) { + return true; + } + is_empty = false; + return false; + }); + return is_empty; +} + static void gather_attributes(MutableAttributeAccessor attributes, const Span ids, const Span indices, @@ -593,9 +614,6 @@ static void extrude_mesh_edges(Mesh &mesh, MutableAttributeAccessor attributes = mesh.attributes_for_write(); remove_non_propagated_attributes(attributes, propagation_info); - const IDsByDomain ids_by_domain = attribute_ids_by_domain( - attributes, {"position", ".edge_verts", ".corner_vert", ".corner_edge"}); - Array edge_to_face_offsets; Array edge_to_face_indices; const GroupedSpan edge_to_face_map = bke::mesh::build_edge_to_face_map( @@ -604,7 +622,7 @@ static void extrude_mesh_edges(Mesh &mesh, Array vert_to_edge_offsets; Array vert_to_edge_indices; GroupedSpan vert_to_selected_edge_map; - if (!ids_by_domain[int(AttrDomain::Edge)].is_empty()) { + if (!is_empty_domain(attributes, {".edge_verts"}, AttrDomain::Edge)) { vert_to_selected_edge_map = build_vert_to_edge_map( orig_edges, edge_selection, orig_vert_size, vert_to_edge_offsets, vert_to_edge_indices); } @@ -619,6 +637,9 @@ static void extrude_mesh_edges(Mesh &mesh, new_face_range.size(), new_loop_range.size()); + const IDsByDomain ids_by_domain = attribute_ids_by_domain( + attributes, {"position", ".edge_verts", ".corner_vert", ".corner_edge"}); + MutableSpan edges = mesh.edges_for_write(); MutableSpan connect_edges = edges.slice(connect_edge_range); MutableSpan duplicate_edges = edges.slice(duplicate_edge_range); @@ -948,9 +969,6 @@ static void extrude_mesh_face_regions(Mesh &mesh, MutableAttributeAccessor attributes = mesh.attributes_for_write(); remove_non_propagated_attributes(attributes, propagation_info); - const IDsByDomain ids_by_domain = attribute_ids_by_domain( - attributes, {".corner_vert", ".corner_edge", ".edge_verts"}); - remove_unsupported_vert_data(mesh); remove_unsupported_edge_data(mesh); remove_unsupported_face_data(mesh); @@ -961,6 +979,9 @@ static void extrude_mesh_face_regions(Mesh &mesh, side_face_range.size(), side_loop_range.size()); + const IDsByDomain ids_by_domain = attribute_ids_by_domain( + attributes, {".corner_vert", ".corner_edge", ".edge_verts"}); + MutableSpan edges = mesh.edges_for_write(); MutableSpan connect_edges = edges.slice(connect_edge_range); MutableSpan boundary_edges = edges.slice(boundary_edge_range); @@ -1244,9 +1265,6 @@ static void extrude_individual_mesh_faces( MutableAttributeAccessor attributes = mesh.attributes_for_write(); remove_non_propagated_attributes(attributes, propagation_info); - const IDsByDomain ids_by_domain = attribute_ids_by_domain( - attributes, {"position", ".edge_verts", ".corner_vert", ".corner_edge"}); - remove_unsupported_vert_data(mesh); remove_unsupported_edge_data(mesh); remove_unsupported_face_data(mesh); @@ -1257,6 +1275,9 @@ static void extrude_individual_mesh_faces( side_face_range.size(), side_loop_range.size()); + const IDsByDomain ids_by_domain = attribute_ids_by_domain( + attributes, {"position", ".edge_verts", ".corner_vert", ".corner_edge"}); + MutableSpan positions = mesh.vert_positions_for_write(); MutableSpan new_positions = positions.slice(new_vert_range); MutableSpan edges = mesh.edges_for_write();