Files
test2/source/blender/blenlib/intern/array_utils.cc
Hans Goudey 63a44e29ac Mesh: Parallelize extraction of UV maps
Since UVs are now stored as 2D vectors in meshes, they can be copied
directly to the vertex buffers. Somewhat surprisingly, multithreading
the copying into the vertex buffer provides a good speedup-- on a CPU
with many cores at least.

Here is a test uploading two UV maps created in geometry
nodes with a 1 million quad mesh, with a Ryzen 7950x:
|         | Before  | After  | Speedup |
| ------- | ------- | ------ | ------- |
| Average | 24.3 ms | 7.5 ms | 3.2x    |
| Min     | 17.6 ms | 7.0 ms | 2.5x    |

I added the copying utilities to the array utils header, since the
need for them has come up in a few different places already, and the
existing function with a selection argument didn't make sense here.

Pull Request: https://projects.blender.org/blender/blender/pulls/105793
2023-03-19 16:18:19 +01:00

56 lines
1.7 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array_utils.hh"
namespace blender::array_utils {
void copy(const GVArray &src, GMutableSpan dst, const int64_t grain_size)
{
BLI_assert(src.type() == dst.type());
BLI_assert(src.size() == dst.size());
threading::parallel_for(src.index_range(), grain_size, [&](const IndexRange range) {
src.materialize_to_uninitialized(range, dst.data());
});
}
void copy(const GVArray &src,
const IndexMask selection,
GMutableSpan dst,
const int64_t grain_size)
{
BLI_assert(src.type() == dst.type());
BLI_assert(src.size() >= selection.min_array_size());
BLI_assert(dst.size() >= selection.min_array_size());
threading::parallel_for(selection.index_range(), grain_size, [&](const IndexRange range) {
src.materialize_to_uninitialized(selection.slice(range), dst.data());
});
}
void gather(const GVArray &src,
const IndexMask indices,
GMutableSpan dst,
const int64_t grain_size)
{
BLI_assert(src.type() == dst.type());
BLI_assert(indices.size() == dst.size());
threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) {
src.materialize_compressed_to_uninitialized(indices.slice(range), dst.slice(range).data());
});
}
void gather(const GSpan src, const IndexMask indices, GMutableSpan dst, const int64_t grain_size)
{
gather(GVArray::ForSpan(src), indices, dst, grain_size);
}
void invert_booleans(MutableSpan<bool> span)
{
threading::parallel_for(span.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
span[i] = !span[i];
}
});
}
} // namespace blender::array_utils