Files
test/source/blender/blenlib/intern/offset_indices.cc
Hans Goudey 2b4666b17b Geometry Nodes: Fill new quad poly offsets in parallel
Add an offset indices utility to do fill constant size new offsets in
parallel, which was already done in the duplicate elements node.

For example, filling poly offsets for a new part of a mesh that is only
quads. In the extrude node this was single-threaded before, so the
new poly offsets is about 10x faster, saving about 10 out of 157 ms
when extruding 2 million faces.
2023-07-05 15:39:33 -04:00

81 lines
2.6 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array_utils.hh"
#include "BLI_offset_indices.hh"
#include "BLI_task.hh"
namespace blender::offset_indices {
OffsetIndices<int> accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets,
const int start_offset)
{
int offset = start_offset;
for (const int i : counts_to_offsets.index_range().drop_back(1)) {
const int count = counts_to_offsets[i];
BLI_assert(count >= 0);
counts_to_offsets[i] = offset;
offset += count;
}
counts_to_offsets.last() = offset;
return OffsetIndices<int>(counts_to_offsets);
}
void fill_constant_group_size(const int size, const int start_offset, MutableSpan<int> offsets)
{
threading::parallel_for(offsets.index_range(), 1024, [&](const IndexRange range) {
for (const int64_t i : range) {
offsets[i] = size * i + start_offset;
}
});
}
void copy_group_sizes(const OffsetIndices<int> offsets,
const IndexMask &mask,
MutableSpan<int> sizes)
{
mask.foreach_index_optimized<int64_t>(GrainSize(4096),
[&](const int64_t i) { sizes[i] = offsets[i].size(); });
}
void gather_group_sizes(const OffsetIndices<int> offsets,
const IndexMask &mask,
MutableSpan<int> sizes)
{
mask.foreach_index_optimized<int64_t>(GrainSize(4096), [&](const int64_t i, const int64_t pos) {
sizes[pos] = offsets[i].size();
});
}
OffsetIndices<int> gather_selected_offsets(const OffsetIndices<int> src_offsets,
const IndexMask &selection,
MutableSpan<int> dst_offsets)
{
if (selection.is_empty()) {
return {};
}
BLI_assert(selection.size() == (dst_offsets.size() - 1));
gather_group_sizes(src_offsets, selection, dst_offsets);
accumulate_counts_to_offsets(dst_offsets);
return OffsetIndices<int>(dst_offsets);
}
void build_reverse_map(OffsetIndices<int> offsets, MutableSpan<int> r_map)
{
threading::parallel_for(offsets.index_range(), 1024, [&](const IndexRange range) {
for (const int64_t i : range) {
r_map.slice(offsets[i]).fill(i);
}
});
}
void build_reverse_offsets(const Span<int> indices, MutableSpan<int> offsets)
{
BLI_assert(std::all_of(offsets.begin(), offsets.end(), [](int value) { return value == 0; }));
array_utils::count_indices(indices, offsets);
offset_indices::accumulate_counts_to_offsets(offsets);
}
} // namespace blender::offset_indices