diff options
author | Germano Cavalcante <mano-wii> | 2021-07-20 17:43:38 +0300 |
---|---|---|
committer | Germano Cavalcante <germano.costa@ig.com.br> | 2021-07-21 21:09:43 +0300 |
commit | 178086d5810a0de9e1d95c7fbd6c443cd53af40d (patch) | |
tree | 690553abc005e71ebca93322c82efb42072df77d /source/blender/draw/intern/mesh_extractors | |
parent | 785d87ee42aa1bb09c6ab3282b9fd602f9c14d62 (diff) |
Draw Cache: extract tris in parallel ranges
The `ibo.tris` extraction in multithread is currently only done if the
mesh has only 1 material.
Now we cache a map indicating the index of each polygon after sort and
thus allow the extraction of tris with materials in multithreaded.
As caching is a heavy operation and was already being performed in
multi-thread for triangle offsets, no significant improvements are
expected.
The benefit will be much greater when we can skip updating the cache
while transforming a geometry.
**Profiling:**
||master:|PATCH:
|---|---|---|
|large_mesh_editing_materials:|Average: 13.855380 FPS|Average: 15.525684 FPS
||rdata 9ms iter 36ms (frame 71ms)|rdata 9ms iter 29ms (frame 64ms)
|subdiv_mesh_final_only_materials:|Average: 28.113742 FPS|Average: 28.633599 FPS
||rdata 0ms iter 1ms (frame 36ms)|rdata 0ms iter 1ms (frame 35ms)
1.1x overall speedup
Differential Revision: https://developer.blender.org/D11445
Diffstat (limited to 'source/blender/draw/intern/mesh_extractors')
-rw-r--r-- | source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc | 109 |
1 files changed, 57 insertions, 52 deletions
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 93f71f920eb..3b2da9879c5 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 @@ -27,59 +27,70 @@ namespace blender::draw { +static void extract_tris_mat_task_reduce(void *_userdata_to, void *_userdata_from) +{ + GPUIndexBufBuilder *elb_to = static_cast<GPUIndexBufBuilder *>(_userdata_to); + GPUIndexBufBuilder *elb_from = static_cast<GPUIndexBufBuilder *>(_userdata_from); + GPU_indexbuf_join(elb_to, elb_from); +} + /* ---------------------------------------------------------------------- */ /** \name Extract Triangles Indices (multi material) * \{ */ -struct MeshExtract_Tri_Data { - GPUIndexBufBuilder elb; - const int *tri_mat_start; - int *tri_mat_end; -}; - static void extract_tris_init(const MeshRenderData *mr, struct MeshBatchCache *UNUSED(cache), void *UNUSED(ibo), void *tls_data) { - MeshExtract_Tri_Data *data = static_cast<MeshExtract_Tri_Data *>(tls_data); - 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); + GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(tls_data); + GPU_indexbuf_init(elb, GPU_PRIM_TRIS, mr->poly_sorted.visible_tri_len, mr->loop_len); } -static void extract_tris_iter_looptri_bm(const MeshRenderData *mr, - BMLoop **elt, - const int UNUSED(elt_index), - void *_data) +static void extract_tris_iter_poly_bm(const MeshRenderData *mr, + const BMFace *f, + const int f_index, + void *_data) { - MeshExtract_Tri_Data *data = static_cast<MeshExtract_Tri_Data *>(_data); - const int mat_last = mr->mat_len - 1; + int tri_first_index = mr->poly_sorted.tri_first_index[f_index]; + if (tri_first_index == -1) { + return; + } - if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) { - int *mat_tri_ofs = data->tri_mat_end; - const int mat = min_ii(elt[0]->f->mat_nr, mat_last); - GPU_indexbuf_set_tri_verts(&data->elb, - mat_tri_ofs[mat]++, + GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data); + int tri_first_index_real = poly_to_tri_count(f_index, BM_elem_index_get(f->l_first)); + + struct BMLoop *(*looptris)[3] = mr->edit_bmesh->looptris; + int tri_len = f->len - 2; + for (int offs = 0; offs < tri_len; offs++) { + BMLoop **elt = looptris[tri_first_index_real + offs]; + int tri_index = tri_first_index + offs; + GPU_indexbuf_set_tri_verts(elb, + tri_index, BM_elem_index_get(elt[0]), BM_elem_index_get(elt[1]), BM_elem_index_get(elt[2])); } } -static void extract_tris_iter_looptri_mesh(const MeshRenderData *mr, - const MLoopTri *mlt, - const int UNUSED(elt_index), - void *_data) +static void extract_tris_iter_poly_mesh(const MeshRenderData *mr, + const MPoly *mp, + const int mp_index, + void *_data) { - MeshExtract_Tri_Data *data = static_cast<MeshExtract_Tri_Data *>(_data); - const int mat_last = mr->mat_len - 1; - const MPoly *mp = &mr->mpoly[mlt->poly]; - if (!(mr->use_hide && (mp->flag & ME_HIDE))) { - int *mat_tri_ofs = data->tri_mat_end; - const int mat = min_ii(mp->mat_nr, mat_last); - GPU_indexbuf_set_tri_verts( - &data->elb, mat_tri_ofs[mat]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]); + int tri_first_index = mr->poly_sorted.tri_first_index[mp_index]; + if (tri_first_index == -1) { + return; + } + + GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data); + int tri_first_index_real = poly_to_tri_count(mp_index, mp->loopstart); + + int tri_len = mp->totloop - 2; + for (int offs = 0; offs < tri_len; offs++) { + const MLoopTri *mlt = &mr->mlooptri[tri_first_index_real + offs]; + int tri_index = tri_first_index + offs; + GPU_indexbuf_set_tri_verts(elb, tri_index, mlt->tri[0], mlt->tri[1], mlt->tri[2]); } } @@ -89,40 +100,41 @@ static void extract_tris_finish(const MeshRenderData *mr, void *_data) { GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); - MeshExtract_Tri_Data *data = static_cast<MeshExtract_Tri_Data *>(_data); - GPU_indexbuf_build_in_place(&data->elb, ibo); + GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data); + GPU_indexbuf_build_in_place(elb, ibo); /* Create ibo sub-ranges. Always do this to avoid error when the standard surface batch * is created before the surfaces-per-material. */ if (mr->use_final_mesh && cache->final.tris_per_mat) { MeshBufferCache *mbc_final = &cache->final; + int mat_start = 0; for (int i = 0; i < mr->mat_len; i++) { /* These IBOs have not been queried yet but we create them just in case they are needed * later since they are not tracked by mesh_buffer_cache_create_requested(). */ if (mbc_final->tris_per_mat[i] == nullptr) { mbc_final->tris_per_mat[i] = GPU_indexbuf_calloc(); } + const int mat_tri_len = mr->poly_sorted.mat_tri_len[i]; /* Multiply by 3 because these are triangle indices. */ - const int mat_start = data->tri_mat_start[i]; - const int mat_end = data->tri_mat_end[i]; const int start = mat_start * 3; - const int len = (mat_end - mat_start) * 3; + const int len = mat_tri_len * 3; GPU_indexbuf_create_subrange_in_place(mbc_final->tris_per_mat[i], ibo, start, len); + mat_start += mat_tri_len; } } - MEM_freeN(data->tri_mat_end); } constexpr MeshExtract create_extractor_tris() { MeshExtract extractor = {nullptr}; extractor.init = extract_tris_init; - extractor.iter_looptri_bm = extract_tris_iter_looptri_bm; - extractor.iter_looptri_mesh = extract_tris_iter_looptri_mesh; + extractor.iter_poly_bm = extract_tris_iter_poly_bm; + extractor.iter_poly_mesh = extract_tris_iter_poly_mesh; + extractor.task_reduce = extract_tris_mat_task_reduce; extractor.finish = extract_tris_finish; - extractor.data_type = MR_DATA_MAT_OFFSETS; - extractor.data_size = sizeof(MeshExtract_Tri_Data); - extractor.use_threading = false; + extractor.data_type = MR_DATA_LOOPTRI | MR_DATA_POLYS_SORTED; + extractor.data_size = sizeof(GPUIndexBufBuilder); + extractor.use_threading = true; extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris); return extractor; } @@ -174,13 +186,6 @@ static void extract_tris_single_mat_iter_looptri_mesh(const MeshRenderData *mr, } } -static void extract_tris_single_mat_task_reduce(void *_userdata_to, void *_userdata_from) -{ - GPUIndexBufBuilder *elb_to = static_cast<GPUIndexBufBuilder *>(_userdata_to); - GPUIndexBufBuilder *elb_from = static_cast<GPUIndexBufBuilder *>(_userdata_from); - GPU_indexbuf_join(elb_to, elb_from); -} - static void extract_tris_single_mat_finish(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf, @@ -213,7 +218,7 @@ constexpr MeshExtract create_extractor_tris_single_mat() extractor.init = extract_tris_single_mat_init; extractor.iter_looptri_bm = extract_tris_single_mat_iter_looptri_bm; extractor.iter_looptri_mesh = extract_tris_single_mat_iter_looptri_mesh; - extractor.task_reduce = extract_tris_single_mat_task_reduce; + extractor.task_reduce = extract_tris_mat_task_reduce; extractor.finish = extract_tris_single_mat_finish; extractor.data_type = MR_DATA_NONE; extractor.data_size = sizeof(GPUIndexBufBuilder); |