BLI: Add utility to reverse index mask

This utility was already duplicated in two places and planned to be used
more. While we should usually avoid creating arrays the size of the
indexed array (rather than the size of the mask), sometimes it does seem
to be the best option, and we're helped by the fact that most memory
stays unintialized for a small mask (allocating but not writing to memory
pages at all generally isn't too expensive).

Pull Request: https://projects.blender.org/blender/blender/pulls/115491
This commit is contained in:
Hans Goudey
2023-11-28 17:32:17 +01:00
committed by Hans Goudey
parent ed23989e2e
commit 21a2390f4c
4 changed files with 24 additions and 22 deletions

View File

@@ -423,7 +423,7 @@ const IndexMask &get_static_index_mask_for_min_size(const int64_t min_size);
std::ostream &operator<<(std::ostream &stream, const IndexMask &mask);
/* -------------------------------------------------------------------- */
/** \name Inline Utilities
/** \name Utilities
* \{ */
inline const std::array<int16_t, max_segment_size> &get_static_indices_array()
@@ -439,6 +439,13 @@ inline void masked_fill(MutableSpan<T> data, const T &value, const IndexMask &ma
mask.foreach_index_optimized<int64_t>([&](const int64_t i) { data[i] = value; });
}
/**
* Fill masked indices of \a r_mask with the index of that item in the mask such that
* `r_map[mask[i]] == i` for the whole mask. The size of `r_map` needs to be at least
* `mask.min_array_size()`.
*/
template<typename T> void build_reverse_map(const IndexMask &mask, MutableSpan<T> r_map);
/* -------------------------------------------------------------------- */
/** \name #RawMaskIterator Inline Methods
* \{ */

View File

@@ -20,6 +20,19 @@
namespace blender::index_mask {
template<typename T> void build_reverse_map(const IndexMask &mask, MutableSpan<T> r_map)
{
#ifdef DEBUG
/* Catch errors with asserts in debug builds. */
r_map.fill(-1);
#endif
BLI_assert(r_map.size() >= mask.min_array_size());
mask.foreach_index_optimized<T>(GrainSize(4096),
[&](const T src, const T dst) { r_map[src] = dst; });
}
template void build_reverse_map<int>(const IndexMask &mask, MutableSpan<int> r_map);
std::array<int16_t, max_segment_size> build_static_indices_array()
{
std::array<int16_t, max_segment_size> data;

View File

@@ -17,15 +17,6 @@
namespace blender::geometry {
static void create_reverse_map(const IndexMask &mask, MutableSpan<int> r_map)
{
#ifdef DEBUG
r_map.fill(-1);
#endif
mask.foreach_index_optimized<int>(
GrainSize(4096), [&](const int src_i, const int dst_i) { r_map[src_i] = dst_i; });
}
static void remap_verts(const OffsetIndices<int> src_faces,
const OffsetIndices<int> dst_faces,
const int src_verts_num,
@@ -38,7 +29,7 @@ static void remap_verts(const OffsetIndices<int> src_faces,
MutableSpan<int> dst_corner_verts)
{
Array<int> map(src_verts_num);
create_reverse_map(vert_mask, map);
index_mask::build_reverse_map<int>(vert_mask, map);
threading::parallel_invoke(
vert_mask.size() > 1024,
[&]() {
@@ -67,7 +58,7 @@ static void remap_edges(const OffsetIndices<int> src_faces,
MutableSpan<int> dst_corner_edges)
{
Array<int> map(src_edges_num);
create_reverse_map(edge_mask, map);
index_mask::build_reverse_map<int>(edge_mask, map);
face_mask.foreach_index(GrainSize(512), [&](const int64_t src_i, const int64_t dst_i) {
const IndexRange src_face = src_faces[src_i];
const IndexRange dst_face = dst_faces[dst_i];

View File

@@ -444,15 +444,6 @@ static void fill_quad_consistent_direction(const Span<int> other_face_verts,
}
}
static void create_reverse_map(const IndexMask &mask, MutableSpan<int> r_map)
{
#ifdef DEBUG
r_map.fill(-1);
#endif
mask.foreach_index_optimized<int>(
GrainSize(4096), [&](const int src_i, const int dst_i) { r_map[src_i] = dst_i; });
}
static GroupedSpan<int> build_vert_to_edge_map(const Span<int2> edges,
const IndexMask &edge_mask,
const int verts_num,
@@ -596,7 +587,7 @@ static void extrude_mesh_edges(Mesh &mesh,
{
Array<int> vert_to_new_vert(orig_vert_size);
create_reverse_map(new_verts, vert_to_new_vert);
index_mask::build_reverse_map<int>(new_verts, vert_to_new_vert);
for (const int i : duplicate_edges.index_range()) {
const int2 orig_edge = edges[edge_selection[i]];
const int i_new_vert_1 = vert_to_new_vert[orig_edge[0]];