diff options
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); |