Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
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.c228
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;
}
/** \} */