Changeset View
Changeset View
Standalone View
Standalone View
source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc
| Show All 15 Lines | |||||
| * The Original Code is Copyright (C) 2021 by Blender Foundation. | * The Original Code is Copyright (C) 2021 by Blender Foundation. | ||||
| * All rights reserved. | * All rights reserved. | ||||
| */ | */ | ||||
| /** \file | /** \file | ||||
| * \ingroup draw | * \ingroup draw | ||||
| */ | */ | ||||
| #include "draw_cache_extract_mesh_private.h" | |||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "extract_mesh.h" | |||||
| namespace blender::draw { | 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) | /** \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, | static void extract_tris_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *UNUSED(ibo), | void *UNUSED(ibo), | ||||
| void *tls_data) | void *tls_data) | ||||
| { | { | ||||
| MeshExtract_Tri_Data *data = static_cast<MeshExtract_Tri_Data *>(tls_data); | GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(tls_data); | ||||
| data->tri_mat_start = mr->mat_offsets.tri; | GPU_indexbuf_init(elb, GPU_PRIM_TRIS, mr->poly_sorted.visible_tri_len, mr->loop_len); | ||||
| 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, | static void extract_tris_iter_poly_bm(const MeshRenderData *mr, | ||||
| BMLoop **elt, | const BMFace *f, | ||||
| const int UNUSED(elt_index), | const int f_index, | ||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_Tri_Data *data = static_cast<MeshExtract_Tri_Data *>(_data); | int tri_first_index = mr->poly_sorted.tri_first_index[f_index]; | ||||
| const int mat_last = mr->mat_len - 1; | if (tri_first_index == -1) { | ||||
| return; | |||||
| } | |||||
| if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) { | GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data); | ||||
| int *mat_tri_ofs = data->tri_mat_end; | int tri_first_index_real = poly_to_tri_count(f_index, BM_elem_index_get(f->l_first)); | ||||
| const int mat = min_ii(elt[0]->f->mat_nr, mat_last); | |||||
| GPU_indexbuf_set_tri_verts(&data->elb, | struct BMLoop *(*looptris)[3] = mr->edit_bmesh->looptris; | ||||
| mat_tri_ofs[mat]++, | 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[0]), | ||||
| BM_elem_index_get(elt[1]), | BM_elem_index_get(elt[1]), | ||||
| BM_elem_index_get(elt[2])); | BM_elem_index_get(elt[2])); | ||||
| } | } | ||||
| } | } | ||||
| static void extract_tris_iter_looptri_mesh(const MeshRenderData *mr, | static void extract_tris_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const MLoopTri *mlt, | const MPoly *mp, | ||||
| const int UNUSED(elt_index), | const int mp_index, | ||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_Tri_Data *data = static_cast<MeshExtract_Tri_Data *>(_data); | int tri_first_index = mr->poly_sorted.tri_first_index[mp_index]; | ||||
| const int mat_last = mr->mat_len - 1; | if (tri_first_index == -1) { | ||||
| const MPoly *mp = &mr->mpoly[mlt->poly]; | return; | ||||
| 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); | GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data); | ||||
| GPU_indexbuf_set_tri_verts( | int tri_first_index_real = poly_to_tri_count(mp_index, mp->loopstart); | ||||
| &data->elb, mat_tri_ofs[mat]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]); | |||||
| 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]); | |||||
| } | } | ||||
| } | } | ||||
| static void extract_tris_finish(const MeshRenderData *mr, | static void extract_tris_finish(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *cache, | struct MeshBatchCache *cache, | ||||
| void *buf, | void *buf, | ||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); | GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); | ||||
| MeshExtract_Tri_Data *data = static_cast<MeshExtract_Tri_Data *>(_data); | GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data); | ||||
| GPU_indexbuf_build_in_place(&data->elb, ibo); | GPU_indexbuf_build_in_place(elb, ibo); | ||||
| /* Create ibo sub-ranges. Always do this to avoid error when the standard surface batch | /* Create ibo sub-ranges. Always do this to avoid error when the standard surface batch | ||||
| * is created before the surfaces-per-material. */ | * is created before the surfaces-per-material. */ | ||||
| if (mr->use_final_mesh && cache->final.tris_per_mat) { | if (mr->use_final_mesh && cache->final.tris_per_mat) { | ||||
| MeshBufferCache *mbc_final = &cache->final; | MeshBufferCache *mbc_final = &cache->final; | ||||
| int mat_start = 0; | |||||
| for (int i = 0; i < mr->mat_len; i++) { | 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 | /* 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(). */ | * later since they are not tracked by mesh_buffer_cache_create_requested(). */ | ||||
| if (mbc_final->tris_per_mat[i] == nullptr) { | if (mbc_final->tris_per_mat[i] == nullptr) { | ||||
| mbc_final->tris_per_mat[i] = GPU_indexbuf_calloc(); | 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. */ | /* 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 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); | 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() | constexpr MeshExtract create_extractor_tris() | ||||
| { | { | ||||
| MeshExtract extractor = {nullptr}; | MeshExtract extractor = {nullptr}; | ||||
| extractor.init = extract_tris_init; | extractor.init = extract_tris_init; | ||||
| extractor.iter_looptri_bm = extract_tris_iter_looptri_bm; | extractor.iter_poly_bm = extract_tris_iter_poly_bm; | ||||
| extractor.iter_looptri_mesh = extract_tris_iter_looptri_mesh; | extractor.iter_poly_mesh = extract_tris_iter_poly_mesh; | ||||
| extractor.task_reduce = extract_tris_mat_task_reduce; | |||||
| extractor.finish = extract_tris_finish; | extractor.finish = extract_tris_finish; | ||||
| extractor.data_type = MR_DATA_MAT_OFFSETS; | extractor.data_type = MR_DATA_LOOPTRI | MR_DATA_POLYS_SORTED; | ||||
| extractor.data_size = sizeof(MeshExtract_Tri_Data); | extractor.data_size = sizeof(GPUIndexBufBuilder); | ||||
| extractor.use_threading = false; | extractor.use_threading = true; | ||||
| extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris); | extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris); | ||||
| return extractor; | return extractor; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /** \name Extract Triangles Indices (single material) | /** \name Extract Triangles Indices (single material) | ||||
| * \{ */ | * \{ */ | ||||
| Show All 35 Lines | static void extract_tris_single_mat_iter_looptri_mesh(const MeshRenderData *mr, | ||||
| if (!(mr->use_hide && (mp->flag & ME_HIDE))) { | if (!(mr->use_hide && (mp->flag & ME_HIDE))) { | ||||
| GPU_indexbuf_set_tri_verts(elb, mlt_index, mlt->tri[0], mlt->tri[1], mlt->tri[2]); | GPU_indexbuf_set_tri_verts(elb, mlt_index, mlt->tri[0], mlt->tri[1], mlt->tri[2]); | ||||
| } | } | ||||
| else { | else { | ||||
| GPU_indexbuf_set_tri_restart(elb, mlt_index); | GPU_indexbuf_set_tri_restart(elb, mlt_index); | ||||
| } | } | ||||
| } | } | ||||
| 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, | static void extract_tris_single_mat_finish(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *cache, | struct MeshBatchCache *cache, | ||||
| void *buf, | void *buf, | ||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); | GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); | ||||
| GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data); | GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data); | ||||
| GPU_indexbuf_build_in_place(elb, ibo); | GPU_indexbuf_build_in_place(elb, ibo); | ||||
| Show All 16 Lines | |||||
| } | } | ||||
| constexpr MeshExtract create_extractor_tris_single_mat() | constexpr MeshExtract create_extractor_tris_single_mat() | ||||
| { | { | ||||
| MeshExtract extractor = {nullptr}; | MeshExtract extractor = {nullptr}; | ||||
| extractor.init = extract_tris_single_mat_init; | extractor.init = extract_tris_single_mat_init; | ||||
| extractor.iter_looptri_bm = extract_tris_single_mat_iter_looptri_bm; | extractor.iter_looptri_bm = extract_tris_single_mat_iter_looptri_bm; | ||||
| extractor.iter_looptri_mesh = extract_tris_single_mat_iter_looptri_mesh; | 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.finish = extract_tris_single_mat_finish; | ||||
| extractor.data_type = MR_DATA_NONE; | extractor.data_type = MR_DATA_NONE; | ||||
| extractor.data_size = sizeof(GPUIndexBufBuilder); | extractor.data_size = sizeof(GPUIndexBufBuilder); | ||||
| extractor.use_threading = true; | extractor.use_threading = true; | ||||
| extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris); | extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris); | ||||
| return extractor; | return extractor; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| } // namespace blender::draw | } // namespace blender::draw | ||||
| extern "C" { | extern "C" { | ||||
| const MeshExtract extract_tris = blender::draw::create_extractor_tris(); | const MeshExtract extract_tris = blender::draw::create_extractor_tris(); | ||||
| const MeshExtract extract_tris_single_mat = blender::draw::create_extractor_tris_single_mat(); | const MeshExtract extract_tris_single_mat = blender::draw::create_extractor_tris_single_mat(); | ||||
| } | } | ||||