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:
authorJeroen Bakker <jbakker>2021-06-15 16:31:17 +0300
committerJeroen Bakker <jeroen@blender.org>2021-06-15 16:31:34 +0300
commit174ed69c1ba8cb8ca7ac39d41922bc203f78326f (patch)
tree547312bc79a8ce1e415f09f6d4966594e223a483 /source/blender/draw
parent7c8b9c7a9aceed5186657fb0ac11cb844f16fec6 (diff)
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
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/intern/draw_cache_extract.h9
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.cc14
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh_private.h7
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh_render_data.c104
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc47
6 files changed, 136 insertions, 47 deletions
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
@@ -167,6 +167,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 *tri_mat_start;
int *tri_mat_end;
};
@@ -43,45 +43,9 @@ static void extract_tris_init(const MeshRenderData *mr,
void *tls_data)
{
MeshExtract_Tri_Data *data = static_cast<MeshExtract_Tri_Data *>(tls_data);
-
- size_t mat_tri_idx_size = sizeof(int) * mr->mat_len;
- data->tri_mat_start = static_cast<int *>(MEM_callocN(mat_tri_idx_size, __func__));
- data->tri_mat_end = static_cast<int *>(MEM_callocN(mat_tri_idx_size, __func__));
-
- int *mat_tri_len = data->tri_mat_start;
- /* Count how many triangle for each material. */
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- 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;
- }
- }
- }
- else {
- 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;
- }
- }
- }
- /* Accumulate triangle lengths per material to have correct offsets. */
- 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;
- }
-
- memcpy(data->tri_mat_end, mat_tri_len, mat_tri_idx_size);
-
- int visible_tri_tot = ofs;
- GPU_indexbuf_init(&data->elb, GPU_PRIM_TRIS, visible_tri_tot, mr->loop_len);
+ data->tri_mat_start = mr->mat_offsets.tri;
+ data->tri_mat_end = static_cast<int *>(MEM_dupallocN(data->tri_mat_start));
+ GPU_indexbuf_init(&data->elb, GPU_PRIM_TRIS, mr->mat_offsets.visible_tri_len, mr->loop_len);
}
static void extract_tris_iter_looptri_bm(const MeshRenderData *mr,
@@ -146,7 +110,6 @@ static void extract_tris_finish(const MeshRenderData *mr,
GPU_indexbuf_create_subrange_in_place(mbc_final->tris_per_mat[i], ibo, start, len);
}
}
- MEM_freeN(data->tri_mat_start);
MEM_freeN(data->tri_mat_end);
}
@@ -157,7 +120,7 @@ constexpr MeshExtract create_extractor_tris()
extractor.iter_looptri_bm = extract_tris_iter_looptri_bm;
extractor.iter_looptri_mesh = extract_tris_iter_looptri_mesh;
extractor.finish = extract_tris_finish;
- extractor.data_type = MR_DATA_NONE;
+ extractor.data_type = MR_DATA_MAT_OFFSETS;
extractor.data_size = sizeof(MeshExtract_Tri_Data);
extractor.use_threading = false;
extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris);