Mesh: Parallelize extraction of UV maps #105793

Merged
Hans Goudey merged 4 commits from HooglyBoogly/blender:mesh-extract-uv-parallel into main 2023-03-19 16:18:30 +01:00
3 changed files with 38 additions and 11 deletions

View File

@ -10,6 +10,24 @@
namespace blender::array_utils {
/**
* Fill the destination span by copying all values from the `src` array. Threaded based on
* grain-size.
*/
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size = 4096);
/**
* Fill the destination span by copying all values from the `src` array. Threaded based on
* grain-size.
*/
template<typename T>
inline void copy(const Span<T> src, MutableSpan<T> dst, const int64_t grain_size = 4096)
{
BLI_assert(src.size() == dst.size());
threading::parallel_for(src.index_range(), grain_size, [&](const IndexRange range) {
HooglyBoogly marked this conversation as resolved Outdated

Shouldn't really help to capture src and dst explicitly here, just use &.

Shouldn't really help to capture `src` and `dst` explicitly here, just use `&`.
dst.slice(range).copy_from(src.slice(range));
});
}
/**
* Fill the destination span by copying masked values from the `src` array. Threaded based on
* grain-size.

View File

@ -4,6 +4,15 @@
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,

View File

@ -5,8 +5,8 @@
* \ingroup draw
*/
#include "BLI_array_utils.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_string.h"
#include "draw_subdivision.h"
#include "extract_mesh.hh"
@ -91,8 +91,9 @@ static void extract_uv_init(const MeshRenderData *mr,
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, v_len);
float2 *uv_data = static_cast<float2 *>(GPU_vertbuf_get_data(vbo));
for (int i = 0; i < MAX_MTFACE; i++) {
MutableSpan<float2> uv_data(static_cast<float2 *>(GPU_vertbuf_get_data(vbo)), v_len);
int vbo_index = 0;
for (const int i : IndexRange(MAX_MTFACE)) {
if (uv_layers & (1 << i)) {
if (mr->extract_type == MR_EXTRACT_BMESH) {
int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_PROP_FLOAT2, i);
@ -102,18 +103,17 @@ static void extract_uv_init(const MeshRenderData *mr,
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
do {
float *luv = BM_ELEM_CD_GET_FLOAT_P(l_iter, cd_ofs);
memcpy(uv_data, luv, sizeof(*uv_data));
uv_data++;
uv_data[vbo_index] = BM_ELEM_CD_GET_FLOAT_P(l_iter, cd_ofs);
vbo_index++;
} while ((l_iter = l_iter->next) != l_first);
}
}
else {
const float2 *layer_data = static_cast<const float2 *>(
CustomData_get_layer_n(cd_ldata, CD_PROP_FLOAT2, i));
for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, uv_data++, layer_data++) {
memcpy(uv_data, layer_data, sizeof(*uv_data));
}
const Span<float2> uv_map(
static_cast<const float2 *>(CustomData_get_layer_n(cd_ldata, CD_PROP_FLOAT2, i)),
HooglyBoogly marked this conversation as resolved Outdated

I'm a bit confused why there is a nested loop now.

I'm a bit confused why there is a nested loop now.

Ah, yikes, sorry about that!

Ah, yikes, sorry about that!
mr->loop_len);
array_utils::copy(uv_map, uv_data.slice(vbo_index, mr->loop_len));
vbo_index += mr->loop_len;
}
}
}