Cleanup: Simplify mesh triangle material counting #105940

Merged
Hans Goudey merged 12 commits from HooglyBoogly/blender:mesh-mat-tri-len-count into main 2023-08-03 05:02:43 +02:00
1 changed files with 64 additions and 64 deletions

View File

@ -11,9 +11,8 @@
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
#include "BLI_array.hh" #include "BLI_array.hh"
#include "BLI_bitmap.h" #include "BLI_enumerable_thread_specific.hh"
#include "BLI_math.h" #include "BLI_task.hh"
#include "BLI_task.h"
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
@ -166,87 +165,86 @@ void mesh_render_data_update_loose_geom(MeshRenderData *mr,
* Contains face indices sorted based on their material. * Contains face indices sorted based on their material.
* \{ */ * \{ */
static void mesh_render_data_mat_tri_len_bm_range_fn(void *__restrict userdata, namespace blender::draw {
const int iter,
const TaskParallelTLS *__restrict tls)
{
MeshRenderData *mr = static_cast<MeshRenderData *>(userdata);
int *mat_tri_len = static_cast<int *>(tls->userdata_chunk);
BMesh *bm = mr->bm; static void accumululate_material_counts_bm(
BMFace *efa = BM_face_at_index(bm, iter); const BMesh &bm, threading::EnumerableThreadSpecific<Array<int>> &all_tri_counts)
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { {
int mat = clamp_i(efa->mat_nr, 0, mr->mat_len - 1); threading::parallel_for(IndexRange(bm.totface), 1024, [&](const IndexRange range) {
mat_tri_len[mat] += efa->len - 2; Array<int> &tri_counts = all_tri_counts.local();
} const short last_index = tri_counts.size() - 1;
for (const int i : range) {
const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), i);
if (!BM_elem_flag_test(&face, BM_ELEM_HIDDEN)) {
const short mat = std::clamp<short>(face.mat_nr, 0, last_index);
tri_counts[mat] += face.len - 2;
}
}
});
} }
static void mesh_render_data_mat_tri_len_mesh_range_fn(void *__restrict userdata, static void accumululate_material_counts_mesh(
const int iter, const MeshRenderData &mr, threading::EnumerableThreadSpecific<Array<int>> &all_tri_counts)
const TaskParallelTLS *__restrict tls)
{ {
MeshRenderData *mr = static_cast<MeshRenderData *>(userdata); if (!mr.material_indices) {
int *mat_tri_len = static_cast<int *>(tls->userdata_chunk); all_tri_counts.local().first() = poly_to_tri_count(mr.face_len, mr.loop_len);
return;
if (!(mr->use_hide && mr->hide_poly && mr->hide_poly[iter])) {
const int mat = mr->material_indices ?
clamp_i(mr->material_indices[iter], 0, mr->mat_len - 1) :
0;
mat_tri_len[mat] += mr->faces[iter].size() - 2;
} }
}
static void mesh_render_data_mat_tri_len_reduce_fn(const void *__restrict userdata, const OffsetIndices faces = mr.faces;
void *__restrict chunk_join, const Span material_indices(mr.material_indices, mr.face_len);
void *__restrict chunk) threading::parallel_for(material_indices.index_range(), 1024, [&](const IndexRange range) {
{ Array<int> &tri_counts = all_tri_counts.local();
const MeshRenderData *mr = static_cast<const MeshRenderData *>(userdata); const int last_index = tri_counts.size() - 1;
int *dst_mat_len = static_cast<int *>(chunk_join); if (mr.use_hide && mr.hide_poly) {
int *src_mat_len = static_cast<int *>(chunk); for (const int i : range) {
for (int i = 0; i < mr->mat_len; i++) { if (!mr.hide_poly[i]) {
dst_mat_len[i] += src_mat_len[i]; const int mat = std::clamp(material_indices[i], 0, last_index);
} tri_counts[mat] += ME_FACE_TRI_TOT(faces[i].size());
} }
}
static void mesh_render_data_mat_tri_len_build_threaded(MeshRenderData *mr, }
int face_len, else {
TaskParallelRangeFunc range_func, for (const int i : range) {
blender::MutableSpan<int> mat_tri_len) const int mat = std::clamp(material_indices[i], 0, last_index);
{ tri_counts[mat] += ME_FACE_TRI_TOT(faces[i].size());
TaskParallelSettings settings; }
BLI_parallel_range_settings_defaults(&settings); }
settings.userdata_chunk = mat_tri_len.data(); });
settings.userdata_chunk_size = mat_tri_len.as_span().size_in_bytes();
settings.min_iter_per_thread = MIN_RANGE_LEN;
settings.func_reduce = mesh_render_data_mat_tri_len_reduce_fn;
BLI_task_parallel_range(0, face_len, mr, range_func, &settings);
} }
/* Count how many triangles for each material. */ /* Count how many triangles for each material. */
static blender::Array<int> mesh_render_data_mat_tri_len_build(MeshRenderData *mr) static Array<int> mesh_render_data_mat_tri_len_build(const MeshRenderData &mr)
{ {
blender::Array<int> mat_tri_len(mr->mat_len, 0); threading::EnumerableThreadSpecific<Array<int>> all_tri_counts(
if (mr->extract_type == MR_EXTRACT_BMESH) { [&]() { return Array<int>(mr.mat_len, 0); });
BMesh *bm = mr->bm;
mesh_render_data_mat_tri_len_build_threaded( if (mr.extract_type == MR_EXTRACT_BMESH) {
mr, bm->totface, mesh_render_data_mat_tri_len_bm_range_fn, mat_tri_len); accumululate_material_counts_bm(*mr.bm, all_tri_counts);
} }
else { else {
mesh_render_data_mat_tri_len_build_threaded( accumululate_material_counts_mesh(mr, all_tri_counts);
mr, mr->face_len, mesh_render_data_mat_tri_len_mesh_range_fn, mat_tri_len);
} }
return mat_tri_len;
Array<int> &mat_tri_len = all_tri_counts.local();
for (const Array<int> &counts : all_tri_counts) {
if (&counts != &mat_tri_len) {
for (const int i : mat_tri_len.index_range()) {
mat_tri_len[i] += counts[i];
}
}
}
return std::move(mat_tri_len);
} }
static void mesh_render_data_faces_sorted_build(MeshRenderData *mr, MeshBufferCache *cache) static void mesh_render_data_faces_sorted_build(MeshRenderData *mr, MeshBufferCache *cache)
{ {
using namespace blender; cache->face_sorted.mat_tri_len = mesh_render_data_mat_tri_len_build(*mr);
cache->face_sorted.mat_tri_len = mesh_render_data_mat_tri_len_build(mr);
const Span<int> mat_tri_len = cache->face_sorted.mat_tri_len; const Span<int> mat_tri_len = cache->face_sorted.mat_tri_len;
/* Apply offset. */ /* Apply offset. */
int visible_tri_len = 0; int visible_tri_len = 0;
blender::Array<int, 32> mat_tri_offs(mr->mat_len); Array<int, 32> mat_tri_offs(mr->mat_len);
{ {
for (int i = 0; i < mr->mat_len; i++) { for (int i = 0; i < mr->mat_len; i++) {
mat_tri_offs[i] = visible_tri_len; mat_tri_offs[i] = visible_tri_len;
@ -297,12 +295,14 @@ static void mesh_render_data_faces_sorted_ensure(MeshRenderData *mr, MeshBufferC
mesh_render_data_faces_sorted_build(mr, cache); mesh_render_data_faces_sorted_build(mr, cache);
} }
} // namespace blender::draw
void mesh_render_data_update_faces_sorted(MeshRenderData *mr, void mesh_render_data_update_faces_sorted(MeshRenderData *mr,
MeshBufferCache *cache, MeshBufferCache *cache,
const eMRDataType data_flag) const eMRDataType data_flag)
{ {
if (data_flag & MR_DATA_POLYS_SORTED) { if (data_flag & MR_DATA_POLYS_SORTED) {
mesh_render_data_faces_sorted_ensure(mr, cache); blender::draw::mesh_render_data_faces_sorted_ensure(mr, cache);
mr->face_sorted = &cache->face_sorted; mr->face_sorted = &cache->face_sorted;
} }
} }