diff --git a/source/blender/blenkernel/intern/mesh_mapping.cc b/source/blender/blenkernel/intern/mesh_mapping.cc index b74687dbf6a..60f603ea93a 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.cc +++ b/source/blender/blenkernel/intern/mesh_mapping.cc @@ -301,10 +301,7 @@ namespace blender::bke::mesh { static Array create_reverse_offsets(const Span indices, const int items_num) { Array offsets(items_num + 1, 0); - for (const int i : indices) { - offsets[i]++; - } - offset_indices::accumulate_counts_to_offsets(offsets); + offset_indices::build_reverse_offsets(indices, offsets); return offsets; } diff --git a/source/blender/blenlib/BLI_array_utils.hh b/source/blender/blenlib/BLI_array_utils.hh index 072d0cedb99..68c6a0a9382 100644 --- a/source/blender/blenlib/BLI_array_utils.hh +++ b/source/blender/blenlib/BLI_array_utils.hh @@ -145,6 +145,16 @@ inline void gather(const VArray &src, }); } +/** + * Count the number of occurences of each index. + * \param indices: The indices to count. + * \param counts: The number of occurrences of each index. Typically initialized to zero. + * Must be large enough to contain the maximum index. + * + * \note The memory referenced by the two spans must not overlap. + */ +void count_indices(Span indices, MutableSpan counts); + void invert_booleans(MutableSpan span); enum class BooleanMix { diff --git a/source/blender/blenlib/intern/array_utils.cc b/source/blender/blenlib/intern/array_utils.cc index 912443383e0..8bf98fb070a 100644 --- a/source/blender/blenlib/intern/array_utils.cc +++ b/source/blender/blenlib/intern/array_utils.cc @@ -4,6 +4,8 @@ #include "BLI_array_utils.hh" +#include "atomic_ops.h" + namespace blender::array_utils { void copy(const GVArray &src, GMutableSpan dst, const int64_t grain_size) @@ -45,6 +47,13 @@ void gather(const GSpan src, const IndexMask &indices, GMutableSpan dst, const i gather(GVArray::ForSpan(src), indices, dst, grain_size); } +void count_indices(const Span indices, MutableSpan counts) +{ + for (const int i : indices) { + counts[i]++; + } +} + void invert_booleans(MutableSpan span) { threading::parallel_for(span.index_range(), 4096, [&](IndexRange range) { diff --git a/source/blender/blenlib/intern/offset_indices.cc b/source/blender/blenlib/intern/offset_indices.cc index 5a7d4ae3476..546281f455e 100644 --- a/source/blender/blenlib/intern/offset_indices.cc +++ b/source/blender/blenlib/intern/offset_indices.cc @@ -2,6 +2,7 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_array_utils.hh" #include "BLI_offset_indices.hh" #include "BLI_task.hh" @@ -63,9 +64,7 @@ void build_reverse_map(OffsetIndices offsets, MutableSpan r_map) void build_reverse_offsets(const Span indices, MutableSpan offsets) { BLI_assert(std::all_of(offsets.begin(), offsets.end(), [](int value) { return value == 0; })); - for (const int i : indices) { - offsets[i]++; - } + array_utils::count_indices(indices, offsets); offset_indices::accumulate_counts_to_offsets(offsets); } diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index fc2363324b1..cf774367791 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -1133,20 +1133,13 @@ static void build_vertex_face_adjacency_maps(DRWSubdivCache *cache) cache->subdiv_vertex_face_adjacency_offsets = gpu_vertbuf_create_from_format( get_origindex_format(), cache->num_subdiv_verts + 1); - int *vertex_offsets = (int *)GPU_vertbuf_get_data(cache->subdiv_vertex_face_adjacency_offsets); - memset(vertex_offsets, 0, sizeof(int) * cache->num_subdiv_verts + 1); + blender::MutableSpan vertex_offsets( + static_cast(GPU_vertbuf_get_data(cache->subdiv_vertex_face_adjacency_offsets)), + cache->num_subdiv_verts + 1); + vertex_offsets.fill(0); - for (int i = 0; i < cache->num_subdiv_loops; i++) { - vertex_offsets[cache->subdiv_loop_subdiv_vert_index[i]]++; - } - - int ofs = vertex_offsets[0]; - vertex_offsets[0] = 0; - for (uint i = 1; i < cache->num_subdiv_verts + 1; i++) { - int tmp = vertex_offsets[i]; - vertex_offsets[i] = ofs; - ofs += tmp; - } + blender::offset_indices::build_reverse_offsets( + {cache->subdiv_loop_subdiv_vert_index, cache->num_subdiv_loops}, vertex_offsets); cache->subdiv_vertex_face_adjacency = gpu_vertbuf_create_from_format(get_origindex_format(), cache->num_subdiv_loops); diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index 75efbb79772..1bf4a91e436 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -13,6 +13,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_array_utils.hh" #include "BLI_blenlib.h" #include "BLI_dial_2d.h" #include "BLI_ghash.h" @@ -6158,20 +6159,12 @@ void SCULPT_boundary_info_ensure(Object *object) } Mesh *base_mesh = BKE_mesh_from_object(object); - const blender::Span edges = base_mesh->edges(); - const OffsetIndices polys = base_mesh->polys(); - const Span corner_edges = base_mesh->corner_edges(); ss->vertex_info.boundary = BLI_BITMAP_NEW(base_mesh->totvert, "Boundary info"); - int *adjacent_faces_edge_count = static_cast( - MEM_calloc_arrayN(base_mesh->totedge, sizeof(int), "Adjacent face edge count")); - - for (const int i : polys.index_range()) { - for (const int edge : corner_edges.slice(polys[i])) { - adjacent_faces_edge_count[edge]++; - } - } + Array adjacent_faces_edge_count(base_mesh->totedge, 0); + array_utils::count_indices(base_mesh->corner_edges(), adjacent_faces_edge_count); + const blender::Span edges = base_mesh->edges(); for (const int e : edges.index_range()) { if (adjacent_faces_edge_count[e] < 2) { const int2 &edge = edges[e]; @@ -6179,8 +6172,6 @@ void SCULPT_boundary_info_ensure(Object *object) BLI_BITMAP_SET(ss->vertex_info.boundary, edge[1], true); } } - - MEM_freeN(adjacent_faces_edge_count); } void SCULPT_fake_neighbors_ensure(Sculpt *sd, Object *ob, const float max_dist) diff --git a/source/blender/geometry/intern/mesh_to_curve_convert.cc b/source/blender/geometry/intern/mesh_to_curve_convert.cc index 1b508a14645..a7fd29a6eb7 100644 --- a/source/blender/geometry/intern/mesh_to_curve_convert.cc +++ b/source/blender/geometry/intern/mesh_to_curve_convert.cc @@ -115,10 +115,7 @@ BLI_NOINLINE static CurveFromEdgesOutput edges_to_curve_point_indices(const int { /* Compute the number of edges connecting to each vertex. */ Array neighbor_offsets_data(verts_num + 1, 0); - for (const int vert : edges.cast()) { - neighbor_offsets_data[vert]++; - } - offset_indices::accumulate_counts_to_offsets(neighbor_offsets_data); + offset_indices::build_reverse_offsets(edges.cast(), neighbor_offsets_data); const OffsetIndices neighbor_offsets(neighbor_offsets_data); /* Use as an index into the "neighbor group" for each vertex. */ diff --git a/source/blender/modifiers/intern/MOD_skin.cc b/source/blender/modifiers/intern/MOD_skin.cc index caec2f193ea..ca1fad51dad 100644 --- a/source/blender/modifiers/intern/MOD_skin.cc +++ b/source/blender/modifiers/intern/MOD_skin.cc @@ -42,6 +42,7 @@ #include "BLI_utildefines.h" +#include "BLI_array_utils.hh" #include "BLI_bitmap.h" #include "BLI_heap_simple.h" #include "BLI_math.h" @@ -911,10 +912,7 @@ static Mesh *subdivide_base(const Mesh *orig) /* Get degree of all vertices */ blender::Array degree(orig_vert_num, 0); - for (i = 0; i < orig_edge_num; i++) { - degree[orig_edges[i][0]]++; - degree[orig_edges[i][1]]++; - } + blender::array_utils::count_indices(orig_edges.cast(), degree); /* Per edge, store how many subdivisions are needed */ blender::Array edge_subd(orig_edge_num, 0); diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc index deac45754c1..2cb38b266f1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc @@ -2,8 +2,7 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" +#include "BLI_array_utils.hh" #include "BKE_mesh.hh" @@ -30,14 +29,10 @@ class EdgeNeighborCountFieldInput final : public bke::MeshFieldInput { const eAttrDomain domain, const IndexMask & /*mask*/) const final { - const Span corner_edges = mesh.corner_edges(); - Array face_count(mesh.totedge, 0); - for (const int edge : corner_edges) { - face_count[edge]++; - } - + Array counts(mesh.totedge, 0); + array_utils::count_indices(mesh.corner_edges(), counts); return mesh.attributes().adapt_domain( - VArray::ForContainer(std::move(face_count)), ATTR_DOMAIN_EDGE, domain); + VArray::ForContainer(std::move(counts)), ATTR_DOMAIN_EDGE, domain); } uint64_t hash() const override diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc index a8a707c8739..93e9efb3501 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc @@ -2,8 +2,7 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" +#include "BLI_array_utils.hh" #include "BKE_mesh.hh" @@ -27,9 +26,7 @@ static VArray construct_neighbor_count_varray(const Mesh &mesh, const eAttr const Span corner_edges = mesh.corner_edges(); Array edge_count(mesh.totedge, 0); - for (const int edge : corner_edges) { - edge_count[edge]++; - } + array_utils::count_indices(corner_edges, edge_count); Array poly_count(polys.size(), 0); for (const int poly_index : polys.index_range()) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_vertex_neighbors.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_vertex_neighbors.cc index 5fad8cd6dcd..24ebaaecc22 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_vertex_neighbors.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_vertex_neighbors.cc @@ -2,8 +2,7 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" +#include "BLI_array_utils.hh" #include "BKE_mesh.hh" @@ -23,20 +22,6 @@ static void node_declare(NodeDeclarationBuilder &b) .description("Number of faces that contain the vertex"); } -static VArray construct_vertex_count_gvarray(const Mesh &mesh, const eAttrDomain domain) -{ - const Span edges = mesh.edges(); - if (domain == ATTR_DOMAIN_POINT) { - Array counts(mesh.totvert, 0); - for (const int i : edges.index_range()) { - counts[edges[i][0]]++; - counts[edges[i][1]]++; - } - return VArray::ForContainer(std::move(counts)); - } - return {}; -} - class VertexCountFieldInput final : public bke::MeshFieldInput { public: VertexCountFieldInput() : bke::MeshFieldInput(CPPType::get(), "Vertex Count Field") @@ -48,7 +33,12 @@ class VertexCountFieldInput final : public bke::MeshFieldInput { const eAttrDomain domain, const IndexMask & /*mask*/) const final { - return construct_vertex_count_gvarray(mesh, domain); + if (domain != ATTR_DOMAIN_POINT) { + return {}; + } + Array counts(mesh.totvert, 0); + array_utils::count_indices(mesh.edges().cast(), counts); + return VArray::ForContainer(std::move(counts)); } uint64_t hash() const override @@ -68,19 +58,6 @@ class VertexCountFieldInput final : public bke::MeshFieldInput { } }; -static VArray construct_face_count_gvarray(const Mesh &mesh, const eAttrDomain domain) -{ - const Span corner_verts = mesh.corner_verts(); - if (domain == ATTR_DOMAIN_POINT) { - Array vertices(mesh.totvert, 0); - for (const int vert : corner_verts) { - vertices[vert]++; - } - return VArray::ForContainer(std::move(vertices)); - } - return {}; -} - class VertexFaceCountFieldInput final : public bke::MeshFieldInput { public: VertexFaceCountFieldInput() : bke::MeshFieldInput(CPPType::get(), "Vertex Face Count Field") @@ -92,7 +69,12 @@ class VertexFaceCountFieldInput final : public bke::MeshFieldInput { const eAttrDomain domain, const IndexMask & /*mask*/) const final { - return construct_face_count_gvarray(mesh, domain); + if (domain != ATTR_DOMAIN_POINT) { + return {}; + } + Array counts(mesh.totvert, 0); + array_utils::count_indices(mesh.corner_verts(), counts); + return VArray::ForContainer(std::move(counts)); } uint64_t hash() const override diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_edge.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_edge.cc index 4e1ee9359cf..046a72dfa89 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_edge.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_edge.cc @@ -5,7 +5,7 @@ #include "BKE_mesh.hh" #include "BKE_mesh_mapping.h" -#include "BLI_task.hh" +#include "BLI_array_utils.hh" #include "node_geometry_util.hh" @@ -151,11 +151,8 @@ class CornersOfEdgeCountInput final : public bke::MeshFieldInput { if (domain != ATTR_DOMAIN_EDGE) { return {}; } - const Span corner_edges = mesh.corner_edges(); Array counts(mesh.totedge, 0); - for (const int i : corner_edges.index_range()) { - counts[corner_edges[i]]++; - } + array_utils::count_indices(mesh.corner_edges(), counts); return VArray::ForContainer(std::move(counts)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc index 63c83ecbbd1..a19365748b3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc @@ -5,7 +5,7 @@ #include "BKE_mesh.hh" #include "BKE_mesh_mapping.h" -#include "BLI_task.hh" +#include "BLI_array_utils.hh" #include "node_geometry_util.hh" @@ -158,11 +158,8 @@ class CornersOfVertCountInput final : public bke::MeshFieldInput { if (domain != ATTR_DOMAIN_POINT) { return {}; } - const Span corner_verts = mesh.corner_verts(); Array counts(mesh.totvert, 0); - for (const int i : corner_verts.index_range()) { - counts[corner_verts[i]]++; - } + array_utils::count_indices(mesh.corner_verts(), counts); return VArray::ForContainer(std::move(counts)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_vertex.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_vertex.cc index bbd4ea3c1e2..d892b5efd23 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_vertex.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_vertex.cc @@ -5,7 +5,7 @@ #include "BKE_mesh.hh" #include "BKE_mesh_mapping.h" -#include "BLI_task.hh" +#include "BLI_array_utils.hh" #include "node_geometry_util.hh" @@ -160,12 +160,8 @@ class EdgesOfVertCountInput final : public bke::MeshFieldInput { if (domain != ATTR_DOMAIN_POINT) { return {}; } - const Span edges = mesh.edges(); Array counts(mesh.totvert, 0); - for (const int i : edges.index_range()) { - counts[edges[i][0]]++; - counts[edges[i][1]]++; - } + array_utils::count_indices(mesh.edges().cast(), counts); return VArray::ForContainer(std::move(counts)); }