[Bf-blender-cvs] [174ed69c1ba] master: DrawManager: Cache material offsets.

Jeroen Bakker noreply at git.blender.org
Tue Jun 15 15:31:36 CEST 2021


Commit: 174ed69c1ba8cb8ca7ac39d41922bc203f78326f
Author: Jeroen Bakker
Date:   Tue Jun 15 15:31:17 2021 +0200
Branches: master
https://developer.blender.org/rB174ed69c1ba8cb8ca7ac39d41922bc203f78326f

DrawManager: Cache material offsets.

When using multiple materials in a single mesh the most time is spend in
counting the offsets of each material for the sorting.

This patch moves the counting of the offsets to render mesh data and
caches it as long as the geometry doesn't change.

This patch doesn't include multithreading of this code.

Reviewed By: mano-wii

Differential Revision: https://developer.blender.org/D11612

===================================================================

M	source/blender/draw/intern/draw_cache_extract.h
M	source/blender/draw/intern/draw_cache_extract_mesh.cc
M	source/blender/draw/intern/draw_cache_extract_mesh_private.h
M	source/blender/draw/intern/draw_cache_extract_mesh_render_data.c
M	source/blender/draw/intern/draw_cache_impl_mesh.c
M	source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc

===================================================================

diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h
index 46234366251..2c4e4dfe76b 100644
--- a/source/blender/draw/intern/draw_cache_extract.h
+++ b/source/blender/draw/intern/draw_cache_extract.h
@@ -83,8 +83,9 @@ typedef enum eMRDataType {
   MR_DATA_LOOPTRI = 1 << 3,
   /** Force loop normals calculation.  */
   MR_DATA_TAN_LOOP_NOR = 1 << 4,
+  MR_DATA_MAT_OFFSETS = 1 << 5,
 } eMRDataType;
-ENUM_OPERATORS(eMRDataType, MR_DATA_TAN_LOOP_NOR)
+ENUM_OPERATORS(eMRDataType, MR_DATA_MAT_OFFSETS)
 
 #ifdef __cplusplus
 extern "C" {
@@ -166,6 +167,12 @@ typedef struct MeshBufferExtractionCache {
     int *verts;
     int *edges;
   } loose_geom;
+
+  struct {
+    int *tri;
+    int visible_tri_len;
+  } mat_offsets;
+
 } MeshBufferExtractionCache;
 
 typedef enum DRWBatchFlag {
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc
index c6b749fe11a..021565fceac 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.cc
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc
@@ -498,11 +498,15 @@ static struct TaskNode *extract_task_node_create(struct TaskGraph *task_graph,
  * \{ */
 struct MeshRenderDataUpdateTaskData {
   MeshRenderData *mr = nullptr;
+  MeshBufferExtractionCache *cache = nullptr;
   eMRIterType iter_type;
   eMRDataType data_flag;
 
-  MeshRenderDataUpdateTaskData(MeshRenderData *mr, eMRIterType iter_type, eMRDataType data_flag)
-      : mr(mr), iter_type(iter_type), data_flag(data_flag)
+  MeshRenderDataUpdateTaskData(MeshRenderData *mr,
+                               MeshBufferExtractionCache *cache,
+                               eMRIterType iter_type,
+                               eMRDataType data_flag)
+      : mr(mr), cache(cache), iter_type(iter_type), data_flag(data_flag)
   {
   }
 
@@ -533,15 +537,17 @@ static void mesh_extract_render_data_node_exec(void *__restrict task_data)
 
   mesh_render_data_update_normals(mr, data_flag);
   mesh_render_data_update_looptris(mr, iter_type, data_flag);
+  mesh_render_data_update_mat_offsets(mr, update_task_data->cache, data_flag);
 }
 
 static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *task_graph,
                                                              MeshRenderData *mr,
+                                                             MeshBufferExtractionCache *cache,
                                                              const eMRIterType iter_type,
                                                              const eMRDataType data_flag)
 {
   MeshRenderDataUpdateTaskData *task_data = new MeshRenderDataUpdateTaskData(
-      mr, iter_type, data_flag);
+      mr, cache, iter_type, data_flag);
 
   struct TaskNode *task_node = BLI_task_graph_node_create(
       task_graph,
@@ -702,7 +708,7 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
 #endif
 
   struct TaskNode *task_node_mesh_render_data = mesh_extract_render_data_node_create(
-      task_graph, mr, iter_type, data_flag);
+      task_graph, mr, extraction_cache, iter_type, data_flag);
 
   /* Simple heuristic. */
   const bool use_thread = (mr->loop_len + mr->loop_loose_len) > MIM_RANGE_LEN;
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_private.h b/source/blender/draw/intern/draw_cache_extract_mesh_private.h
index 2ece0b4f1db..8c7011dd13c 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh_private.h
+++ b/source/blender/draw/intern/draw_cache_extract_mesh_private.h
@@ -94,6 +94,10 @@ typedef struct MeshRenderData {
   float (*loop_normals)[3];
   float (*poly_normals)[3];
   int *lverts, *ledges;
+  struct {
+    int *tri;
+    int visible_tri_len;
+  } mat_offsets;
 } MeshRenderData;
 
 BLI_INLINE BMFace *bm_original_face_get(const MeshRenderData *mr, int idx)
@@ -238,6 +242,9 @@ MeshRenderData *mesh_render_data_create(Mesh *me,
                                         const eMRIterType iter_type);
 void mesh_render_data_free(MeshRenderData *mr);
 void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_flag);
+void mesh_render_data_update_mat_offsets(MeshRenderData *mr,
+                                         MeshBufferExtractionCache *cache,
+                                         const eMRDataType data_flag);
 void mesh_render_data_update_looptris(MeshRenderData *mr,
                                       const eMRIterType iter_type,
                                       const eMRDataType data_flag);
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 3efd86affca..7e9fe9b3bdb 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
@@ -166,6 +166,110 @@ static void mesh_render_data_ledges_bm(const MeshRenderData *mr,
 
 /** \} */
 
+/* ---------------------------------------------------------------------- */
+/** \name Material Offsets
+ *
+ * Material offsets contains the offset of a material after sorting tris 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,
+                                                 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)
+{
+  if (data_flag & MR_DATA_MAT_OFFSETS) {
+    mesh_render_data_mat_offset_ensure(mr, cache);
+    mesh_render_data_mat_offset_load(mr, cache);
+  }
+}
+
+static void mesh_render_data_mat_offset_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;
+}
+
+static void mesh_render_data_mat_offset_ensure(MeshRenderData *mr,
+                                               MeshBufferExtractionCache *cache)
+{
+  if (cache->mat_offsets.tri) {
+    return;
+  }
+  mesh_render_data_mat_offset_build(mr, cache);
+}
+
+static void mesh_render_data_mat_offset_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__);
+
+  /* Count how many triangles for each material. */
+  if (mr->extract_type == MR_EXTRACT_BMESH) {
+    mesh_render_data_mat_offset_build_bm(mr, cache);
+  }
+  else {
+    mesh_render_data_mat_offset_build_mesh(mr, cache);
+  }
+
+  mesh_render_data_mat_offset_apply_offset(mr, cache);
+}
+
+static void mesh_render_data_mat_offset_build_bm(MeshRenderData *mr,
+                                                 MeshBufferExtractionCache *cache)
+{
+  int *mat_tri_len = cache->mat_offsets.tri;
+  BMIter iter;
+  BMFace *efa;
+  BM_ITER_MESH (efa, &iter, mr->bm, BM_FACES_OF_MESH) {
+    if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+      int mat = min_ii(efa->mat_nr, mr->mat_len - 1);
+      mat_tri_len[mat] += efa->len - 2;
+    }
+  }
+}
+
+static void mesh_render_data_mat_offset_build_mesh(MeshRenderData *mr,
+                                                   MeshBufferExtractionCache *cache)
+{
+  int *mat_tri_len = cache->mat_offsets.tri;
+  const MPoly *mp = mr->mpoly;
+  for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+    if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
+      int mat = min_ii(mp->mat_nr, mr->mat_len - 1);
+      mat_tri_len[mat] += mp->totloop - 2;
+    }
+  }
+}
+
+static void mesh_render_data_mat_offset_apply_offset(MeshRenderData *mr,
+                                                     MeshBufferExtractionCache *cache)
+{
+  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;
+  }
+  cache->mat_offsets.visible_tri_len = ofs;
+}
+
+/** \} */
+
 /* ---------------------------------------------------------------------- */
 /** \name Mesh/BMesh Interface (indirect, partially cached access to complex data).
  * \{ */
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 38f3f4b433a..e4c682e1765 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -725,6 +725,8 @@ static void mesh_buffer_extraction_cache_clear(MeshBufferExtractionCache *extrac
   MEM_SAFE_FREE(extraction_cache->loose_geom.edges);
   extraction_cache->loose_geom.edge_len = 0;
   extraction_cache->loose_geom.vert_len = 0;
+
+  MEM_SAFE_FREE(extraction_cache->mat_offsets.tri);
 }
 
 static void mesh_batch_cache_clear(Mesh *me)
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc
index 70b46481b51..ec968fa33da 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc
@@ -33,7 +33,7 @@ namespace blender::draw {
 
 struct MeshExtract_Tri_Data {
   GPUIndexBufBuilder elb;
-  int *tri_mat_start;
+  const int

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list