From 9b0b30e68dc6958d70e633a45aa16530c1f96756 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 10 May 2023 17:04:58 -0400 Subject: [PATCH 1/2] Cleanup: Reduce binary size by deduplicating attribute processing This makes the Blender binary 350 KB smaller. The largest change comes from using FunctionRef instead of a template when gathering indices to mix in the extrude node (which has no performance cost). The rest of the change comes from consolidating uses of code generation for all attribute types. This brings us a bit further in the direction of unifying attribute propagation. --- .../blender/blenkernel/BKE_attribute_math.hh | 14 ++ .../blenkernel/intern/attribute_math.cc | 18 ++ .../blenkernel/intern/curves_geometry.cc | 10 +- .../geometry/intern/mesh_split_edges.cc | 32 +-- .../geometry/intern/mesh_to_curve_convert.cc | 16 +- .../geometry/nodes/node_geo_curve_sample.cc | 6 +- .../geometry/nodes/node_geo_dual_mesh.cc | 70 +++--- .../nodes/node_geo_duplicate_elements.cc | 152 ++++++------ .../geometry/nodes/node_geo_extrude_mesh.cc | 229 +++++++++--------- 9 files changed, 282 insertions(+), 265 deletions(-) diff --git a/source/blender/blenkernel/BKE_attribute_math.hh b/source/blender/blenkernel/BKE_attribute_math.hh index 8f1e776d517..48c7609e548 100644 --- a/source/blender/blenkernel/BKE_attribute_math.hh +++ b/source/blender/blenkernel/BKE_attribute_math.hh @@ -5,6 +5,8 @@ #include "BLI_array.hh" #include "BLI_color.hh" #include "BLI_cpp_type.hh" +#include "BLI_generic_span.hh" +#include "BLI_generic_virtual_array.hh" #include "BLI_math_color.hh" #include "BLI_math_vector.h" #include "BLI_math_vector.hh" @@ -587,4 +589,16 @@ template using DefaultMixer = typename DefaultMixerStruct::type; /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Generic Array Utils Implementations + * + * Extra implementations of functions from #BLI_array_utils.hh for all attribute types, + * used to avoid templating the same logic for each type in many places. + * \{ */ + +void gather(GSpan src, Span map, GMutableSpan dst); +void gather(const GVArray &src, Span map, GMutableSpan dst); + +/** \} */ + } // namespace blender::bke::attribute_math diff --git a/source/blender/blenkernel/intern/attribute_math.cc b/source/blender/blenkernel/intern/attribute_math.cc index bee05275a15..a95a11b1967 100644 --- a/source/blender/blenkernel/intern/attribute_math.cc +++ b/source/blender/blenkernel/intern/attribute_math.cc @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_array_utils.hh" + #include "BKE_attribute_math.hh" namespace blender::bke::attribute_math { @@ -128,4 +130,20 @@ void ColorGeometry4bMixer::finalize(const IndexMask mask) }); } +void gather(const GSpan src, const Span map, GMutableSpan dst) +{ + attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { + using T = decltype(dummy); + array_utils::gather(src.typed(), map, dst.typed()); + }); +} + +void gather(const GVArray &src, const Span map, GMutableSpan dst) +{ + attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { + using T = decltype(dummy); + array_utils::gather(src.typed(), map, dst.typed()); + }); +} + } // namespace blender::bke::attribute_math diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index 31c09f155ad..8feddfec9a9 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -1124,14 +1124,6 @@ static void copy_construct_data(const GSpan src, GMutableSpan dst) src.type().copy_construct_n(src.data(), dst.data(), src.size()); } -static void copy_with_map(const GSpan src, const Span map, GMutableSpan dst) -{ - attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { - using T = decltype(dummy); - array_utils::gather(src.typed(), map, dst.typed()); - }); -} - static CurvesGeometry copy_with_removed_points( const CurvesGeometry &curves, const IndexMask points_to_delete, @@ -1216,7 +1208,7 @@ static CurvesGeometry copy_with_removed_points( attribute.dst.span.copy_from(attribute.src); } else { - copy_with_map(attribute.src, new_curve_orig_indices, attribute.dst.span); + bke::attribute_math::gather(attribute.src, new_curve_orig_indices, attribute.dst.span); } } }); diff --git a/source/blender/geometry/intern/mesh_split_edges.cc b/source/blender/geometry/intern/mesh_split_edges.cc index 6b573285cf5..9594ce346f2 100644 --- a/source/blender/geometry/intern/mesh_split_edges.cc +++ b/source/blender/geometry/intern/mesh_split_edges.cc @@ -18,14 +18,6 @@ static inline bool naive_edges_equal(const int2 &edge1, const int2 &edge2) return edge1 == edge2; } -template -static void copy_to_new_verts(MutableSpan data, const Span new_to_old_verts_map) -{ - const Span old_data = data.drop_back(new_to_old_verts_map.size()); - MutableSpan new_data = data.take_back(new_to_old_verts_map.size()); - array_utils::gather(old_data, new_to_old_verts_map, new_data); -} - static void add_new_vertices(Mesh &mesh, const Span new_to_old_verts_map) { /* These types aren't supported for interpolation below. */ @@ -46,22 +38,26 @@ static void add_new_vertices(Mesh &mesh, const Span new_to_old_verts_map) continue; } - bke::attribute_math::convert_to_static_type(attribute.span.type(), [&](auto dummy) { - using T = decltype(dummy); - copy_to_new_verts(attribute.span.typed(), new_to_old_verts_map); - }); + bke::attribute_math::gather(attribute.span, + new_to_old_verts_map, + attribute.span.take_back(new_to_old_verts_map.size())); attribute.finish(); } if (float3 *orco = static_cast( CustomData_get_layer_for_write(&mesh.vdata, CD_ORCO, mesh.totvert))) { - copy_to_new_verts({orco, mesh.totvert}, new_to_old_verts_map); + array_utils::gather(Span(orco, mesh.totvert), + new_to_old_verts_map, + MutableSpan(orco, mesh.totvert).take_back(new_to_old_verts_map.size())); } if (int *orig_indices = static_cast( CustomData_get_layer_for_write(&mesh.vdata, CD_ORIGINDEX, mesh.totvert))) { - copy_to_new_verts({orig_indices, mesh.totvert}, new_to_old_verts_map); + array_utils::gather( + Span(orig_indices, mesh.totvert), + new_to_old_verts_map, + MutableSpan(orig_indices, mesh.totvert).take_back(new_to_old_verts_map.size())); } } @@ -119,12 +115,8 @@ static void add_new_edges(Mesh &mesh, const CPPType &type = attribute.varray.type(); void *new_data = MEM_malloc_arrayN(new_edges.size(), type.size(), __func__); - bke::attribute_math::convert_to_static_type(type, [&](auto dummy) { - using T = decltype(dummy); - const VArray src = attribute.varray.typed(); - MutableSpan dst(static_cast(new_data), new_edges.size()); - array_utils::gather(src, new_to_old_edges_map, dst); - }); + bke::attribute_math::gather( + attribute.varray, new_to_old_edges_map, GMutableSpan(type, new_data, new_edges.size())); /* Free the original attribute as soon as possible to lower peak memory usage. */ attributes.remove(local_id); diff --git a/source/blender/geometry/intern/mesh_to_curve_convert.cc b/source/blender/geometry/intern/mesh_to_curve_convert.cc index e35afa06e15..a4445acd89a 100644 --- a/source/blender/geometry/intern/mesh_to_curve_convert.cc +++ b/source/blender/geometry/intern/mesh_to_curve_convert.cc @@ -51,21 +51,19 @@ BLI_NOINLINE bke::CurvesGeometry create_curve_from_vert_indices( continue; } - const GVArray mesh_attribute = *mesh_attributes.lookup(attribute_id, ATTR_DOMAIN_POINT); + const GVArray src = *mesh_attributes.lookup(attribute_id, ATTR_DOMAIN_POINT); /* Some attributes might not exist if they were builtin attribute on domains that don't * have any elements, i.e. a face attribute on the output of the line primitive node. */ - if (!mesh_attribute) { + if (!src) { continue; } + const eCustomDataType type = bke::cpp_type_to_custom_data_type(src.type()); /* Copy attribute based on the map for this curve. */ - bke::attribute_math::convert_to_static_type(mesh_attribute.type(), [&](auto dummy) { - using T = decltype(dummy); - bke::SpanAttributeWriter attribute = - curves_attributes.lookup_or_add_for_write_only_span(attribute_id, ATTR_DOMAIN_POINT); - array_utils::gather(mesh_attribute.typed(), vert_indices, attribute.span); - attribute.finish(); - }); + bke::GSpanAttributeWriter dst = curves_attributes.lookup_or_add_for_write_only_span( + attribute_id, ATTR_DOMAIN_POINT, type); + bke::attribute_math::gather(src, vert_indices, dst.span); + dst.finish(); } return curves; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc index 48423137375..d3435fc1fb5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc @@ -334,10 +334,8 @@ class SampleCurveFunction : public mf::MultiFunction { sampled_normals.fill_indices(mask.indices(), float3(0)); } if (!sampled_values.is_empty()) { - bke::attribute_math::convert_to_static_type(source_data_->type(), [&](auto dummy) { - using T = decltype(dummy); - sampled_values.typed().fill_indices(mask.indices(), {}); - }); + const CPPType &type = sampled_values.type(); + type.fill_assign_indices(type.default_value(), sampled_values.data(), mask); } }; diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc index 06384c95f6e..ccf7521badb 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc @@ -149,52 +149,58 @@ static void transfer_attributes( }); for (const AttributeIDRef &id : attribute_ids) { - GAttributeReader src_attribute = src_attributes.lookup(id); + GAttributeReader src = src_attributes.lookup(id); eAttrDomain out_domain; - if (src_attribute.domain == ATTR_DOMAIN_FACE) { + if (src.domain == ATTR_DOMAIN_FACE) { out_domain = ATTR_DOMAIN_POINT; } - else if (src_attribute.domain == ATTR_DOMAIN_POINT) { + else if (src.domain == ATTR_DOMAIN_POINT) { out_domain = ATTR_DOMAIN_FACE; } else { /* Edges and Face Corners. */ - out_domain = src_attribute.domain; + out_domain = src.domain; } - const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( - src_attribute.varray.type()); - GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( + const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(src.varray.type()); + GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span( id, out_domain, data_type); - if (!dst_attribute) { + if (!dst) { continue; } - bke::attribute_math::convert_to_static_type(data_type, [&](auto dummy) { - using T = decltype(dummy); - VArraySpan span{src_attribute.varray.typed()}; - MutableSpan dst_span = dst_attribute.span.typed(); - switch (src_attribute.domain) { - case ATTR_DOMAIN_POINT: - copy_data_based_on_vertex_types(span, dst_span, vertex_types, keep_boundaries); - break; - case ATTR_DOMAIN_EDGE: - array_utils::gather(span, new_to_old_edges_map, dst_span); - break; - case ATTR_DOMAIN_FACE: - dst_span.take_front(span.size()).copy_from(span); - if (keep_boundaries) { - copy_data_based_on_pairs(span, dst_span, boundary_vertex_to_relevant_face_map); - } - break; - case ATTR_DOMAIN_CORNER: - array_utils::gather(span, new_to_old_face_corners_map, dst_span); - break; - default: - BLI_assert_unreachable(); + switch (src.domain) { + case ATTR_DOMAIN_POINT: { + const GVArraySpan src_span(*src); + bke::attribute_math::convert_to_static_type(data_type, [&](auto dummy) { + using T = decltype(dummy); + copy_data_based_on_vertex_types( + src_span.typed(), dst.span.typed(), vertex_types, keep_boundaries); + }); + break; } - }); - dst_attribute.finish(); + case ATTR_DOMAIN_EDGE: + bke::attribute_math::gather(*src, new_to_old_edges_map, dst.span); + break; + case ATTR_DOMAIN_FACE: { + const GVArraySpan src_span(*src); + dst.span.take_front(src_span.size()).copy_from(src_span); + bke::attribute_math::convert_to_static_type(data_type, [&](auto dummy) { + using T = decltype(dummy); + if (keep_boundaries) { + copy_data_based_on_pairs( + src_span.typed(), dst.span.typed(), boundary_vertex_to_relevant_face_map); + } + }); + break; + } + case ATTR_DOMAIN_CORNER: + bke::attribute_math::gather(*src, new_to_old_face_corners_map, dst.span); + break; + default: + BLI_assert_unreachable(); + } + dst.finish(); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc index ed1e80fa80a..f8f817444ba 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -103,6 +103,17 @@ static void threaded_slice_fill(const OffsetIndices offsets, }); } +static void threaded_slice_fill(const OffsetIndices offsets, + const IndexMask selection, + const GSpan src, + GMutableSpan dst) +{ + bke::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { + using T = decltype(dummy); + threaded_slice_fill(offsets, selection, src.typed(), dst.typed()); + }); +} + static void copy_hashed_ids(const Span src, const int hash, MutableSpan dst) { for (const int i : src.index_range()) { @@ -181,12 +192,7 @@ static void copy_attributes_without_id(const OffsetIndices offsets, for (auto &attribute : bke::retrieve_attributes_for_transfer( src_attributes, dst_attributes, ATTR_DOMAIN_AS_MASK(domain), propagation_info, {"id"})) { - bke::attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { - using T = decltype(dummy); - const Span src = attribute.src.typed(); - MutableSpan dst = attribute.dst.span.typed(); - threaded_slice_fill(offsets, selection, src, dst); - }); + threaded_slice_fill(offsets, selection, attribute.src, attribute.dst.span); attribute.dst.finish(); } } @@ -217,16 +223,15 @@ static void copy_curve_attributes_without_id( propagation_info, {"id"})) { - bke::attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { - using T = decltype(dummy); - const Span src = attribute.src.typed(); - MutableSpan dst = attribute.dst.span.typed(); - - switch (attribute.meta_data.domain) { - case ATTR_DOMAIN_CURVE: - threaded_slice_fill(curve_offsets, selection, src, dst); - break; - case ATTR_DOMAIN_POINT: + switch (attribute.meta_data.domain) { + case ATTR_DOMAIN_CURVE: + threaded_slice_fill(curve_offsets, selection, attribute.src, attribute.dst.span); + break; + case ATTR_DOMAIN_POINT: + bke::attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { + using T = decltype(dummy); + const Span src = attribute.src.typed(); + MutableSpan dst = attribute.dst.span.typed(); threading::parallel_for(selection.index_range(), 512, [&](IndexRange range) { for (const int i_selection : range) { const int i_src_curve = selection[i_selection]; @@ -236,12 +241,12 @@ static void copy_curve_attributes_without_id( } } }); - break; - default: - BLI_assert_unreachable(); - break; - } - }); + }); + break; + default: + BLI_assert_unreachable(); + break; + } attribute.dst.finish(); } } @@ -395,29 +400,23 @@ static void copy_face_attributes_without_id( propagation_info, {"id", ".corner_vert", ".corner_edge", ".edge_verts"})) { - bke::attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { - using T = decltype(dummy); - const Span src = attribute.src.typed(); - MutableSpan dst = attribute.dst.span.typed(); - - switch (attribute.meta_data.domain) { - case ATTR_DOMAIN_POINT: - array_utils::gather(src, vert_mapping, dst); - break; - case ATTR_DOMAIN_EDGE: - array_utils::gather(src, edge_mapping, dst); - break; - case ATTR_DOMAIN_FACE: - threaded_slice_fill(offsets, selection, src, dst); - break; - case ATTR_DOMAIN_CORNER: - array_utils::gather(src, loop_mapping, dst); - break; - default: - BLI_assert_unreachable(); - break; - } - }); + switch (attribute.meta_data.domain) { + case ATTR_DOMAIN_POINT: + bke::attribute_math::gather(attribute.src, vert_mapping, attribute.dst.span); + break; + case ATTR_DOMAIN_EDGE: + bke::attribute_math::gather(attribute.src, edge_mapping, attribute.dst.span); + break; + case ATTR_DOMAIN_FACE: + threaded_slice_fill(offsets, selection, attribute.src, attribute.dst.span); + break; + case ATTR_DOMAIN_CORNER: + bke::attribute_math::gather(attribute.src, loop_mapping, attribute.dst.span); + break; + default: + BLI_assert_unreachable(); + break; + } attribute.dst.finish(); } } @@ -606,23 +605,17 @@ static void copy_edge_attributes_without_id( propagation_info, {"id", ".edge_verts"})) { - bke::attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { - using T = decltype(dummy); - const Span src = attribute.src.typed(); - MutableSpan dst = attribute.dst.span.typed(); - - switch (attribute.meta_data.domain) { - case ATTR_DOMAIN_EDGE: - threaded_slice_fill(offsets, selection, src, dst); - break; - case ATTR_DOMAIN_POINT: - array_utils::gather(src, point_mapping, dst); - break; - default: - BLI_assert_unreachable(); - break; - } - }); + switch (attribute.meta_data.domain) { + case ATTR_DOMAIN_EDGE: + threaded_slice_fill(offsets, selection, attribute.src, attribute.dst.span); + break; + case ATTR_DOMAIN_POINT: + bke::attribute_math::gather(attribute.src, point_mapping, attribute.dst.span); + break; + default: + BLI_assert_unreachable(); + break; + } attribute.dst.finish(); } } @@ -784,10 +777,7 @@ static void duplicate_points_curve(GeometrySet &geometry_set, bke::curves_copy_parameters(src_curves_id, *new_curves_id); bke::CurvesGeometry &new_curves = new_curves_id->geometry.wrap(); MutableSpan new_curve_offsets = new_curves.offsets_for_write(); - for (const int i : new_curves.curves_range()) { - new_curve_offsets[i] = i; - } - new_curve_offsets.last() = dst_num; + std::iota(new_curve_offsets.begin(), new_curve_offsets.end(), 0); for (auto &attribute : bke::retrieve_attributes_for_transfer(src_curves.attributes(), new_curves.attributes_for_write(), @@ -795,27 +785,27 @@ static void duplicate_points_curve(GeometrySet &geometry_set, propagation_info, {"id"})) { - bke::attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { - using T = decltype(dummy); - const Span src = attribute.src.typed(); - MutableSpan dst = attribute.dst.span.typed(); - switch (attribute.meta_data.domain) { - case ATTR_DOMAIN_CURVE: + switch (attribute.meta_data.domain) { + case ATTR_DOMAIN_CURVE: + bke::attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { + using T = decltype(dummy); + const Span src = attribute.src.typed(); + MutableSpan dst = attribute.dst.span.typed(); threading::parallel_for(selection.index_range(), 512, [&](IndexRange range) { for (const int i_selection : range) { const T &src_value = src[point_to_curve_map[selection[i_selection]]]; dst.slice(duplicates[i_selection]).fill(src_value); } }); - break; - case ATTR_DOMAIN_POINT: - threaded_slice_fill(duplicates, selection, src, dst); - break; - default: - BLI_assert_unreachable(); - break; - } - }); + }); + break; + case ATTR_DOMAIN_POINT: + threaded_slice_fill(duplicates, selection, attribute.src, attribute.dst.span); + break; + default: + BLI_assert_unreachable(); + break; + } attribute.dst.finish(); } 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 1f49a0d0d96..63e13e644e1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -199,15 +199,16 @@ static MutableSpan get_orig_index_layer(Mesh &mesh, const eAttrDomain domai * \param get_mix_indices_fn: Returns a Span of indices of the source points to mix for every * result point. */ -template +template void copy_with_mixing(const Span src, - const GetMixIndicesFn &get_mix_indices_fn, + const FunctionRef(int)> get_mix_indices_fn, MutableSpan dst) { threading::parallel_for(dst.index_range(), 512, [&](const IndexRange range) { bke::attribute_math::DefaultPropagationMixer mixer{dst.slice(range)}; for (const int i_dst : IndexRange(range.size())) { - for (const int i_src : get_mix_indices_fn(range[i_dst])) { + const Span indices = get_mix_indices_fn(range[i_dst]); + for (const int i_src : indices) { mixer.mix_in(i_dst, src[i_src]); } } @@ -215,8 +216,9 @@ void copy_with_mixing(const Span src, }); } -template -void copy_with_mixing(const GSpan src, const GetMixIndicesFn &get_mix_indices_fn, GMutableSpan dst) +static void copy_with_mixing(const GSpan src, + const FunctionRef(int)> get_mix_indices_fn, + GMutableSpan dst) { bke::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); @@ -535,41 +537,40 @@ static void extrude_mesh_edges(Mesh &mesh, } GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id); - bke::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { - using T = decltype(dummy); - MutableSpan data = attribute.span.typed(); - switch (attribute.domain) { - case ATTR_DOMAIN_POINT: { - /* New vertices copy the attribute values from their source vertex. */ - array_utils::gather( - data.as_span(), new_vert_indices.as_span(), data.slice(new_vert_range)); - break; - } - case ATTR_DOMAIN_EDGE: { - /* Edges parallel to original edges copy the edge attributes from the original edges. */ - MutableSpan duplicate_data = data.slice(duplicate_edge_range); - array_utils::gather(data.as_span(), edge_selection, duplicate_data); + switch (attribute.domain) { + case ATTR_DOMAIN_POINT: { + /* New vertices copy the attribute values from their source vertex. */ + bke::attribute_math::gather( + attribute.span, new_vert_indices, attribute.span.slice(new_vert_range)); + break; + } + case ATTR_DOMAIN_EDGE: { + /* Edges parallel to original edges copy the edge attributes from the original edges. */ + GMutableSpan duplicate_data = attribute.span.slice(duplicate_edge_range); + array_utils::gather(attribute.span, edge_selection, duplicate_data); - /* Edges connected to original vertices mix values of selected connected edges. */ - copy_with_mixing( - duplicate_data.as_span(), - [&](const int i) { return new_vert_to_duplicate_edge_map[i].as_span(); }, - data.slice(connect_edge_range)); - break; - } - case ATTR_DOMAIN_FACE: { - /* Attribute values for new faces are a mix of the values of faces connected to the its - * original edge. */ - copy_with_mixing( - data.as_span(), - [&](const int i) { return edge_to_poly_map[edge_selection[i]].as_span(); }, - data.slice(new_poly_range)); - - break; - } - case ATTR_DOMAIN_CORNER: { - /* New corners get the average value of all adjacent corners on original faces connected - * to the original edge of their face. */ + /* Edges connected to original vertices mix values of selected connected edges. */ + copy_with_mixing( + duplicate_data, + [&](const int i) { return new_vert_to_duplicate_edge_map[i].as_span(); }, + attribute.span.slice(connect_edge_range)); + break; + } + case ATTR_DOMAIN_FACE: { + /* Attribute values for new faces are a mix of the values of faces connected to the its + * original edge. */ + copy_with_mixing( + attribute.span, + [&](const int i) { return edge_to_poly_map[edge_selection[i]].as_span(); }, + attribute.span.slice(new_poly_range)); + break; + } + case ATTR_DOMAIN_CORNER: { + /* New corners get the average value of all adjacent corners on original faces connected + * to the original edge of their face. */ + bke::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { + using T = decltype(dummy); + MutableSpan data = attribute.span.typed(); MutableSpan new_data = data.slice(new_loop_range); threading::parallel_for(edge_selection.index_range(), 256, [&](const IndexRange range) { for (const int i_edge_selection : range) { @@ -623,12 +624,12 @@ static void extrude_mesh_edges(Mesh &mesh, } } }); - break; - } - default: - BLI_assert_unreachable(); + }); + break; } - }); + default: + BLI_assert_unreachable(); + } attribute.finish(); return true; @@ -935,41 +936,41 @@ static void extrude_mesh_face_regions(Mesh &mesh, } GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id); - bke::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { - using T = decltype(dummy); - MutableSpan data = attribute.span.typed(); - switch (attribute.domain) { - case ATTR_DOMAIN_POINT: { - /* New vertices copy the attributes from their original vertices. */ - array_utils::gather( - data.as_span(), new_vert_indices.as_span(), data.slice(new_vert_range)); - break; - } - case ATTR_DOMAIN_EDGE: { - /* Edges parallel to original edges copy the edge attributes from the original edges. */ - MutableSpan boundary_data = data.slice(boundary_edge_range); - array_utils::gather(data.as_span(), boundary_edge_indices.as_span(), boundary_data); + switch (attribute.domain) { + case ATTR_DOMAIN_POINT: { + /* New vertices copy the attributes from their original vertices. */ + bke::attribute_math::gather( + attribute.span, new_vert_indices, attribute.span.slice(new_vert_range)); + break; + } + case ATTR_DOMAIN_EDGE: { + /* Edges parallel to original edges copy the edge attributes from the original edges. */ + GMutableSpan boundary_data = attribute.span.slice(boundary_edge_range); + bke::attribute_math::gather(attribute.span, boundary_edge_indices, boundary_data); - /* Edges inside of face regions also just duplicate their source data. */ - MutableSpan new_inner_data = data.slice(new_inner_edge_range); - array_utils::gather(data.as_span(), new_inner_edge_indices.as_span(), new_inner_data); + /* Edges inside of face regions also just duplicate their source data. */ + GMutableSpan new_inner_data = attribute.span.slice(new_inner_edge_range); + bke::attribute_math::gather(attribute.span, new_inner_edge_indices, new_inner_data); - /* Edges connected to original vertices mix values of selected connected edges. */ - copy_with_mixing( - boundary_data.as_span(), - [&](const int i) { return new_vert_to_duplicate_edge_map[i].as_span(); }, - data.slice(connect_edge_range)); - break; - } - case ATTR_DOMAIN_FACE: { - /* New faces on the side of extrusions get the values from the corresponding selected - * face. */ - array_utils::gather( - data.as_span(), edge_extruded_face_indices.as_span(), data.slice(side_poly_range)); - break; - } - case ATTR_DOMAIN_CORNER: { - /* New corners get the values from the corresponding corner on the extruded face. */ + /* Edges connected to original vertices mix values of selected connected edges. */ + copy_with_mixing( + boundary_data, + [&](const int i) { return new_vert_to_duplicate_edge_map[i].as_span(); }, + attribute.span.slice(connect_edge_range)); + break; + } + case ATTR_DOMAIN_FACE: { + /* New faces on the side of extrusions get the values from the corresponding selected + * face. */ + GMutableSpan side_data = attribute.span.slice(side_poly_range); + bke::attribute_math::gather(attribute.span, edge_extruded_face_indices, side_data); + break; + } + case ATTR_DOMAIN_CORNER: { + /* New corners get the values from the corresponding corner on the extruded face. */ + bke::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { + using T = decltype(dummy); + MutableSpan data = attribute.span.typed(); MutableSpan new_data = data.slice(side_loop_range); threading::parallel_for( boundary_edge_indices.index_range(), 256, [&](const IndexRange range) { @@ -1009,12 +1010,12 @@ static void extrude_mesh_face_regions(Mesh &mesh, } } }); - break; - } - default: - BLI_assert_unreachable(); + }); + break; } - }); + default: + BLI_assert_unreachable(); + } attribute.finish(); return true; @@ -1234,21 +1235,21 @@ static void extrude_individual_mesh_faces( } GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id); - bke::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { - using T = decltype(dummy); - MutableSpan data = attribute.span.typed(); - switch (attribute.domain) { - case ATTR_DOMAIN_POINT: { - /* New vertices copy the attributes from their original vertices. */ - MutableSpan new_data = data.slice(new_vert_range); - array_utils::gather(data.as_span(), new_vert_indices.as_span(), new_data); - break; - } - case ATTR_DOMAIN_EDGE: { - /* The data for the duplicate edge is simply a copy of the original edge's data. */ - MutableSpan duplicate_data = data.slice(duplicate_edge_range); - array_utils::gather(data.as_span(), duplicate_edge_indices.as_span(), duplicate_data); + switch (attribute.domain) { + case ATTR_DOMAIN_POINT: { + /* New vertices copy the attributes from their original vertices. */ + GMutableSpan new_data = attribute.span.slice(new_vert_range); + bke::attribute_math::gather(attribute.span, new_vert_indices, new_data); + break; + } + case ATTR_DOMAIN_EDGE: { + /* The data for the duplicate edge is simply a copy of the original edge's data. */ + GMutableSpan duplicate_data = attribute.span.slice(duplicate_edge_range); + bke::attribute_math::gather(attribute.span, duplicate_edge_indices, duplicate_data); + bke::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { + using T = decltype(dummy); + MutableSpan data = attribute.span.typed(); MutableSpan connect_data = data.slice(connect_edge_range); threading::parallel_for(poly_selection.index_range(), 512, [&](const IndexRange range) { for (const int i_selection : range) { @@ -1275,10 +1276,14 @@ static void extrude_individual_mesh_faces( } } }); - break; - } - case ATTR_DOMAIN_FACE: { - /* Each side face gets the values from the corresponding new face. */ + }); + break; + } + case ATTR_DOMAIN_FACE: { + /* Each side face gets the values from the corresponding new face. */ + bke::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { + using T = decltype(dummy); + MutableSpan data = attribute.span.typed(); MutableSpan new_data = data.slice(side_poly_range); threading::parallel_for(poly_selection.index_range(), 1024, [&](const IndexRange range) { for (const int i_selection : range) { @@ -1287,11 +1292,15 @@ static void extrude_individual_mesh_faces( new_data.slice(extrude_range).fill(data[poly_index]); } }); - break; - } - case ATTR_DOMAIN_CORNER: { - /* Each corner on a side face gets its value from the matching corner on an extruded - * face. */ + }); + break; + } + case ATTR_DOMAIN_CORNER: { + /* Each corner on a side face gets its value from the matching corner on an extruded + * face. */ + bke::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { + using T = decltype(dummy); + MutableSpan data = attribute.span.typed(); MutableSpan new_data = data.slice(side_loop_range); threading::parallel_for(poly_selection.index_range(), 256, [&](const IndexRange range) { for (const int i_selection : range) { @@ -1315,12 +1324,12 @@ static void extrude_individual_mesh_faces( } } }); - break; - } - default: - BLI_assert_unreachable(); + }); + break; } - }); + default: + BLI_assert_unreachable(); + } attribute.finish(); return true; -- 2.30.2 From 0b194073158fe221a5ed1899718acecf52f59276 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 12 May 2023 08:42:48 -0400 Subject: [PATCH 2/2] Correct array initialization --- source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc index d3435fc1fb5..a4d5b7bfd79 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc @@ -335,7 +335,7 @@ class SampleCurveFunction : public mf::MultiFunction { } if (!sampled_values.is_empty()) { const CPPType &type = sampled_values.type(); - type.fill_assign_indices(type.default_value(), sampled_values.data(), mask); + type.fill_construct_indices(type.default_value(), sampled_values.data(), mask); } }; -- 2.30.2