diff options
Diffstat (limited to 'source/blender/draw/intern/draw_cache_extract_mesh_render_data.c')
-rw-r--r-- | source/blender/draw/intern/draw_cache_extract_mesh_render_data.c | 228 |
1 files changed, 116 insertions, 112 deletions
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c index bec21bd5a8c..297d61babb0 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c @@ -25,6 +25,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_alloca.h" #include "BLI_bitmap.h" #include "BLI_math.h" #include "BLI_task.h" @@ -179,116 +180,104 @@ void mesh_render_data_update_loose_geom(MeshRenderData *mr, /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Material Offsets +/** \name Polygons sorted per material * - * Material offsets contains the offset of a material after sorting tris based on their material. + * Contains polygon indices sorted based on their material. * * \{ */ -static void mesh_render_data_mat_offset_load(MeshRenderData *mr, - const MeshBufferExtractionCache *cache); -static void mesh_render_data_mat_offset_ensure(MeshRenderData *mr, - MeshBufferExtractionCache *cache); -static void mesh_render_data_mat_offset_build(MeshRenderData *mr, - MeshBufferExtractionCache *cache); -static void mesh_render_data_mat_offset_build_bm(MeshRenderData *mr, +static void mesh_render_data_polys_sorted_load(MeshRenderData *mr, + const MeshBufferExtractionCache *cache); +static void mesh_render_data_polys_sorted_ensure(MeshRenderData *mr, MeshBufferExtractionCache *cache); -static void mesh_render_data_mat_offset_build_mesh(MeshRenderData *mr, - MeshBufferExtractionCache *cache); -static void mesh_render_data_mat_offset_apply_offset(MeshRenderData *mr, - MeshBufferExtractionCache *cache); - -void mesh_render_data_update_mat_offsets(MeshRenderData *mr, - MeshBufferExtractionCache *cache, - const eMRDataType data_flag) +static void mesh_render_data_polys_sorted_build(MeshRenderData *mr, + MeshBufferExtractionCache *cache); +static int *mesh_render_data_mat_tri_len_build(MeshRenderData *mr); + +void mesh_render_data_update_polys_sorted(MeshRenderData *mr, + MeshBufferExtractionCache *cache, + const eMRDataType data_flag) { - if (data_flag & MR_DATA_MAT_OFFSETS) { - mesh_render_data_mat_offset_ensure(mr, cache); - mesh_render_data_mat_offset_load(mr, cache); + if (data_flag & MR_DATA_POLYS_SORTED) { + mesh_render_data_polys_sorted_ensure(mr, cache); + mesh_render_data_polys_sorted_load(mr, cache); } } -static void mesh_render_data_mat_offset_load(MeshRenderData *mr, - const MeshBufferExtractionCache *cache) +static void mesh_render_data_polys_sorted_load(MeshRenderData *mr, + const MeshBufferExtractionCache *cache) { - mr->mat_offsets.tri = cache->mat_offsets.tri; - mr->mat_offsets.visible_tri_len = cache->mat_offsets.visible_tri_len; + mr->poly_sorted.tri_first_index = cache->poly_sorted.tri_first_index; + mr->poly_sorted.mat_tri_len = cache->poly_sorted.mat_tri_len; + mr->poly_sorted.visible_tri_len = cache->poly_sorted.visible_tri_len; } -static void mesh_render_data_mat_offset_ensure(MeshRenderData *mr, - MeshBufferExtractionCache *cache) +static void mesh_render_data_polys_sorted_ensure(MeshRenderData *mr, + MeshBufferExtractionCache *cache) { - if (cache->mat_offsets.tri) { + if (cache->poly_sorted.tri_first_index) { return; } - mesh_render_data_mat_offset_build(mr, cache); + mesh_render_data_polys_sorted_build(mr, cache); } -static void mesh_render_data_mat_offset_build(MeshRenderData *mr, MeshBufferExtractionCache *cache) +static void mesh_render_data_polys_sorted_build(MeshRenderData *mr, + MeshBufferExtractionCache *cache) { - size_t mat_tri_idx_size = sizeof(int) * mr->mat_len; - cache->mat_offsets.tri = MEM_callocN(mat_tri_idx_size, __func__); + int *tri_first_index = MEM_mallocN(sizeof(*tri_first_index) * mr->poly_len, __func__); + int *mat_tri_len = mesh_render_data_mat_tri_len_build(mr); + + /* Apply offset. */ + int visible_tri_len = 0; + int *mat_tri_offs = BLI_array_alloca(mat_tri_offs, mr->mat_len); + { + for (int i = 0; i < mr->mat_len; i++) { + mat_tri_offs[i] = visible_tri_len; + visible_tri_len += mat_tri_len[i]; + } + } - /* Count how many triangles for each material. */ + /* Sort per material. */ + int mat_last = mr->mat_len - 1; if (mr->extract_type == MR_EXTRACT_BMESH) { - mesh_render_data_mat_offset_build_bm(mr, cache); + BMIter iter; + BMFace *f; + int i; + BM_ITER_MESH_INDEX (f, &iter, mr->bm, BM_FACES_OF_MESH, i) { + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + const int mat = min_ii(f->mat_nr, mat_last); + tri_first_index[i] = mat_tri_offs[mat]; + mat_tri_offs[mat] += f->len - 2; + } + else { + tri_first_index[i] = -1; + } + } } else { - mesh_render_data_mat_offset_build_mesh(mr, cache); - } - - mesh_render_data_mat_offset_apply_offset(mr, cache); -} - -typedef struct MatOffsetUserData { - MeshRenderData *mr; - /** This struct is extended during allocation to hold mat_tri_len for each material. */ - int mat_tri_len[0]; -} MatOffsetUserData; - -static void mesh_render_data_mat_offset_reduce(const void *__restrict UNUSED(userdata), - void *__restrict chunk_join, - void *__restrict chunk) -{ - MatOffsetUserData *dst = chunk_join; - MatOffsetUserData *src = chunk; - int *dst_mat_len = dst->mat_tri_len; - int *src_mat_len = src->mat_tri_len; - for (int i = 0; i < dst->mr->mat_len; i++) { - dst_mat_len[i] += src_mat_len[i]; + const MPoly *mp = &mr->mpoly[0]; + for (int i = 0; i < mr->poly_len; i++, mp++) { + if (!(mr->use_hide && (mp->flag & ME_HIDE))) { + const int mat = min_ii(mp->mat_nr, mat_last); + tri_first_index[i] = mat_tri_offs[mat]; + mat_tri_offs[mat] += mp->totloop - 2; + } + else { + tri_first_index[i] = -1; + } + } } -} - -static void mesh_render_data_mat_offset_build_threaded(MeshRenderData *mr, - MeshBufferExtractionCache *cache, - int face_len, - TaskParallelRangeFunc range_func) -{ - /* Extending the #MatOffsetUserData with an int per material slot. */ - size_t userdata_size = sizeof(MatOffsetUserData) + - (mr->mat_len) * sizeof(*cache->mat_offsets.tri); - MatOffsetUserData *userdata = MEM_callocN(userdata_size, __func__); - userdata->mr = mr; - TaskParallelSettings settings; - BLI_parallel_range_settings_defaults(&settings); - settings.userdata_chunk = userdata; - settings.userdata_chunk_size = userdata_size; - settings.min_iter_per_thread = MIN_RANGE_LEN; - settings.func_reduce = mesh_render_data_mat_offset_reduce; - BLI_task_parallel_range(0, face_len, NULL, range_func, &settings); - memcpy(cache->mat_offsets.tri, - &userdata->mat_tri_len, - (mr->mat_len) * sizeof(*cache->mat_offsets.tri)); - MEM_freeN(userdata); + cache->poly_sorted.tri_first_index = tri_first_index; + cache->poly_sorted.mat_tri_len = mat_tri_len; + cache->poly_sorted.visible_tri_len = visible_tri_len; } -static void mesh_render_data_mat_offset_bm_range(void *__restrict UNUSED(userdata), - const int iter, - const TaskParallelTLS *__restrict tls) +static void mesh_render_data_mat_tri_len_bm_range_fn(void *__restrict userdata, + const int iter, + const TaskParallelTLS *__restrict tls) { - MatOffsetUserData *mat_offset_userdata = tls->userdata_chunk; - MeshRenderData *mr = mat_offset_userdata->mr; - int *mat_tri_len = mat_offset_userdata->mat_tri_len; + MeshRenderData *mr = userdata; + int *mat_tri_len = tls->userdata_chunk; BMesh *bm = mr->bm; BMFace *efa = BM_face_at_index(bm, iter); @@ -298,21 +287,12 @@ static void mesh_render_data_mat_offset_bm_range(void *__restrict UNUSED(userdat } } -static void mesh_render_data_mat_offset_build_bm(MeshRenderData *mr, - MeshBufferExtractionCache *cache) -{ - BMesh *bm = mr->bm; - mesh_render_data_mat_offset_build_threaded( - mr, cache, bm->totface, mesh_render_data_mat_offset_bm_range); -} - -static void mesh_render_data_mat_offset_mesh_range(void *__restrict UNUSED(userdata), - const int iter, - const TaskParallelTLS *__restrict tls) +static void mesh_render_data_mat_tri_len_mesh_range_fn(void *__restrict userdata, + const int iter, + const TaskParallelTLS *__restrict tls) { - MatOffsetUserData *mat_offset_userdata = tls->userdata_chunk; - const MeshRenderData *mr = mat_offset_userdata->mr; - int *mat_tri_len = mat_offset_userdata->mat_tri_len; + MeshRenderData *mr = userdata; + int *mat_tri_len = tls->userdata_chunk; const MPoly *mp = &mr->mpoly[iter]; if (!(mr->use_hide && (mp->flag & ME_HIDE))) { @@ -321,25 +301,49 @@ static void mesh_render_data_mat_offset_mesh_range(void *__restrict UNUSED(userd } } -static void mesh_render_data_mat_offset_build_mesh(MeshRenderData *mr, - MeshBufferExtractionCache *cache) +static void mesh_render_data_mat_tri_len_reduce_fn(const void *__restrict userdata, + void *__restrict chunk_join, + void *__restrict chunk) +{ + const MeshRenderData *mr = userdata; + int *dst_mat_len = chunk_join; + int *src_mat_len = chunk; + for (int i = 0; i < mr->mat_len; i++) { + dst_mat_len[i] += src_mat_len[i]; + } +} + +static int *mesh_render_data_mat_tri_len_build_threaded(MeshRenderData *mr, + int face_len, + TaskParallelRangeFunc range_func) { - mesh_render_data_mat_offset_build_threaded( - mr, cache, mr->poly_len, mesh_render_data_mat_offset_mesh_range); + /* Extending the #MatOffsetUserData with an int per material slot. */ + size_t mat_tri_len_size = sizeof(int) * mr->mat_len; + int *mat_tri_len = MEM_callocN(mat_tri_len_size, __func__); + + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.userdata_chunk = mat_tri_len; + settings.userdata_chunk_size = mat_tri_len_size; + 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); + + return mat_tri_len; } -static void mesh_render_data_mat_offset_apply_offset(MeshRenderData *mr, - MeshBufferExtractionCache *cache) +/* Count how many triangles for each material. */ +static int *mesh_render_data_mat_tri_len_build(MeshRenderData *mr) { - int *mat_tri_len = cache->mat_offsets.tri; - int ofs = mat_tri_len[0]; - mat_tri_len[0] = 0; - for (int i = 1; i < mr->mat_len; i++) { - int tmp = mat_tri_len[i]; - mat_tri_len[i] = ofs; - ofs += tmp; + if (mr->extract_type == MR_EXTRACT_BMESH) { + BMesh *bm = mr->bm; + return mesh_render_data_mat_tri_len_build_threaded( + mr, bm->totface, mesh_render_data_mat_tri_len_bm_range_fn); + } + else { + return mesh_render_data_mat_tri_len_build_threaded( + mr, mr->poly_len, mesh_render_data_mat_tri_len_mesh_range_fn); } - cache->mat_offsets.visible_tri_len = ofs; } /** \} */ |