diff options
13 files changed, 626 insertions, 1193 deletions
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index 6b5877e6759..c6303d541b3 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -50,7 +50,7 @@ # include "PIL_time_utildefines.h" #endif -#define CHUNK_SIZE 8192 +#define CHUNK_SIZE 1024 namespace blender::draw { @@ -65,26 +65,12 @@ struct ExtractorRunData { const MeshExtract *extractor; /* During iteration the VBO/IBO that is being build. */ void *buffer = nullptr; - /* User data during iteration. Created in MeshExtract.init and passed along to other MeshExtract - * functions. */ - void *user_data = nullptr; - std::optional<Array<void *>> task_user_datas; + uint32_t data_offset = 0; ExtractorRunData(const MeshExtract *extractor) : extractor(extractor) { } - void init_task_user_datas(const TaskLen task_len) - { - task_user_datas = Array<void *>(task_len); - } - - void *&operator[](const TaskId task_id) - { - BLI_assert(task_user_datas); - return (*task_user_datas)[task_id]; - } - #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("DRAW:ExtractorRunData") #endif @@ -157,6 +143,16 @@ class ExtractorRunDatas : public Vector<ExtractorRunData> { return data_type; } + size_t data_size_total() + { + size_t data_size = 0; + for (const ExtractorRunData &data : *this) { + const MeshExtract *extractor = data.extractor; + data_size += extractor->data_size; + } + return data_size; + } + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("DRAW:ExtractorRunDatas") #endif @@ -165,446 +161,334 @@ class ExtractorRunDatas : public Vector<ExtractorRunData> { /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Extract +/** \name ExtractTaskData + * \{ */ +struct ExtractTaskData { + const MeshRenderData *mr = nullptr; + MeshBatchCache *cache = nullptr; + ExtractorRunDatas *extractors = nullptr; + MeshBufferCache *mbc = nullptr; + + eMRIterType iter_type; + bool use_threading = false; + + ExtractTaskData(const MeshRenderData *mr, + struct MeshBatchCache *cache, + ExtractorRunDatas *extractors, + MeshBufferCache *mbc, + const bool use_threading) + : mr(mr), cache(cache), extractors(extractors), mbc(mbc), use_threading(use_threading) + { + iter_type = extractors->iter_types(); + }; + + ExtractTaskData(const ExtractTaskData &src) = default; + + ~ExtractTaskData() + { + delete extractors; + } + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("DRW:ExtractTaskData") +#endif +}; + +static void extract_task_data_free(void *data) +{ + ExtractTaskData *task_data = static_cast<ExtractTaskData *>(data); + delete task_data; +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Extract Init and Finish * \{ */ BLI_INLINE void extract_init(const MeshRenderData *mr, struct MeshBatchCache *cache, ExtractorRunDatas &extractors, - MeshBufferCache *mbc) + MeshBufferCache *mbc, + void *data_stack) { - /* Multi thread. */ + uint32_t data_offset = 0; for (ExtractorRunData &run_data : extractors) { const MeshExtract *extractor = run_data.extractor; run_data.buffer = mesh_extract_buffer_get(extractor, mbc); - run_data.user_data = extractor->init(mr, cache, run_data.buffer); + run_data.data_offset = data_offset; + extractor->init(mr, cache, run_data.buffer, POINTER_OFFSET(data_stack, data_offset)); + data_offset += (uint32_t)extractor->data_size; } } -BLI_INLINE void extract_iter_looptri_bm(const MeshRenderData *mr, - const ExtractTriBMesh_Params *params, - const ExtractorRunDatas &all_extractors, - const TaskId task_id) +BLI_INLINE void extract_finish(const MeshRenderData *mr, + struct MeshBatchCache *cache, + const ExtractorRunDatas &extractors, + void *data_stack) { - ExtractorRunDatas extractors; - all_extractors.filter_into(extractors, MR_ITER_LOOPTRI); - - EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, elt_index, params) - { - for (ExtractorRunData &run_data : extractors) { - run_data.extractor->iter_looptri_bm(mr, elt, elt_index, run_data[task_id]); + for (const ExtractorRunData &run_data : extractors) { + const MeshExtract *extractor = run_data.extractor; + if (extractor->finish) { + extractor->finish( + mr, cache, run_data.buffer, POINTER_OFFSET(data_stack, run_data.data_offset)); } } - EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END; } -BLI_INLINE void extract_iter_looptri_mesh(const MeshRenderData *mr, - const ExtractTriMesh_Params *params, - const ExtractorRunDatas &all_extractors, - const TaskId task_id) -{ +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Extract In Parallel Ranges + * \{ */ + +struct ExtractorIterData { ExtractorRunDatas extractors; - all_extractors.filter_into(extractors, MR_ITER_LOOPTRI); + const MeshRenderData *mr = nullptr; + const void *elems = nullptr; + const int *loose_elems = nullptr; - EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, mlt_index, params) - { - for (ExtractorRunData &run_data : extractors) { - run_data.extractor->iter_looptri_mesh(mr, mlt, mlt_index, run_data[task_id]); +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("DRW:MeshRenderDataUpdateTaskData") +#endif +}; + +static void extract_task_reduce(const void *__restrict userdata, + void *__restrict chunk_to, + void *__restrict chunk_from) +{ + const ExtractorIterData *data = static_cast<const ExtractorIterData *>(userdata); + for (const ExtractorRunData &run_data : data->extractors) { + const MeshExtract *extractor = run_data.extractor; + if (extractor->task_reduce) { + extractor->task_reduce(POINTER_OFFSET(chunk_to, run_data.data_offset), + POINTER_OFFSET(chunk_from, run_data.data_offset)); } } - EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END; } -BLI_INLINE void extract_iter_poly_bm(const MeshRenderData *mr, - const ExtractPolyBMesh_Params *params, - const ExtractorRunDatas &all_extractors, - const TaskId task_id) +static void extract_range_iter_looptri_bm(void *__restrict userdata, + const int iter, + const TaskParallelTLS *__restrict tls) { - ExtractorRunDatas extractors; - all_extractors.filter_into(extractors, MR_ITER_POLY); - - EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr) - { - for (ExtractorRunData &run_data : extractors) { - run_data.extractor->iter_poly_bm(mr, f, f_index, run_data[task_id]); - } + const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata); + void *extract_data = tls->userdata_chunk; + const MeshRenderData *mr = data->mr; + BMLoop **elt = ((BMLoop * (*)[3]) data->elems)[iter]; + for (const ExtractorRunData &run_data : data->extractors) { + run_data.extractor->iter_looptri_bm( + mr, elt, iter, POINTER_OFFSET(extract_data, run_data.data_offset)); } - EXTRACT_POLY_FOREACH_BM_END; } -BLI_INLINE void extract_iter_poly_mesh(const MeshRenderData *mr, - const ExtractPolyMesh_Params *params, - const ExtractorRunDatas &all_extractors, - const TaskId task_id) +static void extract_range_iter_looptri_mesh(void *__restrict userdata, + const int iter, + const TaskParallelTLS *__restrict tls) { - ExtractorRunDatas extractors; - all_extractors.filter_into(extractors, MR_ITER_POLY); + void *extract_data = tls->userdata_chunk; - EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) - { - for (ExtractorRunData &run_data : extractors) { - run_data.extractor->iter_poly_mesh(mr, mp, mp_index, run_data[task_id]); - } + const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata); + const MeshRenderData *mr = data->mr; + const MLoopTri *mlt = &((const MLoopTri *)data->elems)[iter]; + for (const ExtractorRunData &run_data : data->extractors) { + run_data.extractor->iter_looptri_mesh( + mr, mlt, iter, POINTER_OFFSET(extract_data, run_data.data_offset)); } - EXTRACT_POLY_FOREACH_MESH_END; } -BLI_INLINE void extract_iter_ledge_bm(const MeshRenderData *mr, - const ExtractLEdgeBMesh_Params *params, - const ExtractorRunDatas &all_extractors, - const TaskId task_id) +static void extract_range_iter_poly_bm(void *__restrict userdata, + const int iter, + const TaskParallelTLS *__restrict tls) { - ExtractorRunDatas extractors; - all_extractors.filter_into(extractors, MR_ITER_LEDGE); + void *extract_data = tls->userdata_chunk; - EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) - { - for (ExtractorRunData &run_data : extractors) { - run_data.extractor->iter_ledge_bm(mr, eed, ledge_index, run_data[task_id]); - } + const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata); + const MeshRenderData *mr = data->mr; + const BMFace *f = ((const BMFace **)data->elems)[iter]; + for (const ExtractorRunData &run_data : data->extractors) { + run_data.extractor->iter_poly_bm( + mr, f, iter, POINTER_OFFSET(extract_data, run_data.data_offset)); } - EXTRACT_LEDGE_FOREACH_BM_END; } -BLI_INLINE void extract_iter_ledge_mesh(const MeshRenderData *mr, - const ExtractLEdgeMesh_Params *params, - const ExtractorRunDatas &all_extractors, - const TaskId task_id) +static void extract_range_iter_poly_mesh(void *__restrict userdata, + const int iter, + const TaskParallelTLS *__restrict tls) { - ExtractorRunDatas extractors; - all_extractors.filter_into(extractors, MR_ITER_LEDGE); + void *extract_data = tls->userdata_chunk; - EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) - { - for (ExtractorRunData &run_data : extractors) { - run_data.extractor->iter_ledge_mesh(mr, med, ledge_index, run_data[task_id]); - } + const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata); + const MeshRenderData *mr = data->mr; + const MPoly *mp = &((const MPoly *)data->elems)[iter]; + for (const ExtractorRunData &run_data : data->extractors) { + run_data.extractor->iter_poly_mesh( + mr, mp, iter, POINTER_OFFSET(extract_data, run_data.data_offset)); } - EXTRACT_LEDGE_FOREACH_MESH_END; } -BLI_INLINE void extract_iter_lvert_bm(const MeshRenderData *mr, - const ExtractLVertBMesh_Params *params, - const ExtractorRunDatas &all_extractors, - const TaskId task_id) +static void extract_range_iter_ledge_bm(void *__restrict userdata, + const int iter, + const TaskParallelTLS *__restrict tls) { - ExtractorRunDatas extractors; - all_extractors.filter_into(extractors, MR_ITER_LVERT); + void *extract_data = tls->userdata_chunk; - EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params) - { - for (ExtractorRunData &run_data : extractors) { - run_data.extractor->iter_lvert_bm(mr, eve, lvert_index, run_data[task_id]); - } + const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata); + const MeshRenderData *mr = data->mr; + const int ledge_index = data->loose_elems[iter]; + const BMEdge *eed = ((const BMEdge **)data->elems)[ledge_index]; + for (const ExtractorRunData &run_data : data->extractors) { + run_data.extractor->iter_ledge_bm( + mr, eed, iter, POINTER_OFFSET(extract_data, run_data.data_offset)); } - EXTRACT_LVERT_FOREACH_BM_END; } -BLI_INLINE void extract_iter_lvert_mesh(const MeshRenderData *mr, - const ExtractLVertMesh_Params *params, - const ExtractorRunDatas &all_extractors, - const TaskId task_id) +static void extract_range_iter_ledge_mesh(void *__restrict userdata, + const int iter, + const TaskParallelTLS *__restrict tls) { - ExtractorRunDatas extractors; - all_extractors.filter_into(extractors, MR_ITER_LVERT); + void *extract_data = tls->userdata_chunk; - EXTRACT_LVERT_FOREACH_MESH_BEGIN(mv, lvert_index, params, mr) - { - for (ExtractorRunData &run_data : extractors) { - run_data.extractor->iter_lvert_mesh(mr, mv, lvert_index, run_data[task_id]); - } + const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata); + const MeshRenderData *mr = data->mr; + const int ledge_index = data->loose_elems[iter]; + const MEdge *med = &((const MEdge *)data->elems)[ledge_index]; + for (const ExtractorRunData &run_data : data->extractors) { + run_data.extractor->iter_ledge_mesh( + mr, med, iter, POINTER_OFFSET(extract_data, run_data.data_offset)); } - EXTRACT_LVERT_FOREACH_MESH_END; } -BLI_INLINE void extract_finish(const MeshRenderData *mr, - struct MeshBatchCache *cache, - const ExtractorRunDatas &extractors) +static void extract_range_iter_lvert_bm(void *__restrict userdata, + const int iter, + const TaskParallelTLS *__restrict tls) { - for (const ExtractorRunData &run_data : extractors) { - const MeshExtract *extractor = run_data.extractor; - if (extractor->finish) { - extractor->finish(mr, cache, run_data.buffer, run_data.user_data); - } + void *extract_data = tls->userdata_chunk; + + const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata); + const MeshRenderData *mr = data->mr; + const int lvert_index = data->loose_elems[iter]; + const BMVert *eve = ((const BMVert **)data->elems)[lvert_index]; + for (const ExtractorRunData &run_data : data->extractors) { + run_data.extractor->iter_lvert_bm( + mr, eve, iter, POINTER_OFFSET(extract_data, run_data.data_offset)); } } -BLI_INLINE void extract_task_init(ExtractorRunDatas &extractors, const TaskLen task_len) +static void extract_range_iter_lvert_mesh(void *__restrict userdata, + const int iter, + const TaskParallelTLS *__restrict tls) { - for (ExtractorRunData &run_data : extractors) { - run_data.init_task_user_datas(task_len); - const MeshExtract *extractor = run_data.extractor; - for (TaskId task_id = 0; task_id < task_len; task_id++) { - void *user_task_data = run_data.user_data; - if (extractor->task_init) { - user_task_data = extractor->task_init(run_data.user_data); - } - run_data[task_id] = user_task_data; - } + void *extract_data = tls->userdata_chunk; + + const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata); + const MeshRenderData *mr = data->mr; + const int lvert_index = data->loose_elems[iter]; + const MVert *mv = &((const MVert *)data->elems)[lvert_index]; + for (const ExtractorRunData &run_data : data->extractors) { + run_data.extractor->iter_lvert_mesh( + mr, mv, iter, POINTER_OFFSET(extract_data, run_data.data_offset)); } } -BLI_INLINE void extract_task_finish(ExtractorRunDatas &extractors, const TaskLen task_len) +BLI_INLINE void extract_task_range_run_iter(const MeshRenderData *mr, + ExtractorRunDatas *extractors, + const eMRIterType iter_type, + bool is_mesh, + TaskParallelSettings *settings) { - for (ExtractorRunData &run_data : extractors) { - const MeshExtract *extractor = run_data.extractor; - if (extractor->task_finish) { - for (TaskId task_id = 0; task_id < task_len; task_id++) { - void *task_user_data = run_data[task_id]; - extractor->task_finish(run_data.user_data, task_user_data); - run_data[task_id] = nullptr; - } - } + ExtractorIterData range_data; + range_data.mr = mr; + + TaskParallelRangeFunc func; + int stop; + switch (iter_type) { + case MR_ITER_LOOPTRI: + range_data.elems = is_mesh ? mr->mlooptri : (void *)mr->edit_bmesh->looptris; + func = is_mesh ? extract_range_iter_looptri_mesh : extract_range_iter_looptri_bm; + stop = mr->tri_len; + break; + case MR_ITER_POLY: + range_data.elems = is_mesh ? mr->mpoly : (void *)mr->bm->ftable; + func = is_mesh ? extract_range_iter_poly_mesh : extract_range_iter_poly_bm; + stop = mr->poly_len; + break; + case MR_ITER_LEDGE: + range_data.loose_elems = mr->ledges; + range_data.elems = is_mesh ? mr->medge : (void *)mr->bm->etable; + func = is_mesh ? extract_range_iter_ledge_mesh : extract_range_iter_ledge_bm; + stop = mr->edge_loose_len; + break; + case MR_ITER_LVERT: + range_data.loose_elems = mr->lverts; + range_data.elems = is_mesh ? mr->mvert : (void *)mr->bm->vtable; + func = is_mesh ? extract_range_iter_lvert_mesh : extract_range_iter_lvert_bm; + stop = mr->vert_loose_len; + break; + default: + BLI_assert(false); + return; } + + extractors->filter_into(range_data.extractors, iter_type); + BLI_task_parallel_range(0, stop, &range_data, func, settings); } -/* Single Thread. */ -BLI_INLINE void extract_run_single_threaded(const MeshRenderData *mr, - struct MeshBatchCache *cache, - ExtractorRunDatas &extractors, - eMRIterType iter_type, - MeshBufferCache *mbc) +static void extract_task_range_run(void *__restrict taskdata) { - const TaskLen task_len = 1; - const TaskId task_id = 0; + ExtractTaskData *data = (ExtractTaskData *)taskdata; + const eMRIterType iter_type = data->iter_type; + const bool is_mesh = data->mr->extract_type != MR_EXTRACT_BMESH; + + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.func_reduce = extract_task_reduce; + settings.min_iter_per_thread = CHUNK_SIZE; + settings.use_threading = data->use_threading; - extract_init(mr, cache, extractors, mbc); - extract_task_init(extractors, task_len); + size_t chunk_size = data->extractors->data_size_total(); + char *chunk = new char[chunk_size]; + extract_init(data->mr, data->cache, *data->extractors, data->mbc, (void *)chunk); + + settings.userdata_chunk = chunk; + settings.userdata_chunk_size = chunk_size; - bool is_mesh = mr->extract_type != MR_EXTRACT_BMESH; if (iter_type & MR_ITER_LOOPTRI) { - if (is_mesh) { - ExtractTriMesh_Params params; - params.mlooptri = mr->mlooptri; - params.tri_range[0] = 0; - params.tri_range[1] = mr->tri_len; - extract_iter_looptri_mesh(mr, ¶ms, extractors, task_id); - } - else { - ExtractTriBMesh_Params params; - params.looptris = mr->edit_bmesh->looptris; - params.tri_range[0] = 0; - params.tri_range[1] = mr->tri_len; - extract_iter_looptri_bm(mr, ¶ms, extractors, task_id); - } + extract_task_range_run_iter(data->mr, data->extractors, MR_ITER_LOOPTRI, is_mesh, &settings); } if (iter_type & MR_ITER_POLY) { - if (is_mesh) { - ExtractPolyMesh_Params params; - params.poly_range[0] = 0; - params.poly_range[1] = mr->poly_len; - extract_iter_poly_mesh(mr, ¶ms, extractors, task_id); - } - else { - ExtractPolyBMesh_Params params; - params.poly_range[0] = 0; - params.poly_range[1] = mr->poly_len; - extract_iter_poly_bm(mr, ¶ms, extractors, task_id); - } + extract_task_range_run_iter(data->mr, data->extractors, MR_ITER_POLY, is_mesh, &settings); } if (iter_type & MR_ITER_LEDGE) { - if (is_mesh) { - ExtractLEdgeMesh_Params params; - params.ledge = mr->ledges; - params.ledge_range[0] = 0; - params.ledge_range[1] = mr->edge_loose_len; - extract_iter_ledge_mesh(mr, ¶ms, extractors, task_id); - } - else { - ExtractLEdgeBMesh_Params params; - params.ledge = mr->ledges; - params.ledge_range[0] = 0; - params.ledge_range[1] = mr->edge_loose_len; - extract_iter_ledge_bm(mr, ¶ms, extractors, task_id); - } + extract_task_range_run_iter(data->mr, data->extractors, MR_ITER_LEDGE, is_mesh, &settings); } if (iter_type & MR_ITER_LVERT) { - if (is_mesh) { - ExtractLVertMesh_Params params; - params.lvert = mr->lverts; - params.lvert_range[0] = 0; - params.lvert_range[1] = mr->vert_loose_len; - extract_iter_lvert_mesh(mr, ¶ms, extractors, task_id); - } - else { - ExtractLVertBMesh_Params params; - params.lvert = mr->lverts; - params.lvert_range[0] = 0; - params.lvert_range[1] = mr->vert_loose_len; - extract_iter_lvert_bm(mr, ¶ms, extractors, task_id); - } + extract_task_range_run_iter(data->mr, data->extractors, MR_ITER_LVERT, is_mesh, &settings); } - extract_task_finish(extractors, task_len); - extract_finish(mr, cache, extractors); + + extract_finish(data->mr, data->cache, *data->extractors, (void *)chunk); + delete[] chunk; } /** \} */ /* ---------------------------------------------------------------------- */ -/** \name ExtractTaskData +/** \name Extract Single Thread * \{ */ -struct ExtractTaskData { - const MeshRenderData *mr = nullptr; - MeshBatchCache *cache = nullptr; - /* #UserData is shared between the iterations as it holds counters to detect if the - * extraction is finished. To make sure the duplication of the user_data does not create a new - * instance of the counters we allocate the user_data in its own container. - * - * This structure makes sure that when extract_init is called, that the user data of all - * iterations are updated. */ - ExtractorRunDatas *extractors = nullptr; - MeshBufferCache *mbc = nullptr; - int32_t *task_counter = nullptr; - - /* Total number of tasks that are created for multi threaded extraction. - * (= 1 for single threaded extractors). */ - uint task_len; - /* Task id of the extraction task. Must never exceed task_len. (= 0 for single threaded - * extractors). */ - uint task_id = 0; - - eMRIterType iter_type; - int start = 0; - int end = INT_MAX; - /** Decremented each time a task is finished. */ - - ExtractTaskData(const MeshRenderData *mr, - struct MeshBatchCache *cache, - ExtractorRunDatas *extractors, - MeshBufferCache *mbc, - int32_t *task_counter, - const uint task_len) - : mr(mr), - cache(cache), - extractors(extractors), - mbc(mbc), - task_counter(task_counter), - task_len(task_len) - { - iter_type = extractors->iter_types(); - }; - - ExtractTaskData(const ExtractTaskData &src) = default; - - ~ExtractTaskData() - { - delete extractors; - } - -#ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("DRW:ExtractTaskData") -#endif -}; - -static void extract_task_data_free(void *data) -{ - ExtractTaskData *task_data = static_cast<ExtractTaskData *>(data); - delete task_data; -} - -static void extract_task_data_free_ex(void *data) -{ - ExtractTaskData *task_data = static_cast<ExtractTaskData *>(data); - task_data->extractors = nullptr; - delete task_data; -} - -BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr, - const eMRIterType iter_type, - int start, - int end, - ExtractorRunDatas &extractors, - const TaskId task_id) -{ - switch (mr->extract_type) { - case MR_EXTRACT_BMESH: - if (iter_type & MR_ITER_LOOPTRI) { - ExtractTriBMesh_Params params; - params.looptris = mr->edit_bmesh->looptris; - params.tri_range[0] = start; - params.tri_range[1] = min_ii(mr->tri_len, end); - extract_iter_looptri_bm(mr, ¶ms, extractors, task_id); - } - if (iter_type & MR_ITER_POLY) { - ExtractPolyBMesh_Params params; - params.poly_range[0] = start; - params.poly_range[1] = min_ii(mr->poly_len, end); - extract_iter_poly_bm(mr, ¶ms, extractors, task_id); - } - if (iter_type & MR_ITER_LEDGE) { - ExtractLEdgeBMesh_Params params; - params.ledge = mr->ledges; - params.ledge_range[0] = start; - params.ledge_range[1] = min_ii(mr->edge_loose_len, end); - extract_iter_ledge_bm(mr, ¶ms, extractors, task_id); - } - if (iter_type & MR_ITER_LVERT) { - ExtractLVertBMesh_Params params; - params.lvert = mr->lverts; - params.lvert_range[0] = start; - params.lvert_range[1] = min_ii(mr->vert_loose_len, end); - extract_iter_lvert_bm(mr, ¶ms, extractors, task_id); - } - break; - case MR_EXTRACT_MAPPED: - case MR_EXTRACT_MESH: - if (iter_type & MR_ITER_LOOPTRI) { - ExtractTriMesh_Params params; - params.mlooptri = mr->mlooptri; - params.tri_range[0] = start; - params.tri_range[1] = min_ii(mr->tri_len, end); - extract_iter_looptri_mesh(mr, ¶ms, extractors, task_id); - } - if (iter_type & MR_ITER_POLY) { - ExtractPolyMesh_Params params; - params.poly_range[0] = start; - params.poly_range[1] = min_ii(mr->poly_len, end); - extract_iter_poly_mesh(mr, ¶ms, extractors, task_id); - } - if (iter_type & MR_ITER_LEDGE) { - ExtractLEdgeMesh_Params params; - params.ledge = mr->ledges; - params.ledge_range[0] = start; - params.ledge_range[1] = min_ii(mr->edge_loose_len, end); - extract_iter_ledge_mesh(mr, ¶ms, extractors, task_id); - } - if (iter_type & MR_ITER_LVERT) { - ExtractLVertMesh_Params params; - params.lvert = mr->lverts; - params.lvert_range[0] = start; - params.lvert_range[1] = min_ii(mr->vert_loose_len, end); - extract_iter_lvert_mesh(mr, ¶ms, extractors, task_id); - } - break; - } -} - -static void extract_task_init(ExtractTaskData *data) +static struct TaskNode *extract_task_node_create(struct TaskGraph *task_graph, + const MeshRenderData *mr, + MeshBatchCache *cache, + ExtractorRunDatas *extractors, + MeshBufferCache *mbc, + const bool use_threading) { - extract_init(data->mr, data->cache, *data->extractors, data->mbc); - extract_task_init(*data->extractors, data->task_len); -} - -static void extract_task_run(void *__restrict taskdata) -{ - ExtractTaskData *data = (ExtractTaskData *)taskdata; - mesh_extract_iter( - data->mr, data->iter_type, data->start, data->end, *data->extractors, data->task_id); - - /* If this is the last task, we do the finish function. */ - int remainin_tasks = atomic_sub_and_fetch_int32(data->task_counter, 1); - if (remainin_tasks == 0) { - extract_task_finish(*data->extractors, data->task_len); - extract_finish(data->mr, data->cache, *data->extractors); - } -} - -static void extract_task_init_and_run(void *__restrict taskdata) -{ - ExtractTaskData *data = (ExtractTaskData *)taskdata; - extract_run_single_threaded( - data->mr, data->cache, *data->extractors, data->iter_type, data->mbc); + ExtractTaskData *taskdata = new ExtractTaskData(mr, cache, extractors, mbc, use_threading); + struct TaskNode *task_node = BLI_task_graph_node_create( + task_graph, + extract_task_range_run, + taskdata, + (TaskGraphNodeFreeFunction)extract_task_data_free); + return task_node; } /** \} */ @@ -670,153 +554,9 @@ static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *t /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Task Node - Extract Single Threaded - * \{ */ - -static struct TaskNode *extract_single_threaded_task_node_create(struct TaskGraph *task_graph, - ExtractTaskData *task_data) -{ - struct TaskNode *task_node = BLI_task_graph_node_create( - task_graph, - extract_task_init_and_run, - task_data, - (TaskGraphNodeFreeFunction)extract_task_data_free); - return task_node; -} - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Task Node - UserData Initializer - * \{ */ -struct UserDataInitTaskData { - ExtractTaskData *td = nullptr; - int32_t task_counter = 0; - - ~UserDataInitTaskData() - { - extract_task_data_free(td); - } - -#ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("DRW:UserDataInitTaskData") -#endif -}; - -static void user_data_init_task_data_free(void *data) -{ - UserDataInitTaskData *taskdata = static_cast<UserDataInitTaskData *>(data); - delete taskdata; -} - -static void user_data_init_task_data_exec(void *__restrict task_data) -{ - UserDataInitTaskData *extract_task_data = static_cast<UserDataInitTaskData *>(task_data); - ExtractTaskData *taskdata_base = extract_task_data->td; - extract_task_init(taskdata_base); -} - -static struct TaskNode *user_data_init_task_node_create(struct TaskGraph *task_graph, - UserDataInitTaskData *task_data) -{ - struct TaskNode *task_node = BLI_task_graph_node_create( - task_graph, - user_data_init_task_data_exec, - task_data, - (TaskGraphNodeFreeFunction)user_data_init_task_data_free); - return task_node; -} - -/** \} */ - -/* ---------------------------------------------------------------------- */ /** \name Extract Loop * \{ */ -static void extract_range_task_create(struct TaskGraph *task_graph, - struct TaskNode *task_node_user_data_init, - ExtractTaskData *taskdata, - const eMRIterType type, - int start, - int length) -{ - taskdata = new ExtractTaskData(*taskdata); - taskdata->task_id = atomic_fetch_and_add_int32(taskdata->task_counter, 1); - BLI_assert(taskdata->task_id < taskdata->task_len); - taskdata->iter_type = type; - taskdata->start = start; - taskdata->end = start + length; - struct TaskNode *task_node = BLI_task_graph_node_create( - task_graph, extract_task_run, taskdata, extract_task_data_free_ex); - BLI_task_graph_edge_create(task_node_user_data_init, task_node); -} - -static int extract_range_task_num_elements_get(const MeshRenderData *mr, - const eMRIterType iter_type) -{ - /* Divide task into sensible chunks. */ - int iter_len = 0; - if (iter_type & MR_ITER_LOOPTRI) { - iter_len += mr->tri_len; - } - if (iter_type & MR_ITER_POLY) { - iter_len += mr->poly_len; - } - if (iter_type & MR_ITER_LEDGE) { - iter_len += mr->edge_loose_len; - } - if (iter_type & MR_ITER_LVERT) { - iter_len += mr->vert_loose_len; - } - return iter_len; -} - -static int extract_range_task_chunk_size_get(const MeshRenderData *mr, - const eMRIterType iter_type, - const int num_threads) -{ - /* Divide task into sensible chunks. */ - const int num_elements = extract_range_task_num_elements_get(mr, iter_type); - int range_len = (num_elements + num_threads) / num_threads; - CLAMP_MIN(range_len, CHUNK_SIZE); - return range_len; -} - -static void extract_task_in_ranges_create(struct TaskGraph *task_graph, - struct TaskNode *task_node_user_data_init, - ExtractTaskData *taskdata_base, - const int num_threads) -{ - const MeshRenderData *mr = taskdata_base->mr; - const int range_len = extract_range_task_chunk_size_get( - mr, taskdata_base->iter_type, num_threads); - - if (taskdata_base->iter_type & MR_ITER_LOOPTRI) { - for (int i = 0; i < mr->tri_len; i += range_len) { - extract_range_task_create( - task_graph, task_node_user_data_init, taskdata_base, MR_ITER_LOOPTRI, i, range_len); - } - } - if (taskdata_base->iter_type & MR_ITER_POLY) { - for (int i = 0; i < mr->poly_len; i += range_len) { - extract_range_task_create( - task_graph, task_node_user_data_init, taskdata_base, MR_ITER_POLY, i, range_len); - } - } - if (taskdata_base->iter_type & MR_ITER_LEDGE) { - for (int i = 0; i < mr->edge_loose_len; i += range_len) { - extract_range_task_create( - task_graph, task_node_user_data_init, taskdata_base, MR_ITER_LEDGE, i, range_len); - } - } - if (taskdata_base->iter_type & MR_ITER_LVERT) { - for (int i = 0; i < mr->vert_loose_len; i += range_len) { - extract_range_task_create( - task_graph, task_node_user_data_init, taskdata_base, MR_ITER_LVERT, i, range_len); - } - } -} - static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, MeshBatchCache *cache, MeshBufferCache *mbc, @@ -968,20 +708,16 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, const bool use_thread = (mr->loop_len + mr->loop_loose_len) > CHUNK_SIZE; if (use_thread) { - uint single_threaded_extractors_len = 0; - /* First run the requested extractors that do not support asynchronous ranges. */ for (const ExtractorRunData &run_data : extractors) { const MeshExtract *extractor = run_data.extractor; if (!extractor->use_threading) { ExtractorRunDatas *single_threaded_extractors = new ExtractorRunDatas(); single_threaded_extractors->append(extractor); - ExtractTaskData *taskdata = new ExtractTaskData( - mr, cache, single_threaded_extractors, mbc, nullptr, 1); - struct TaskNode *task_node = extract_single_threaded_task_node_create(task_graph, - taskdata); + struct TaskNode *task_node = extract_task_node_create( + task_graph, mr, cache, single_threaded_extractors, mbc, false); + BLI_task_graph_edge_create(task_node_mesh_render_data, task_node); - single_threaded_extractors_len++; } } @@ -989,31 +725,10 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, ExtractorRunDatas *multi_threaded_extractors = new ExtractorRunDatas(); extractors.filter_threaded_extractors_into(*multi_threaded_extractors); if (!multi_threaded_extractors->is_empty()) { - /* - * Determine the number of thread to use for multithreading. - * Thread can be used for single threaded tasks. These typically take longer to execute so - * fill the rest of the threads for range operations. - */ - int num_threads = BLI_task_scheduler_num_threads(); - num_threads -= single_threaded_extractors_len % num_threads; - const int max_multithreaded_task_len = multi_threaded_extractors->iter_types_len() + - num_threads; - - UserDataInitTaskData *user_data_init_task_data = new UserDataInitTaskData(); - struct TaskNode *task_node_user_data_init = user_data_init_task_node_create( - task_graph, user_data_init_task_data); - - user_data_init_task_data->td = new ExtractTaskData(mr, - cache, - multi_threaded_extractors, - mbc, - &user_data_init_task_data->task_counter, - max_multithreaded_task_len); - - extract_task_in_ranges_create( - task_graph, task_node_user_data_init, user_data_init_task_data->td, num_threads); - - BLI_task_graph_edge_create(task_node_mesh_render_data, task_node_user_data_init); + struct TaskNode *task_node = extract_task_node_create( + task_graph, mr, cache, multi_threaded_extractors, mbc, true); + + BLI_task_graph_edge_create(task_node_mesh_render_data, task_node); } else { /* No tasks created freeing extractors list. */ @@ -1023,9 +738,9 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, else { /* Run all requests on the same thread. */ ExtractorRunDatas *extractors_copy = new ExtractorRunDatas(extractors); - ExtractTaskData *taskdata = new ExtractTaskData(mr, cache, extractors_copy, mbc, nullptr, 1); + struct TaskNode *task_node = extract_task_node_create( + task_graph, mr, cache, extractors_copy, mbc, false); - struct TaskNode *task_node = extract_single_threaded_task_node_create(task_graph, taskdata); BLI_task_graph_edge_create(task_node_mesh_render_data, task_node); } diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c b/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c index 3cac391c42d..3a8edcad463 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c @@ -130,12 +130,13 @@ typedef struct PosNorLoop { typedef struct MeshExtract_PosNor_Data { PosNorLoop *vbo_data; - GPUNormal normals[]; + GPUNormal *normals; } MeshExtract_PosNor_Data; -static void *extract_pos_nor_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_pos_nor_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -149,9 +150,9 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); /* Pack normals per vert, reduce amount of computation. */ - size_t packed_nor_len = sizeof(GPUNormal) * mr->vert_len; - MeshExtract_PosNor_Data *data = MEM_mallocN(sizeof(*data) + packed_nor_len, __func__); + MeshExtract_PosNor_Data *data = tls_data; data->vbo_data = (PosNorLoop *)GPU_vertbuf_get_data(vbo); + data->normals = MEM_mallocN(sizeof(GPUNormal) * mr->vert_len, __func__); /* Quicker than doing it for each loop. */ if (mr->extract_type == MR_EXTRACT_BMESH) { @@ -168,11 +169,10 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, data->normals[v].low = GPU_normal_convert_i10_s3(mv->no); } } - return data; } static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr, - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *_data) { @@ -220,7 +220,7 @@ static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr, } static void extract_pos_nor_iter_ledge_bm(const MeshRenderData *mr, - BMEdge *eed, + const BMEdge *eed, const int ledge_index, void *_data) { @@ -249,7 +249,7 @@ static void extract_pos_nor_iter_ledge_mesh(const MeshRenderData *mr, } static void extract_pos_nor_iter_lvert_bm(const MeshRenderData *mr, - BMVert *eve, + const BMVert *eve, const int lvert_index, void *_data) { @@ -280,9 +280,10 @@ static void extract_pos_nor_iter_lvert_mesh(const MeshRenderData *mr, static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), struct MeshBatchCache *UNUSED(cache), void *UNUSED(buf), - void *data) + void *_data) { - MEM_freeN(data); + MeshExtract_PosNor_Data *data = _data; + MEM_freeN(data->normals); } const MeshExtract extract_pos_nor = { @@ -295,6 +296,7 @@ const MeshExtract extract_pos_nor = { .iter_lvert_mesh = extract_pos_nor_iter_lvert_mesh, .finish = extract_pos_nor_finish, .data_type = 0, + .data_size = sizeof(MeshExtract_PosNor_Data), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor), }; @@ -312,12 +314,13 @@ typedef struct PosNorHQLoop { typedef struct MeshExtract_PosNorHQ_Data { PosNorHQLoop *vbo_data; - GPUNormal normals[]; + GPUNormal *normals; } MeshExtract_PosNorHQ_Data; -static void *extract_pos_nor_hq_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_pos_nor_hq_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -331,9 +334,9 @@ static void *extract_pos_nor_hq_init(const MeshRenderData *mr, GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); /* Pack normals per vert, reduce amount of computation. */ - size_t packed_nor_len = sizeof(GPUNormal) * mr->vert_len; - MeshExtract_PosNorHQ_Data *data = MEM_mallocN(sizeof(*data) + packed_nor_len, __func__); + MeshExtract_PosNorHQ_Data *data = tls_data; data->vbo_data = (PosNorHQLoop *)GPU_vertbuf_get_data(vbo); + data->normals = MEM_mallocN(sizeof(GPUNormal) * mr->vert_len, __func__); /* Quicker than doing it for each loop. */ if (mr->extract_type == MR_EXTRACT_BMESH) { @@ -350,11 +353,10 @@ static void *extract_pos_nor_hq_init(const MeshRenderData *mr, copy_v3_v3_short(data->normals[v].high, mv->no); } } - return data; } static void extract_pos_nor_hq_iter_poly_bm(const MeshRenderData *mr, - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *_data) { @@ -404,7 +406,7 @@ static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr, } static void extract_pos_nor_hq_iter_ledge_bm(const MeshRenderData *mr, - BMEdge *eed, + const BMEdge *eed, const int ledge_index, void *_data) { @@ -436,7 +438,7 @@ static void extract_pos_nor_hq_iter_ledge_mesh(const MeshRenderData *mr, } static void extract_pos_nor_hq_iter_lvert_bm(const MeshRenderData *mr, - BMVert *eve, + const BMVert *eve, const int lvert_index, void *_data) { @@ -469,9 +471,10 @@ static void extract_pos_nor_hq_iter_lvert_mesh(const MeshRenderData *mr, static void extract_pos_nor_hq_finish(const MeshRenderData *UNUSED(mr), struct MeshBatchCache *UNUSED(cache), void *UNUSED(buf), - void *data) + void *_data) { - MEM_freeN(data); + MeshExtract_PosNorHQ_Data *data = _data; + MEM_freeN(data->normals); } const MeshExtract extract_pos_nor_hq = { @@ -484,6 +487,7 @@ const MeshExtract extract_pos_nor_hq = { .iter_lvert_mesh = extract_pos_nor_hq_iter_lvert_mesh, .finish = extract_pos_nor_hq_finish, .data_type = 0, + .data_size = sizeof(MeshExtract_PosNorHQ_Data), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor)}; @@ -496,9 +500,10 @@ typedef struct gpuHQNor { short x, y, z, w; } gpuHQNor; -static void *extract_lnor_hq_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_lnor_hq_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -509,11 +514,11 @@ static void *extract_lnor_hq_init(const MeshRenderData *mr, GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->loop_len); - return GPU_vertbuf_get_data(vbo); + *(gpuHQNor **)tls_data = GPU_vertbuf_get_data(vbo); } static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr, - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *data) { @@ -522,14 +527,14 @@ static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr, do { const int l_index = BM_elem_index_get(l_iter); if (mr->loop_normals) { - normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, mr->loop_normals[l_index]); + normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, mr->loop_normals[l_index]); } else { if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { - normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_vert_no_get(mr, l_iter->v)); + normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, bm_vert_no_get(mr, l_iter->v)); } else { - normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_face_no_get(mr, f)); + normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, bm_face_no_get(mr, f)); } } } while ((l_iter = l_iter->next) != l_first); @@ -544,7 +549,7 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = mp->loopstart + mp->totloop; for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { const MLoop *ml = &mloop[ml_index]; - gpuHQNor *lnor_data = &((gpuHQNor *)data)[ml_index]; + gpuHQNor *lnor_data = &(*(gpuHQNor **)data)[ml_index]; if (mr->loop_normals) { normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]); } @@ -576,6 +581,7 @@ const MeshExtract extract_lnor_hq = { .iter_poly_bm = extract_lnor_hq_iter_poly_bm, .iter_poly_mesh = extract_lnor_hq_iter_poly_mesh, .data_type = MR_DATA_LOOP_NOR, + .data_size = sizeof(gpuHQNor *), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor), }; @@ -585,9 +591,10 @@ const MeshExtract extract_lnor_hq = { /** \name Extract Loop Normal * \{ */ -static void *extract_lnor_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_lnor_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -598,11 +605,11 @@ static void *extract_lnor_init(const MeshRenderData *mr, GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->loop_len); - return GPU_vertbuf_get_data(vbo); + *(GPUPackedNormal **)tls_data = GPU_vertbuf_get_data(vbo); } static void extract_lnor_iter_poly_bm(const MeshRenderData *mr, - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *data) { @@ -611,18 +618,18 @@ static void extract_lnor_iter_poly_bm(const MeshRenderData *mr, do { const int l_index = BM_elem_index_get(l_iter); if (mr->loop_normals) { - ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(mr->loop_normals[l_index]); + (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(mr->loop_normals[l_index]); } else { if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { - ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3( + (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3( bm_vert_no_get(mr, l_iter->v)); } else { - ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, f)); + (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, f)); } } - ((GPUPackedNormal *)data)[l_index].w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0; + (*(GPUPackedNormal **)data)[l_index].w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0; } while ((l_iter = l_iter->next) != l_first); } @@ -635,7 +642,7 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = mp->loopstart + mp->totloop; for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { const MLoop *ml = &mloop[ml_index]; - GPUPackedNormal *lnor_data = &((GPUPackedNormal *)data)[ml_index]; + GPUPackedNormal *lnor_data = &(*(GPUPackedNormal **)data)[ml_index]; if (mr->loop_normals) { *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]); } @@ -667,6 +674,7 @@ const MeshExtract extract_lnor = { .iter_poly_bm = extract_lnor_iter_poly_bm, .iter_poly_mesh = extract_lnor_iter_poly_mesh, .data_type = MR_DATA_LOOP_NOR, + .data_size = sizeof(GPUPackedNormal *), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor), }; @@ -677,7 +685,10 @@ const MeshExtract extract_lnor = { /** \name Extract UV layers * \{ */ -static void *extract_uv_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) +static void extract_uv_init(const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buf, + void *UNUSED(tls_data)) { GPUVertBuf *vbo = buf; GPUVertFormat format = {0}; @@ -757,13 +768,12 @@ static void *extract_uv_init(const MeshRenderData *mr, struct MeshBatchCache *ca } } } - - return NULL; } const MeshExtract extract_uv = { .init = extract_uv_init, .data_type = 0, + .data_size = 0, .use_threading = false, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.uv), }; @@ -946,15 +956,18 @@ static void extract_tan_ex_init(const MeshRenderData *mr, CustomData_free(&loop_data, mr->loop_len); } -static void *extract_tan_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) +static void extract_tan_init(const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buf, + void *UNUSED(tls_data)) { extract_tan_ex_init(mr, cache, buf, false); - return NULL; } const MeshExtract extract_tan = { .init = extract_tan_init, .data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, + .data_size = 0, .use_threading = false, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan), }; @@ -965,15 +978,18 @@ const MeshExtract extract_tan = { /** \name Extract HQ Tangent layers * \{ */ -static void *extract_tan_hq_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) +static void extract_tan_hq_init(const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buf, + void *UNUSED(tls_data)) { extract_tan_ex_init(mr, cache, buf, true); - return NULL; } const MeshExtract extract_tan_hq = { .init = extract_tan_hq_init, .data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, + .data_size = 0, .use_threading = false, }; @@ -983,9 +999,10 @@ const MeshExtract extract_tan_hq = { /** \name Extract Sculpt Data * \{ */ -static void *extract_sculpt_data_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_sculpt_data_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(tls_data)) { GPUVertBuf *vbo = buf; GPUVertFormat format = {0}; @@ -1066,13 +1083,12 @@ static void *extract_sculpt_data_init(const MeshRenderData *mr, } } } - - return NULL; } const MeshExtract extract_sculpt_data = { .init = extract_sculpt_data_init, .data_type = 0, + .data_size = 0, /* TODO: enable threading. */ .use_threading = false, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.sculpt_data)}; @@ -1083,7 +1099,10 @@ const MeshExtract extract_sculpt_data = { /** \name Extract VCol * \{ */ -static void *extract_vcol_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) +static void extract_vcol_init(const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buf, + void *UNUSED(tls_data)) { GPUVertBuf *vbo = buf; GPUVertFormat format = {0}; @@ -1216,12 +1235,12 @@ static void *extract_vcol_init(const MeshRenderData *mr, struct MeshBatchCache * } } } - return NULL; } const MeshExtract extract_vcol = { .init = extract_vcol_init, .data_type = 0, + .data_size = 0, .use_threading = false, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vcol), }; @@ -1237,9 +1256,10 @@ typedef struct MeshExtract_Orco_Data { float (*orco)[3]; } MeshExtract_Orco_Data; -static void *extract_orco_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_orco_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -1256,16 +1276,15 @@ static void *extract_orco_init(const MeshRenderData *mr, CustomData *cd_vdata = &mr->me->vdata; - MeshExtract_Orco_Data *data = MEM_mallocN(sizeof(*data), __func__); + MeshExtract_Orco_Data *data = tls_data; data->vbo_data = (float(*)[4])GPU_vertbuf_get_data(vbo); data->orco = CustomData_get_layer(cd_vdata, CD_ORCO); /* Make sure `orco` layer was requested only if needed! */ BLI_assert(data->orco); - return data; } static void extract_orco_iter_poly_bm(const MeshRenderData *UNUSED(mr), - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *data) { @@ -1296,20 +1315,12 @@ static void extract_orco_iter_poly_mesh(const MeshRenderData *mr, } } -static void extract_orco_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(buf), - void *data) -{ - MEM_freeN(data); -} - const MeshExtract extract_orco = { .init = extract_orco_init, .iter_poly_bm = extract_orco_iter_poly_bm, .iter_poly_mesh = extract_orco_iter_poly_mesh, - .finish = extract_orco_finish, .data_type = 0, + .data_size = sizeof(MeshExtract_Orco_Data), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.orco), }; @@ -1325,7 +1336,7 @@ typedef struct MeshExtract_EdgeFac_Data { uchar *vbo_data; bool use_edge_render; /* Number of loop per edge. */ - uchar edge_loop_count[0]; + uchar *edge_loop_count; } MeshExtract_EdgeFac_Data; static float loop_edge_factor_get(const float f_no[3], @@ -1344,9 +1355,10 @@ static float loop_edge_factor_get(const float f_no[3], return d; } -static void *extract_edge_fac_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_edge_fac_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -1357,11 +1369,10 @@ static void *extract_edge_fac_init(const MeshRenderData *mr, GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); - MeshExtract_EdgeFac_Data *data; + MeshExtract_EdgeFac_Data *data = tls_data; if (mr->extract_type == MR_EXTRACT_MESH) { - size_t edge_loop_count_size = sizeof(uint32_t) * mr->edge_len; - data = MEM_callocN(sizeof(*data) + edge_loop_count_size, __func__); + data->edge_loop_count = MEM_callocN(sizeof(uint32_t) * mr->edge_len, __func__); /* HACK(fclem) Detecting the need for edge render. * We could have a flag in the mesh instead or check the modifier stack. */ @@ -1374,17 +1385,15 @@ static void *extract_edge_fac_init(const MeshRenderData *mr, } } else { - data = MEM_callocN(sizeof(*data), __func__); /* HACK to bypass non-manifold check in mesh_edge_fac_finish(). */ data->use_edge_render = true; } data->vbo_data = GPU_vertbuf_get_data(vbo); - return data; } static void extract_edge_fac_iter_poly_bm(const MeshRenderData *mr, - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *_data) { @@ -1450,7 +1459,7 @@ static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr, } static void extract_edge_fac_iter_ledge_bm(const MeshRenderData *mr, - BMEdge *UNUSED(eed), + const BMEdge *UNUSED(eed), const int ledge_index, void *_data) { @@ -1501,7 +1510,7 @@ static void extract_edge_fac_finish(const MeshRenderData *mr, /* Free old byte data. */ MEM_freeN(data->vbo_data); } - MEM_freeN(data); + MEM_SAFE_FREE(data->edge_loop_count); } const MeshExtract extract_edge_fac = { @@ -1512,6 +1521,7 @@ const MeshExtract extract_edge_fac = { .iter_ledge_mesh = extract_edge_fac_iter_ledge_mesh, .finish = extract_edge_fac_finish, .data_type = MR_DATA_POLY_NOR, + .data_size = sizeof(MeshExtract_EdgeFac_Data), .use_threading = false, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_fac)}; @@ -1580,9 +1590,10 @@ static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeig return input; } -static void *extract_weights_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, - void *buf) +static void extract_weights_init(const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -1592,7 +1603,7 @@ static void *extract_weights_init(const MeshRenderData *mr, GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); - MeshExtract_Weight_Data *data = MEM_callocN(sizeof(*data), __func__); + MeshExtract_Weight_Data *data = tls_data; data->vbo_data = (float *)GPU_vertbuf_get_data(vbo); data->wstate = &cache->weight_state; @@ -1609,11 +1620,10 @@ static void *extract_weights_init(const MeshRenderData *mr, data->dvert = CustomData_get_layer(&mr->me->vdata, CD_MDEFORMVERT); data->cd_ofs = -1; } - return data; } static void extract_weights_iter_poly_bm(const MeshRenderData *UNUSED(mr), - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *_data) { @@ -1653,20 +1663,12 @@ static void extract_weights_iter_poly_mesh(const MeshRenderData *mr, } } -static void extract_weights_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(buf), - void *data) -{ - MEM_freeN(data); -} - const MeshExtract extract_weights = { .init = extract_weights_init, .iter_poly_bm = extract_weights_iter_poly_bm, .iter_poly_mesh = extract_weights_iter_poly_mesh, - .finish = extract_weights_finish, .data_type = 0, + .data_size = sizeof(MeshExtract_Weight_Data), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.weights), }; @@ -1685,7 +1687,7 @@ typedef struct EditLoopData { } EditLoopData; static void mesh_render_data_face_flag(const MeshRenderData *mr, - BMFace *efa, + const BMFace *efa, const int cd_ofs, EditLoopData *eattr) { @@ -1713,7 +1715,9 @@ static void mesh_render_data_face_flag(const MeshRenderData *mr, #endif } -static void mesh_render_data_edge_flag(const MeshRenderData *mr, BMEdge *eed, EditLoopData *eattr) +static void mesh_render_data_edge_flag(const MeshRenderData *mr, + const BMEdge *eed, + EditLoopData *eattr) { const ToolSettings *ts = mr->toolsettings; const bool is_vertex_select_mode = (ts != NULL) && (ts->selectmode & SCE_SELECT_VERTEX) != 0; @@ -1805,7 +1809,9 @@ static void mesh_render_data_loop_edge_flag(const MeshRenderData *mr, } } -static void mesh_render_data_vert_flag(const MeshRenderData *mr, BMVert *eve, EditLoopData *eattr) +static void mesh_render_data_vert_flag(const MeshRenderData *mr, + const BMVert *eve, + EditLoopData *eattr) { if (eve == mr->eve_act) { eattr->e_flag |= VFLAG_VERT_ACTIVE; @@ -1815,9 +1821,10 @@ static void mesh_render_data_vert_flag(const MeshRenderData *mr, BMVert *eve, Ed } } -static void *extract_edit_data_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_edit_data_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -1828,20 +1835,23 @@ static void *extract_edit_data_init(const MeshRenderData *mr, } GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); - return GPU_vertbuf_get_data(vbo); + EditLoopData *vbo_data = GPU_vertbuf_get_data(vbo); + *(EditLoopData **)tls_data = vbo_data; } static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr, - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *_data) { + EditLoopData *vbo_data = *(EditLoopData **)_data; + BMLoop *l_iter, *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { const int l_index = BM_elem_index_get(l_iter); - EditLoopData *data = (EditLoopData *)_data + l_index; + EditLoopData *data = vbo_data + l_index; memset(data, 0x0, sizeof(*data)); mesh_render_data_face_flag(mr, f, -1, data); mesh_render_data_edge_flag(mr, l_iter->e, data); @@ -1854,11 +1864,13 @@ static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr, const int mp_index, void *_data) { + EditLoopData *vbo_data = *(EditLoopData **)_data; + const MLoop *mloop = mr->mloop; const int ml_index_end = mp->loopstart + mp->totloop; for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { const MLoop *ml = &mloop[ml_index]; - EditLoopData *data = (EditLoopData *)_data + ml_index; + EditLoopData *data = vbo_data + ml_index; memset(data, 0x0, sizeof(*data)); BMFace *efa = bm_original_face_get(mr, mp_index); BMEdge *eed = bm_original_edge_get(mr, ml->e); @@ -1876,11 +1888,12 @@ static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr, } static void extract_edit_data_iter_ledge_bm(const MeshRenderData *mr, - BMEdge *eed, + const BMEdge *eed, const int ledge_index, void *_data) { - EditLoopData *data = (EditLoopData *)_data + mr->loop_len + (ledge_index * 2); + EditLoopData *vbo_data = *(EditLoopData **)_data; + EditLoopData *data = vbo_data + mr->loop_len + (ledge_index * 2); memset(data, 0x0, sizeof(*data) * 2); mesh_render_data_edge_flag(mr, eed, &data[0]); data[1] = data[0]; @@ -1893,7 +1906,8 @@ static void extract_edit_data_iter_ledge_mesh(const MeshRenderData *mr, const int ledge_index, void *_data) { - EditLoopData *data = (EditLoopData *)_data + mr->loop_len + ledge_index * 2; + EditLoopData *vbo_data = *(EditLoopData **)_data; + EditLoopData *data = vbo_data + mr->loop_len + ledge_index * 2; memset(data, 0x0, sizeof(*data) * 2); const int e_index = mr->ledges[ledge_index]; BMEdge *eed = bm_original_edge_get(mr, e_index); @@ -1912,12 +1926,13 @@ static void extract_edit_data_iter_ledge_mesh(const MeshRenderData *mr, } static void extract_edit_data_iter_lvert_bm(const MeshRenderData *mr, - BMVert *eve, + const BMVert *eve, const int lvert_index, void *_data) { + EditLoopData *vbo_data = *(EditLoopData **)_data; const int offset = mr->loop_len + (mr->edge_loose_len * 2); - EditLoopData *data = (EditLoopData *)_data + offset + lvert_index; + EditLoopData *data = vbo_data + offset + lvert_index; memset(data, 0x0, sizeof(*data)); mesh_render_data_vert_flag(mr, eve, data); } @@ -1927,9 +1942,10 @@ static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr, const int lvert_index, void *_data) { + EditLoopData *vbo_data = *(EditLoopData **)_data; const int offset = mr->loop_len + (mr->edge_loose_len * 2); - EditLoopData *data = (EditLoopData *)_data + offset + lvert_index; + EditLoopData *data = vbo_data + offset + lvert_index; memset(data, 0x0, sizeof(*data)); const int v_index = mr->lverts[lvert_index]; BMVert *eve = bm_original_vert_get(mr, v_index); @@ -1947,6 +1963,7 @@ const MeshExtract extract_edit_data = { .iter_lvert_bm = extract_edit_data_iter_lvert_bm, .iter_lvert_mesh = extract_edit_data_iter_lvert_mesh, .data_type = 0, + .data_size = sizeof(EditLoopData *), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edit_data)}; @@ -1961,9 +1978,10 @@ typedef struct MeshExtract_EditUVData_Data { int cd_ofs; } MeshExtract_EditUVData_Data; -static void *extract_edituv_data_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_edituv_data_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -1978,14 +1996,13 @@ static void *extract_edituv_data_init(const MeshRenderData *mr, CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; - MeshExtract_EditUVData_Data *data = MEM_callocN(sizeof(*data), __func__); + MeshExtract_EditUVData_Data *data = tls_data; data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo); data->cd_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV); - return data; } static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr, - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *_data) { @@ -2044,20 +2061,12 @@ static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr, } } -static void extract_edituv_data_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(buf), - void *data) -{ - MEM_freeN(data); -} - const MeshExtract extract_edituv_data = { .init = extract_edituv_data_init, .iter_poly_bm = extract_edituv_data_iter_poly_bm, .iter_poly_mesh = extract_edituv_data_iter_poly_mesh, - .finish = extract_edituv_data_finish, .data_type = 0, + .data_size = sizeof(MeshExtract_EditUVData_Data), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_data)}; @@ -2067,9 +2076,10 @@ const MeshExtract extract_edituv_data = { /** \name Extract Edit UV area stretch * \{ */ -static void *extract_edituv_stretch_area_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_edituv_stretch_area_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(tls_data)) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -2079,8 +2089,6 @@ static void *extract_edituv_stretch_area_init(const MeshRenderData *mr, GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->loop_len); - - return NULL; } BLI_INLINE float area_ratio_get(float area, float uvarea) @@ -2174,6 +2182,7 @@ const MeshExtract extract_edituv_stretch_area = { .init = extract_edituv_stretch_area_init, .finish = extract_edituv_stretch_area_finish, .data_type = 0, + .data_size = 0, .use_threading = false, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_area)}; @@ -2237,9 +2246,10 @@ static void edituv_get_edituv_stretch_angle(float auv[2][2], #endif } -static void *extract_edituv_stretch_angle_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_edituv_stretch_angle_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -2252,7 +2262,7 @@ static void *extract_edituv_stretch_angle_init(const MeshRenderData *mr, GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->loop_len); - MeshExtract_StretchAngle_Data *data = MEM_callocN(sizeof(*data), __func__); + MeshExtract_StretchAngle_Data *data = tls_data; data->vbo_data = (UVStretchAngle *)GPU_vertbuf_get_data(vbo); /* Special iterator needed to save about half of the computing cost. */ @@ -2263,11 +2273,10 @@ static void *extract_edituv_stretch_angle_init(const MeshRenderData *mr, BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH)); data->luv = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV); } - return data; } static void extract_edituv_stretch_angle_iter_poly_bm(const MeshRenderData *mr, - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *_data) { @@ -2363,20 +2372,12 @@ static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr } } -static void extract_edituv_stretch_angle_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(buf), - void *data) -{ - MEM_freeN(data); -} - const MeshExtract extract_edituv_stretch_angle = { .init = extract_edituv_stretch_angle_init, .iter_poly_bm = extract_edituv_stretch_angle_iter_poly_bm, .iter_poly_mesh = extract_edituv_stretch_angle_iter_poly_mesh, - .finish = extract_edituv_stretch_angle_finish, .data_type = 0, + .data_size = sizeof(MeshExtract_StretchAngle_Data), .use_threading = false, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_angle)}; @@ -2386,9 +2387,10 @@ const MeshExtract extract_edituv_stretch_angle = { /** \name Extract Edit Mesh Analysis Colors * \{ */ -static void *extract_mesh_analysis_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_mesh_analysis_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(tls_data)) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -2398,8 +2400,6 @@ static void *extract_mesh_analysis_init(const MeshRenderData *mr, GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->loop_len); - - return NULL; } static void axis_from_enum_v3(float v[3], const char axis) @@ -2984,6 +2984,7 @@ const MeshExtract extract_mesh_analysis = { /* This is not needed for all visualization types. * * Maybe split into different extract. */ .data_type = MR_DATA_POLY_NOR | MR_DATA_LOOPTRI, + .data_size = 0, .use_threading = false, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.mesh_analysis)}; @@ -2993,9 +2994,10 @@ const MeshExtract extract_mesh_analysis = { /** \name Extract Face-dots positions * \{ */ -static void *extract_fdots_pos_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_fdots_pos_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -3005,15 +3007,15 @@ static void *extract_fdots_pos_init(const MeshRenderData *mr, GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->poly_len); - return GPU_vertbuf_get_data(vbo); + *(float(**)[3])tls_data = GPU_vertbuf_get_data(vbo); } static void extract_fdots_pos_iter_poly_bm(const MeshRenderData *mr, - BMFace *f, + const BMFace *f, const int f_index, void *data) { - float(*center)[3] = data; + float(*center)[3] = *(float(**)[3])data; float *co = center[f_index]; zero_v3(co); @@ -3031,7 +3033,7 @@ static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr, const int mp_index, void *data) { - float(*center)[3] = (float(*)[3])data; + float(*center)[3] = *(float(**)[3])data; float *co = center[mp_index]; zero_v3(co); @@ -3064,6 +3066,7 @@ const MeshExtract extract_fdots_pos = { .iter_poly_bm = extract_fdots_pos_iter_poly_bm, .iter_poly_mesh = extract_fdots_pos_iter_poly_mesh, .data_type = 0, + .data_size = sizeof(float (*)[3]), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_pos)}; @@ -3077,9 +3080,10 @@ const MeshExtract extract_fdots_pos = { #define NOR_AND_FLAG_ACTIVE -1 #define NOR_AND_FLAG_HIDDEN -2 -static void *extract_fdots_nor_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_fdots_nor_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(tls_data)) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -3089,8 +3093,6 @@ static void *extract_fdots_nor_init(const MeshRenderData *mr, GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->poly_len); - - return NULL; } static void extract_fdots_nor_finish(const MeshRenderData *mr, @@ -3146,6 +3148,7 @@ const MeshExtract extract_fdots_nor = { .init = extract_fdots_nor_init, .finish = extract_fdots_nor_finish, .data_type = MR_DATA_POLY_NOR, + .data_size = 0, .use_threading = false, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor)}; @@ -3154,9 +3157,10 @@ const MeshExtract extract_fdots_nor = { /* ---------------------------------------------------------------------- */ /** \name Extract Face-dots High Quality Normal and edit flag * \{ */ -static void *extract_fdots_nor_hq_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_fdots_nor_hq_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(tls_data)) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -3166,8 +3170,6 @@ static void *extract_fdots_nor_hq_init(const MeshRenderData *mr, GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->poly_len); - - return NULL; } static void extract_fdots_nor_hq_finish(const MeshRenderData *mr, @@ -3223,6 +3225,7 @@ const MeshExtract extract_fdots_nor_hq = { .init = extract_fdots_nor_hq_init, .finish = extract_fdots_nor_hq_finish, .data_type = MR_DATA_POLY_NOR, + .data_size = 0, .use_threading = false, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor)}; @@ -3238,9 +3241,10 @@ typedef struct MeshExtract_FdotUV_Data { int cd_ofs; } MeshExtract_FdotUV_Data; -static void *extract_fdots_uv_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_fdots_uv_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -3258,7 +3262,7 @@ static void *extract_fdots_uv_init(const MeshRenderData *mr, memset(GPU_vertbuf_get_data(vbo), 0x0, mr->poly_len * GPU_vertbuf_get_format(vbo)->stride); } - MeshExtract_FdotUV_Data *data = MEM_callocN(sizeof(*data), __func__); + MeshExtract_FdotUV_Data *data = tls_data; data->vbo_data = (float(*)[2])GPU_vertbuf_get_data(vbo); if (mr->extract_type == MR_EXTRACT_BMESH) { @@ -3267,11 +3271,10 @@ static void *extract_fdots_uv_init(const MeshRenderData *mr, else { data->uv_data = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV); } - return data; } static void extract_fdots_uv_iter_poly_bm(const MeshRenderData *UNUSED(mr), - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *_data) { @@ -3308,20 +3311,12 @@ static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr, } } -static void extract_fdots_uv_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(buf), - void *data) -{ - MEM_freeN(data); -} - const MeshExtract extract_fdots_uv = { .init = extract_fdots_uv_init, .iter_poly_bm = extract_fdots_uv_iter_poly_bm, .iter_poly_mesh = extract_fdots_uv_iter_poly_mesh, - .finish = extract_fdots_uv_finish, .data_type = 0, + .data_size = sizeof(MeshExtract_FdotUV_Data), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_uv)}; @@ -3336,9 +3331,10 @@ typedef struct MeshExtract_EditUVFdotData_Data { int cd_ofs; } MeshExtract_EditUVFdotData_Data; -static void *extract_fdots_edituv_data_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_fdots_edituv_data_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -3349,14 +3345,13 @@ static void *extract_fdots_edituv_data_init(const MeshRenderData *mr, GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->poly_len); - MeshExtract_EditUVFdotData_Data *data = MEM_callocN(sizeof(*data), __func__); + MeshExtract_EditUVFdotData_Data *data = tls_data; data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo); data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); - return data; } static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr, - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *_data) { @@ -3380,20 +3375,12 @@ static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr, } } -static void extract_fdots_edituv_data_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(buf), - void *data) -{ - MEM_freeN(data); -} - const MeshExtract extract_fdots_edituv_data = { .init = extract_fdots_edituv_data_init, .iter_poly_bm = extract_fdots_edituv_data_iter_poly_bm, .iter_poly_mesh = extract_fdots_edituv_data_iter_poly_mesh, - .finish = extract_fdots_edituv_data_finish, .data_type = 0, + .data_size = sizeof(MeshExtract_EditUVFdotData_Data), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_edituv_data)}; @@ -3408,9 +3395,10 @@ typedef struct SkinRootData { float local_pos[3]; } SkinRootData; -static void *extract_skin_roots_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_skin_roots_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *UNUSED(tls_data)) { GPUVertBuf *vbo = buf; /* Exclusively for edit mode. */ @@ -3444,13 +3432,12 @@ static void *extract_skin_roots_init(const MeshRenderData *mr, /* It's really unlikely that all verts will be roots. Resize to avoid losing VRAM. */ GPU_vertbuf_data_len_set(vbo, root_len); - - return NULL; } const MeshExtract extract_skin_roots = { .init = extract_skin_roots_init, .data_type = 0, + .data_size = 0, .use_threading = false, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.skin_roots)}; @@ -3460,9 +3447,10 @@ const MeshExtract extract_skin_roots = { /** \name Extract Selection Index * \{ */ -static void *extract_select_idx_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_select_idx_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -3472,7 +3460,7 @@ static void *extract_select_idx_init(const MeshRenderData *mr, } GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); - return GPU_vertbuf_get_data(vbo); + *(uint32_t **)tls_data = GPU_vertbuf_get_data(vbo); } /* TODO Use #glVertexID to get loop index and use the data structure on the CPU to retrieve the @@ -3481,7 +3469,7 @@ static void *extract_select_idx_init(const MeshRenderData *mr, * shader to output original index. */ static void extract_poly_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), - BMFace *f, + const BMFace *f, const int f_index, void *data) { @@ -3489,12 +3477,12 @@ static void extract_poly_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { const int l_index = BM_elem_index_get(l_iter); - ((uint32_t *)data)[l_index] = f_index; + (*(uint32_t **)data)[l_index] = f_index; } while ((l_iter = l_iter->next) != l_first); } static void extract_edge_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *data) { @@ -3502,12 +3490,12 @@ static void extract_edge_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { const int l_index = BM_elem_index_get(l_iter); - ((uint32_t *)data)[l_index] = BM_elem_index_get(l_iter->e); + (*(uint32_t **)data)[l_index] = BM_elem_index_get(l_iter->e); } while ((l_iter = l_iter->next) != l_first); } static void extract_vert_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *data) { @@ -3515,36 +3503,36 @@ static void extract_vert_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { const int l_index = BM_elem_index_get(l_iter); - ((uint32_t *)data)[l_index] = BM_elem_index_get(l_iter->v); + (*(uint32_t **)data)[l_index] = BM_elem_index_get(l_iter->v); } while ((l_iter = l_iter->next) != l_first); } static void extract_edge_idx_iter_ledge_bm(const MeshRenderData *mr, - BMEdge *eed, + const BMEdge *eed, const int ledge_index, void *data) { - ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed); - ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed); + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed); + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed); } static void extract_vert_idx_iter_ledge_bm(const MeshRenderData *mr, - BMEdge *eed, + const BMEdge *eed, const int ledge_index, void *data) { - ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed->v1); - ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed->v2); + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed->v1); + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed->v2); } static void extract_vert_idx_iter_lvert_bm(const MeshRenderData *mr, - BMVert *eve, + const BMVert *eve, const int lvert_index, void *data) { const int offset = mr->loop_len + (mr->edge_loose_len * 2); - ((uint32_t *)data)[offset + lvert_index] = BM_elem_index_get(eve); + (*(uint32_t **)data)[offset + lvert_index] = BM_elem_index_get(eve); } static void extract_poly_idx_iter_poly_mesh(const MeshRenderData *mr, @@ -3554,7 +3542,7 @@ static void extract_poly_idx_iter_poly_mesh(const MeshRenderData *mr, { const int ml_index_end = mp->loopstart + mp->totloop; for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { - ((uint32_t *)data)[ml_index] = (mr->p_origindex) ? mr->p_origindex[mp_index] : mp_index; + (*(uint32_t **)data)[ml_index] = (mr->p_origindex) ? mr->p_origindex[mp_index] : mp_index; } } @@ -3567,7 +3555,7 @@ static void extract_edge_idx_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = mp->loopstart + mp->totloop; for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { const MLoop *ml = &mloop[ml_index]; - ((uint32_t *)data)[ml_index] = (mr->e_origindex) ? mr->e_origindex[ml->e] : ml->e; + (*(uint32_t **)data)[ml_index] = (mr->e_origindex) ? mr->e_origindex[ml->e] : ml->e; } } @@ -3580,7 +3568,7 @@ static void extract_vert_idx_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = mp->loopstart + mp->totloop; for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { const MLoop *ml = &mloop[ml_index]; - ((uint32_t *)data)[ml_index] = (mr->v_origindex) ? mr->v_origindex[ml->v] : ml->v; + (*(uint32_t **)data)[ml_index] = (mr->v_origindex) ? mr->v_origindex[ml->v] : ml->v; } } @@ -3591,8 +3579,8 @@ static void extract_edge_idx_iter_ledge_mesh(const MeshRenderData *mr, { const int e_index = mr->ledges[ledge_index]; const int e_orig = (mr->e_origindex) ? mr->e_origindex[e_index] : e_index; - ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = e_orig; - ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = e_orig; + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = e_orig; + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = e_orig; } static void extract_vert_idx_iter_ledge_mesh(const MeshRenderData *mr, @@ -3602,8 +3590,8 @@ static void extract_vert_idx_iter_ledge_mesh(const MeshRenderData *mr, { int v1_orig = (mr->v_origindex) ? mr->v_origindex[med->v1] : med->v1; int v2_orig = (mr->v_origindex) ? mr->v_origindex[med->v2] : med->v2; - ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = v1_orig; - ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = v2_orig; + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = v1_orig; + (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = v2_orig; } static void extract_vert_idx_iter_lvert_mesh(const MeshRenderData *mr, @@ -3615,7 +3603,7 @@ static void extract_vert_idx_iter_lvert_mesh(const MeshRenderData *mr, const int v_index = mr->lverts[lvert_index]; const int v_orig = (mr->v_origindex) ? mr->v_origindex[v_index] : v_index; - ((uint32_t *)data)[offset + lvert_index] = v_orig; + (*(uint32_t **)data)[offset + lvert_index] = v_orig; } const MeshExtract extract_poly_idx = { @@ -3623,6 +3611,7 @@ const MeshExtract extract_poly_idx = { .iter_poly_bm = extract_poly_idx_iter_poly_bm, .iter_poly_mesh = extract_poly_idx_iter_poly_mesh, .data_type = 0, + .data_size = sizeof(uint32_t *), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.poly_idx)}; @@ -3633,6 +3622,7 @@ const MeshExtract extract_edge_idx = { .iter_ledge_bm = extract_edge_idx_iter_ledge_bm, .iter_ledge_mesh = extract_edge_idx_iter_ledge_mesh, .data_type = 0, + .data_size = sizeof(uint32_t *), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_idx)}; @@ -3645,12 +3635,14 @@ const MeshExtract extract_vert_idx = { .iter_lvert_bm = extract_vert_idx_iter_lvert_bm, .iter_lvert_mesh = extract_vert_idx_iter_lvert_mesh, .data_type = 0, + .data_size = sizeof(uint32_t *), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vert_idx)}; -static void *extract_fdot_idx_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *buf) +static void extract_fdot_idx_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf, + void *tls_data) { GPUVertBuf *vbo = buf; static GPUVertFormat format = {0}; @@ -3661,15 +3653,15 @@ static void *extract_fdot_idx_init(const MeshRenderData *mr, GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->poly_len); - return GPU_vertbuf_get_data(vbo); + *(uint32_t **)tls_data = GPU_vertbuf_get_data(vbo); } static void extract_fdot_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), - BMFace *UNUSED(f), + const BMFace *UNUSED(f), const int f_index, void *data) { - ((uint32_t *)data)[f_index] = f_index; + (*(uint32_t **)data)[f_index] = f_index; } static void extract_fdot_idx_iter_poly_mesh(const MeshRenderData *mr, @@ -3678,10 +3670,10 @@ static void extract_fdot_idx_iter_poly_mesh(const MeshRenderData *mr, void *data) { if (mr->p_origindex != NULL) { - ((uint32_t *)data)[mp_index] = mr->p_origindex[mp_index]; + (*(uint32_t **)data)[mp_index] = mr->p_origindex[mp_index]; } else { - ((uint32_t *)data)[mp_index] = mp_index; + (*(uint32_t **)data)[mp_index] = mp_index; } } @@ -3690,5 +3682,6 @@ const MeshExtract extract_fdot_idx = { .iter_poly_bm = extract_fdot_idx_iter_poly_bm, .iter_poly_mesh = extract_fdot_idx_iter_poly_mesh, .data_type = 0, + .data_size = sizeof(uint32_t *), .use_threading = true, .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdot_idx)}; 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 2eea53354f2..26849eca08c 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_private.h +++ b/source/blender/draw/intern/draw_cache_extract_mesh_private.h @@ -150,278 +150,56 @@ BLI_INLINE const float *bm_face_no_get(const MeshRenderData *mr, const BMFace *e return efa->no; } -/* TODO(jbakker): phase out batch iteration macros as they are only used once. */ /* ---------------------------------------------------------------------- */ -/** \name Mesh Elements Extract: Loop Triangles +/** \name Mesh Elements Extract Struct * \{ */ - -typedef struct ExtractTriBMesh_Params { - BMLoop *(*looptris)[3]; - int tri_range[2]; -} ExtractTriBMesh_Params; +/* TODO(jbakker): move parameters inside a struct. */ typedef void(ExtractTriBMeshFn)(const MeshRenderData *mr, BMLoop **elt, const int elt_index, void *data); - -#define EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elem_tri, index_tri, params) \ - CHECK_TYPE(params, const ExtractTriBMesh_Params *); \ - { \ - const int _tri_index_end = (params)->tri_range[1]; \ - BMLoop **elem_tri = (params)->looptris[(params)->tri_range[0]]; \ - for (int index_tri = (params)->tri_range[0]; index_tri < _tri_index_end; \ - index_tri += 1, elem_tri += 3) -#define EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END } - -typedef struct ExtractTriMesh_Params { - const MLoopTri *mlooptri; - int tri_range[2]; -} ExtractTriMesh_Params; typedef void(ExtractTriMeshFn)(const MeshRenderData *mr, const MLoopTri *mlt, const int elt_index, void *data); - -#define EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(elem_tri, index_tri, params) \ - CHECK_TYPE(params, const ExtractTriMesh_Params *); \ - { \ - const int _tri_index_end = (params)->tri_range[1]; \ - const MLoopTri *elem_tri = &(params)->mlooptri[(params)->tri_range[0]]; \ - for (int index_tri = (params)->tri_range[0]; index_tri < _tri_index_end; \ - index_tri += 1, elem_tri += 1) -#define EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END } - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Mesh Elements Extract: Polygons, Loops - * \{ */ - -typedef struct ExtractPolyBMesh_Params { - BMLoop *(*looptris)[3]; - int poly_range[2]; -} ExtractPolyBMesh_Params; typedef void(ExtractPolyBMeshFn)(const MeshRenderData *mr, - BMFace *f, + const BMFace *f, const int f_index, void *data); - -#define EXTRACT_POLY_FOREACH_BM_BEGIN(elem_poly, index_poly, params, mr) \ - CHECK_TYPE(params, const ExtractPolyBMesh_Params *); \ - { \ - BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \ - BMFace **_ftable = mr->bm->ftable; \ - const int _poly_index_end = (params)->poly_range[1]; \ - for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \ - index_poly += 1) { \ - BMFace *elem_poly = _ftable[index_poly]; \ - (void)elem_poly; - -#define EXTRACT_POLY_FOREACH_BM_END \ - } \ - } - -/* Iterate over polygon and loop. */ -#define EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(elem_loop, index_loop, params, mr) \ - CHECK_TYPE(params, const ExtractPolyBMesh_Params *); \ - { \ - BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \ - BMFace **_ftable = mr->bm->ftable; \ - const int _poly_index_end = (params)->poly_range[1]; \ - for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \ - index_poly += 1) { \ - BMFace *elem_face = _ftable[index_poly]; \ - BMLoop *elem_loop, *l_first; \ - elem_loop = l_first = BM_FACE_FIRST_LOOP(elem_face); \ - do { \ - const int index_loop = BM_elem_index_get(elem_loop); \ - (void)index_loop; /* Quiet warning when unused. */ - -#define EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(elem_loop) \ - } \ - while ((elem_loop = elem_loop->next) != l_first) \ - ; \ - } \ - } - -typedef struct ExtractPolyMesh_Params { - int poly_range[2]; -} ExtractPolyMesh_Params; typedef void(ExtractPolyMeshFn)(const MeshRenderData *mr, const MPoly *mp, const int mp_index, void *data); - -#define EXTRACT_POLY_FOREACH_MESH_BEGIN(elem_poly, index_poly, params, mr) \ - CHECK_TYPE(params, const ExtractPolyMesh_Params *); \ - { \ - const MPoly *_mpoly = mr->mpoly; \ - const int _poly_index_end = (params)->poly_range[1]; \ - for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \ - index_poly += 1) { \ - const MPoly *elem_poly = &_mpoly[index_poly]; \ - (void)elem_poly; - -#define EXTRACT_POLY_FOREACH_MESH_END \ - } \ - } - -/* Iterate over polygon and loop. */ -#define EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN( \ - elem_poly, index_poly, elem_loop, index_loop, params, mr) \ - CHECK_TYPE(params, const ExtractPolyMesh_Params *); \ - { \ - const MPoly *_mpoly = mr->mpoly; \ - const MLoop *_mloop = mr->mloop; \ - const int _poly_index_end = (params)->poly_range[1]; \ - for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \ - index_poly += 1) { \ - const MPoly *elem_poly = &_mpoly[index_poly]; \ - const int _index_end = elem_poly->loopstart + elem_poly->totloop; \ - for (int index_loop = elem_poly->loopstart; index_loop < _index_end; index_loop += 1) { \ - const MLoop *elem_loop = &_mloop[index_loop]; \ - (void)elem_loop; - -#define EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END \ - } \ - } \ - } - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Mesh Elements Extract: Loose Edges - * \{ */ - -typedef struct ExtractLEdgeBMesh_Params { - const int *ledge; - int ledge_range[2]; -} ExtractLEdgeBMesh_Params; typedef void(ExtractLEdgeBMeshFn)(const MeshRenderData *mr, - BMEdge *eed, + const BMEdge *eed, const int ledge_index, void *data); - -#define EXTRACT_LEDGE_FOREACH_BM_BEGIN(elem_edge, index_ledge, params) \ - CHECK_TYPE(params, const ExtractLEdgeBMesh_Params *); \ - { \ - BLI_assert((mr->bm->elem_table_dirty & BM_EDGE) == 0); \ - BMEdge **_etable = mr->bm->etable; \ - const int *_ledge = (params)->ledge; \ - const int _ledge_index_end = (params)->ledge_range[1]; \ - for (int index_ledge = (params)->ledge_range[0]; index_ledge < _ledge_index_end; \ - index_ledge += 1) { \ - BMEdge *elem_edge = _etable[_ledge[index_ledge]]; \ - (void)elem_edge; /* Quiet warning when unused. */ \ - { -#define EXTRACT_LEDGE_FOREACH_BM_END \ - } \ - } \ - } - -typedef struct ExtractLEdgeMesh_Params { - const int *ledge; - int ledge_range[2]; -} ExtractLEdgeMesh_Params; typedef void(ExtractLEdgeMeshFn)(const MeshRenderData *mr, const MEdge *med, const int ledge_index, void *data); - -#define EXTRACT_LEDGE_FOREACH_MESH_BEGIN(elem_edge, index_ledge, params, mr) \ - CHECK_TYPE(params, const ExtractLEdgeMesh_Params *); \ - { \ - const MEdge *_medge = mr->medge; \ - const int *_ledge = (params)->ledge; \ - const int _ledge_index_end = (params)->ledge_range[1]; \ - for (int index_ledge = (params)->ledge_range[0]; index_ledge < _ledge_index_end; \ - index_ledge += 1) { \ - const MEdge *elem_edge = &_medge[_ledge[index_ledge]]; \ - (void)elem_edge; /* Quiet warning when unused. */ \ - { -#define EXTRACT_LEDGE_FOREACH_MESH_END \ - } \ - } \ - } - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Mesh Elements Extract: Loose Vertices - * \{ */ - -typedef struct ExtractLVertBMesh_Params { - const int *lvert; - int lvert_range[2]; -} ExtractLVertBMesh_Params; typedef void(ExtractLVertBMeshFn)(const MeshRenderData *mr, - BMVert *eve, + const BMVert *eve, const int lvert_index, void *data); - -#define EXTRACT_LVERT_FOREACH_BM_BEGIN(elem_vert, index_lvert, params) \ - CHECK_TYPE(params, const ExtractLVertBMesh_Params *); \ - { \ - BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \ - BMVert **vtable = mr->bm->vtable; \ - const int *lverts = (params)->lvert; \ - const int _lvert_index_end = (params)->lvert_range[1]; \ - for (int index_lvert = (params)->lvert_range[0]; index_lvert < _lvert_index_end; \ - index_lvert += 1) { \ - BMVert *elem_vert = vtable[lverts[index_lvert]]; \ - (void)elem_vert; /* Quiet warning when unused. */ \ - { -#define EXTRACT_LVERT_FOREACH_BM_END \ - } \ - } \ - } - -typedef struct ExtractLVertMesh_Params { - const int *lvert; - int lvert_range[2]; -} ExtractLVertMesh_Params; typedef void(ExtractLVertMeshFn)(const MeshRenderData *mr, const MVert *mv, const int lvert_index, void *data); - -#define EXTRACT_LVERT_FOREACH_MESH_BEGIN(elem, index_lvert, params, mr) \ - CHECK_TYPE(params, const ExtractLVertMesh_Params *); \ - { \ - const MVert *mvert = mr->mvert; \ - const int *lverts = (params)->lvert; \ - const int _lvert_index_end = (params)->lvert_range[1]; \ - for (int index_lvert = (params)->lvert_range[0]; index_lvert < _lvert_index_end; \ - index_lvert += 1) { \ - const MVert *elem = &mvert[lverts[index_lvert]]; \ - (void)elem; /* Quiet warning when unused. */ \ - { -#define EXTRACT_LVERT_FOREACH_MESH_END \ - } \ - } \ - } - -/** \} */ - -/* ---------------------------------------------------------------------- */ -/** \name Mesh Elements Extract Struct - * \{ */ -/* TODO(jbakker): move parameters inside a struct. */ -typedef void *(ExtractInitFn)(const MeshRenderData *mr, - struct MeshBatchCache *cache, - void *buffer); +typedef void(ExtractInitFn)(const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buffer, + void *r_data); typedef void(ExtractFinishFn)(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buffer, void *data); -typedef void *(ExtractTaskInitFn)(void *userdata); +typedef void(ExtractTaskInitFn)(void *userdata, void *r_task_userdata); typedef void(ExtractTaskFinishFn)(void *userdata, void *task_userdata); typedef struct MeshExtract { /** Executed on main thread and return user data for iteration functions. */ ExtractInitFn *init; - /** Task local data. */ - ExtractTaskInitFn *task_init; /** Executed on one (or more if use_threading) worker thread(s). */ ExtractTriBMeshFn *iter_looptri_bm; ExtractTriMeshFn *iter_looptri_mesh; @@ -432,10 +210,11 @@ typedef struct MeshExtract { ExtractLVertBMeshFn *iter_lvert_bm; ExtractLVertMeshFn *iter_lvert_mesh; /** Executed on one worker thread after all elements iterations. */ - ExtractTaskFinishFn *task_finish; + ExtractTaskFinishFn *task_reduce; ExtractFinishFn *finish; /** Used to request common data. */ eMRDataType data_type; + size_t data_size; /** Used to know if the element callbacks are thread-safe and can be parallelized. */ bool use_threading; /** diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc index 20b0ec738ee..565f8834ab1 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc @@ -37,15 +37,14 @@ struct MeshExtract_EditUvElem_Data { bool sync_selection; }; -static void *extract_edituv_tris_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(ibo)) +static void extract_edituv_tris_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *UNUSED(ibo), + void *tls_data) { - MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>( - MEM_callocN(sizeof(*data), __func__)); + MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data); GPU_indexbuf_init(&data->elb, GPU_PRIM_TRIS, mr->tri_len, mr->loop_len); data->sync_selection = (mr->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0; - return data; } BLI_INLINE void edituv_tri_add( @@ -93,7 +92,6 @@ static void extract_edituv_tris_finish(const MeshRenderData *UNUSED(mr), MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data); GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); GPU_indexbuf_build_in_place(&data->elb, ibo); - MEM_freeN(data); } constexpr MeshExtract create_extractor_edituv_tris() @@ -104,6 +102,7 @@ constexpr MeshExtract create_extractor_edituv_tris() extractor.iter_looptri_mesh = extract_edituv_tris_iter_looptri_mesh; extractor.finish = extract_edituv_tris_finish; extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_EditUvElem_Data); extractor.use_threading = false; extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_tris); return extractor; @@ -115,15 +114,14 @@ constexpr MeshExtract create_extractor_edituv_tris() /** \name Extract Edit UV Line Indices around faces * \{ */ -static void *extract_edituv_lines_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(ibo)) +static void extract_edituv_lines_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *UNUSED(ibo), + void *tls_data) { - MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>( - MEM_callocN(sizeof(*data), __func__)); + MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data); GPU_indexbuf_init(&data->elb, GPU_PRIM_LINES, mr->loop_len, mr->loop_len); data->sync_selection = (mr->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0; - return data; } BLI_INLINE void edituv_edge_add( @@ -135,7 +133,7 @@ BLI_INLINE void edituv_edge_add( } static void extract_edituv_lines_iter_poly_bm(const MeshRenderData *UNUSED(mr), - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *_data) { @@ -184,7 +182,6 @@ static void extract_edituv_lines_finish(const MeshRenderData *UNUSED(mr), MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data); GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); GPU_indexbuf_build_in_place(&data->elb, ibo); - MEM_freeN(data); } constexpr MeshExtract create_extractor_edituv_lines() @@ -195,6 +192,7 @@ constexpr MeshExtract create_extractor_edituv_lines() extractor.iter_poly_mesh = extract_edituv_lines_iter_poly_mesh; extractor.finish = extract_edituv_lines_finish; extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_EditUvElem_Data); extractor.use_threading = false; extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_lines); return extractor; @@ -206,15 +204,14 @@ constexpr MeshExtract create_extractor_edituv_lines() /** \name Extract Edit UV Points Indices * \{ */ -static void *extract_edituv_points_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(ibo)) +static void extract_edituv_points_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *UNUSED(ibo), + void *tls_data) { - MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>( - MEM_callocN(sizeof(*data), __func__)); + MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data); GPU_indexbuf_init(&data->elb, GPU_PRIM_POINTS, mr->loop_len, mr->loop_len); data->sync_selection = (mr->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0; - return data; } BLI_INLINE void edituv_point_add(MeshExtract_EditUvElem_Data *data, @@ -228,7 +225,7 @@ BLI_INLINE void edituv_point_add(MeshExtract_EditUvElem_Data *data, } static void extract_edituv_points_iter_poly_bm(const MeshRenderData *UNUSED(mr), - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *_data) { @@ -269,7 +266,6 @@ static void extract_edituv_points_finish(const MeshRenderData *UNUSED(mr), MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data); GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); GPU_indexbuf_build_in_place(&data->elb, ibo); - MEM_freeN(data); } constexpr MeshExtract create_extractor_edituv_points() @@ -280,6 +276,7 @@ constexpr MeshExtract create_extractor_edituv_points() extractor.iter_poly_mesh = extract_edituv_points_iter_poly_mesh; extractor.finish = extract_edituv_points_finish; extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_EditUvElem_Data); extractor.use_threading = false; extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_points); return extractor; @@ -291,15 +288,14 @@ constexpr MeshExtract create_extractor_edituv_points() /** \name Extract Edit UV Face-dots Indices * \{ */ -static void *extract_edituv_fdots_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(ibo)) +static void extract_edituv_fdots_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *UNUSED(ibo), + void *tls_data) { - MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>( - MEM_callocN(sizeof(*data), __func__)); + MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data); GPU_indexbuf_init(&data->elb, GPU_PRIM_POINTS, mr->poly_len, mr->poly_len); data->sync_selection = (mr->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0; - return data; } BLI_INLINE void edituv_facedot_add(MeshExtract_EditUvElem_Data *data, @@ -316,7 +312,7 @@ BLI_INLINE void edituv_facedot_add(MeshExtract_EditUvElem_Data *data, } static void extract_edituv_fdots_iter_poly_bm(const MeshRenderData *UNUSED(mr), - BMFace *f, + const BMFace *f, const int f_index, void *_data) { @@ -366,7 +362,6 @@ static void extract_edituv_fdots_finish(const MeshRenderData *UNUSED(mr), MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data); GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); GPU_indexbuf_build_in_place(&data->elb, ibo); - MEM_freeN(data); } constexpr MeshExtract create_extractor_edituv_fdots() @@ -377,6 +372,7 @@ constexpr MeshExtract create_extractor_edituv_fdots() extractor.iter_poly_mesh = extract_edituv_fdots_iter_poly_mesh; extractor.finish = extract_edituv_fdots_finish; extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_EditUvElem_Data); extractor.use_threading = false; extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_fdots); return extractor; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc index 9bd918dc9a5..1d1a000061d 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc @@ -32,17 +32,17 @@ namespace blender::draw { /** \name Extract Face-dots Indices * \{ */ -static void *extract_fdots_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(buf)) +static void extract_fdots_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *UNUSED(buf), + void *tls_data) { - GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(MEM_mallocN(sizeof(*elb), __func__)); + GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(tls_data); GPU_indexbuf_init(elb, GPU_PRIM_POINTS, mr->poly_len, mr->poly_len); - return elb; } static void extract_fdots_iter_poly_bm(const MeshRenderData *UNUSED(mr), - BMFace *f, + const BMFace *f, const int f_index, void *_userdata) { @@ -93,7 +93,6 @@ static void extract_fdots_finish(const MeshRenderData *UNUSED(mr), GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_userdata); GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); GPU_indexbuf_build_in_place(elb, ibo); - MEM_freeN(elb); } constexpr MeshExtract create_extractor_fdots() @@ -104,6 +103,7 @@ constexpr MeshExtract create_extractor_fdots() extractor.iter_poly_mesh = extract_fdots_iter_poly_mesh; extractor.finish = extract_fdots_finish; extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(GPUIndexBufBuilder); extractor.use_threading = false; extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.fdots); return extractor; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc index 74a3d3825c5..683794d4d66 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc @@ -31,28 +31,19 @@ namespace blender::draw { /** \name Extract Edges Indices * \{ */ -static void *extract_lines_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(buf)) +static void extract_lines_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *UNUSED(buf), + void *tls_data) { - GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(MEM_mallocN(sizeof(*elb), __func__)); + GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(tls_data); /* Put loose edges at the end. */ GPU_indexbuf_init( elb, GPU_PRIM_LINES, mr->edge_len + mr->edge_loose_len, mr->loop_len + mr->loop_loose_len); - return elb; -} - -static void *extract_lines_task_init(void *_userdata) -{ - GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_userdata); - GPUIndexBufBuilder *sub_builder = static_cast<GPUIndexBufBuilder *>( - MEM_mallocN(sizeof(*sub_builder), __func__)); - GPU_indexbuf_subbuilder_init(elb, sub_builder); - return sub_builder; } static void extract_lines_iter_poly_bm(const MeshRenderData *UNUSED(mr), - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *data) { @@ -109,7 +100,7 @@ static void extract_lines_iter_poly_mesh(const MeshRenderData *mr, } static void extract_lines_iter_ledge_bm(const MeshRenderData *mr, - BMEdge *eed, + const BMEdge *eed, const int ledge_index, void *data) { @@ -147,12 +138,11 @@ static void extract_lines_iter_ledge_mesh(const MeshRenderData *mr, GPU_indexbuf_set_line_restart(elb, e_index); } -static void extract_lines_task_finish(void *_userdata, void *_task_userdata) +static void extract_lines_task_finish(void *_userdata_to, void *_userdata_from) { - GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_userdata); - GPUIndexBufBuilder *sub_builder = static_cast<GPUIndexBufBuilder *>(_task_userdata); - GPU_indexbuf_subbuilder_finish(elb, sub_builder); - MEM_freeN(sub_builder); + GPUIndexBufBuilder *elb_to = static_cast<GPUIndexBufBuilder *>(_userdata_to); + GPUIndexBufBuilder *elb_from = static_cast<GPUIndexBufBuilder *>(_userdata_from); + GPU_indexbuf_join_copies(elb_to, elb_from); } static void extract_lines_finish(const MeshRenderData *UNUSED(mr), @@ -163,21 +153,20 @@ static void extract_lines_finish(const MeshRenderData *UNUSED(mr), GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data); GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); GPU_indexbuf_build_in_place(elb, ibo); - MEM_freeN(elb); } constexpr MeshExtract create_extractor_lines() { MeshExtract extractor = {0}; extractor.init = extract_lines_init; - extractor.task_init = extract_lines_task_init; extractor.iter_poly_bm = extract_lines_iter_poly_bm; extractor.iter_poly_mesh = extract_lines_iter_poly_mesh; extractor.iter_ledge_bm = extract_lines_iter_ledge_bm; extractor.iter_ledge_mesh = extract_lines_iter_ledge_mesh; - extractor.task_finish = extract_lines_task_finish; + extractor.task_reduce = extract_lines_task_finish; extractor.finish = extract_lines_finish; extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(GPUIndexBufBuilder); extractor.use_threading = true; extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines); return extractor; @@ -209,21 +198,20 @@ static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); GPU_indexbuf_build_in_place(elb, ibo); extract_lines_loose_subbuffer(mr, cache); - MEM_freeN(elb); } constexpr MeshExtract create_extractor_lines_with_lines_loose() { MeshExtract extractor = {0}; extractor.init = extract_lines_init; - extractor.task_init = extract_lines_task_init; extractor.iter_poly_bm = extract_lines_iter_poly_bm; extractor.iter_poly_mesh = extract_lines_iter_poly_mesh; extractor.iter_ledge_bm = extract_lines_iter_ledge_bm; extractor.iter_ledge_mesh = extract_lines_iter_ledge_mesh; - extractor.task_finish = extract_lines_task_finish; + extractor.task_reduce = extract_lines_task_finish; extractor.finish = extract_lines_with_lines_loose_finish; extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(GPUIndexBufBuilder); extractor.use_threading = true; extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines); return extractor; @@ -235,14 +223,14 @@ constexpr MeshExtract create_extractor_lines_with_lines_loose() /** \name Extract Loose Edges Sub Buffer * \{ */ -static void *extract_lines_loose_only_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, - void *buf) +static void extract_lines_loose_only_init(const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buf, + void *UNUSED(tls_data)) { BLI_assert(buf == cache->final.ibo.lines_loose); UNUSED_VARS_NDEBUG(buf); extract_lines_loose_subbuffer(mr, cache); - return NULL; } constexpr MeshExtract create_extractor_lines_loose_only() @@ -250,6 +238,7 @@ constexpr MeshExtract create_extractor_lines_loose_only() MeshExtract extractor = {0}; extractor.init = extract_lines_loose_only_init; extractor.data_type = MR_DATA_NONE; + extractor.data_size = 0; extractor.use_threading = false; extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines_loose); return extractor; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc index 6140ae86c96..cace18b0c08 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc @@ -41,26 +41,25 @@ struct MeshExtract_LineAdjacency_Data { EdgeHash *eh; bool is_manifold; /* Array to convert vert index to any loop index of this vert. */ - uint vert_to_loop[0]; + uint *vert_to_loop; }; -static void *extract_lines_adjacency_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(buf)) +static void extract_lines_adjacency_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *UNUSED(buf), + void *tls_data) { /* Similar to poly_to_tri_count(). * There is always (loop + triangle - 1) edges inside a polygon. * Accumulate for all polys and you get : */ uint tess_edge_len = mr->loop_len + mr->tri_len - mr->poly_len; - size_t vert_to_loop_size = sizeof(uint) * mr->vert_len; + MeshExtract_LineAdjacency_Data *data = static_cast<MeshExtract_LineAdjacency_Data *>(tls_data); + data->vert_to_loop = static_cast<uint *>(MEM_callocN(sizeof(uint) * mr->vert_len, __func__)); - MeshExtract_LineAdjacency_Data *data = static_cast<MeshExtract_LineAdjacency_Data *>( - MEM_callocN(sizeof(*data) + vert_to_loop_size, __func__)); GPU_indexbuf_init(&data->elb, GPU_PRIM_LINES_ADJ, tess_edge_len, mr->loop_len); data->eh = BLI_edgehash_new_ex(__func__, tess_edge_len); data->is_manifold = true; - return data; } BLI_INLINE void lines_adjacency_triangle( @@ -169,7 +168,7 @@ static void extract_lines_adjacency_finish(const MeshRenderData *UNUSED(mr), cache->is_manifold = data->is_manifold; GPU_indexbuf_build_in_place(&data->elb, ibo); - MEM_freeN(data); + MEM_freeN(data->vert_to_loop); } #undef NO_EDGE @@ -184,6 +183,7 @@ constexpr MeshExtract create_extractor_lines_adjacency() extractor.iter_looptri_mesh = extract_lines_adjacency_iter_looptri_mesh; extractor.finish = extract_lines_adjacency_finish; extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_LineAdjacency_Data); extractor.use_threading = false; extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines_adjacency); return extractor; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc index 6bbd0188f65..a142692ab4e 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc @@ -37,18 +37,17 @@ namespace blender::draw { struct MeshExtract_LinePaintMask_Data { GPUIndexBufBuilder elb; /** One bit per edge set if face is selected. */ - BLI_bitmap select_map[0]; + BLI_bitmap *select_map; }; -static void *extract_lines_paint_mask_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(ibo)) +static void extract_lines_paint_mask_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *UNUSED(ibo), + void *tls_data) { - size_t bitmap_size = BLI_BITMAP_SIZE(mr->edge_len); - MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>( - MEM_callocN(sizeof(*data) + bitmap_size, __func__)); + MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>(tls_data); + data->select_map = BLI_BITMAP_NEW(mr->edge_len, __func__); GPU_indexbuf_init(&data->elb, GPU_PRIM_LINES, mr->edge_len, mr->loop_len); - return data; } static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr, @@ -101,7 +100,7 @@ static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr), MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>(_data); GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); GPU_indexbuf_build_in_place(&data->elb, ibo); - MEM_freeN(data); + MEM_freeN(data->select_map); } /** \} */ @@ -113,6 +112,7 @@ constexpr MeshExtract create_extractor_lines_paint_mask() extractor.iter_poly_mesh = extract_lines_paint_mask_iter_poly_mesh; extractor.finish = extract_lines_paint_mask_finish; extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_LinePaintMask_Data); extractor.use_threading = false; extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines_paint_mask); return extractor; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc index 9220198d799..25d1a159f60 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc @@ -32,25 +32,16 @@ namespace blender::draw { /* ---------------------------------------------------------------------- */ /** \name Extract Point Indices * \{ */ -static void *extract_points_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(buf)) +static void extract_points_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *UNUSED(buf), + void *tls_data) { - GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(MEM_mallocN(sizeof(*elb), __func__)); + GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(tls_data); GPU_indexbuf_init(elb, GPU_PRIM_POINTS, mr->vert_len, mr->loop_len + mr->loop_loose_len); - return elb; } -static void *extract_points_task_init(void *_userdata) -{ - GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_userdata); - GPUIndexBufBuilder *sub_builder = static_cast<GPUIndexBufBuilder *>( - MEM_mallocN(sizeof(*sub_builder), __func__)); - GPU_indexbuf_subbuilder_init(elb, sub_builder); - return sub_builder; -} - -BLI_INLINE void vert_set_bm(GPUIndexBufBuilder *elb, BMVert *eve, int l_index) +BLI_INLINE void vert_set_bm(GPUIndexBufBuilder *elb, const BMVert *eve, int l_index) { const int v_index = BM_elem_index_get(eve); if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { @@ -78,7 +69,7 @@ BLI_INLINE void vert_set_mesh(GPUIndexBufBuilder *elb, } static void extract_points_iter_poly_bm(const MeshRenderData *UNUSED(mr), - BMFace *f, + const BMFace *f, const int UNUSED(f_index), void *_userdata) { @@ -107,7 +98,7 @@ static void extract_points_iter_poly_mesh(const MeshRenderData *mr, } static void extract_points_iter_ledge_bm(const MeshRenderData *mr, - BMEdge *eed, + const BMEdge *eed, const int ledge_index, void *_userdata) { @@ -127,7 +118,7 @@ static void extract_points_iter_ledge_mesh(const MeshRenderData *mr, } static void extract_points_iter_lvert_bm(const MeshRenderData *mr, - BMVert *eve, + const BMVert *eve, const int lvert_index, void *_userdata) { @@ -146,12 +137,11 @@ static void extract_points_iter_lvert_mesh(const MeshRenderData *mr, vert_set_mesh(elb, mr, mr->lverts[lvert_index], offset + lvert_index); } -static void extract_points_task_finish(void *_userdata, void *_task_userdata) +static void extract_points_task_finish(void *_userdata_to, void *_userdata_from) { - GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_userdata); - GPUIndexBufBuilder *sub_builder = static_cast<GPUIndexBufBuilder *>(_task_userdata); - GPU_indexbuf_subbuilder_finish(elb, sub_builder); - MEM_freeN(sub_builder); + GPUIndexBufBuilder *elb_to = static_cast<GPUIndexBufBuilder *>(_userdata_to); + GPUIndexBufBuilder *elb_from = static_cast<GPUIndexBufBuilder *>(_userdata_from); + GPU_indexbuf_join_copies(elb_to, elb_from); } static void extract_points_finish(const MeshRenderData *UNUSED(mr), @@ -162,24 +152,23 @@ static void extract_points_finish(const MeshRenderData *UNUSED(mr), GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_userdata); GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf); GPU_indexbuf_build_in_place(elb, ibo); - MEM_freeN(elb); } constexpr MeshExtract create_extractor_points() { MeshExtract extractor = {0}; extractor.init = extract_points_init; - extractor.task_init = extract_points_task_init; extractor.iter_poly_bm = extract_points_iter_poly_bm; extractor.iter_poly_mesh = extract_points_iter_poly_mesh; extractor.iter_ledge_bm = extract_points_iter_ledge_bm; extractor.iter_ledge_mesh = extract_points_iter_ledge_mesh; extractor.iter_lvert_bm = extract_points_iter_lvert_bm; extractor.iter_lvert_mesh = extract_points_iter_lvert_mesh; - extractor.task_finish = extract_points_task_finish; + extractor.task_reduce = extract_points_task_finish; extractor.finish = extract_points_finish; extractor.use_threading = true; extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(GPUIndexBufBuilder); extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.points); return extractor; } 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 acfffdacb88..27929fa8ba3 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 @@ -37,12 +37,12 @@ struct MeshExtract_Tri_Data { int *tri_mat_end; }; -static void *extract_tris_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(ibo)) +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 *>( - MEM_callocN(sizeof(*data), __func__)); + 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__)); @@ -82,8 +82,6 @@ static void *extract_tris_init(const MeshRenderData *mr, int visible_tri_tot = ofs; GPU_indexbuf_init(&data->elb, GPU_PRIM_TRIS, visible_tri_tot, mr->loop_len); - - return data; } static void extract_tris_iter_looptri_bm(const MeshRenderData *mr, @@ -150,7 +148,6 @@ static void extract_tris_finish(const MeshRenderData *mr, } MEM_freeN(data->tri_mat_start); MEM_freeN(data->tri_mat_end); - MEM_freeN(data); } constexpr MeshExtract create_extractor_tris() @@ -161,6 +158,7 @@ constexpr MeshExtract create_extractor_tris() extractor.iter_looptri_mesh = extract_tris_iter_looptri_mesh; extractor.finish = extract_tris_finish; extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(MeshExtract_Tri_Data); extractor.use_threading = false; extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris); return extractor; @@ -171,22 +169,13 @@ constexpr MeshExtract create_extractor_tris() /** \name Extract Triangles Indices (single material) * \{ */ -static void *extract_tris_single_mat_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), - void *UNUSED(ibo)) +static void extract_tris_single_mat_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *UNUSED(ibo), + void *tls_data) { - GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(MEM_mallocN(sizeof(*elb), __func__)); + GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(tls_data); GPU_indexbuf_init(elb, GPU_PRIM_TRIS, mr->tri_len, mr->loop_len); - return elb; -} - -static void *extract_tris_single_mat_task_init(void *_userdata) -{ - GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_userdata); - GPUIndexBufBuilder *sub_builder = static_cast<GPUIndexBufBuilder *>( - MEM_mallocN(sizeof(*sub_builder), __func__)); - GPU_indexbuf_subbuilder_init(elb, sub_builder); - return sub_builder; } static void extract_tris_single_mat_iter_looptri_bm(const MeshRenderData *UNUSED(mr), @@ -222,12 +211,11 @@ static void extract_tris_single_mat_iter_looptri_mesh(const MeshRenderData *mr, } } -static void extract_tris_single_mat_task_finish(void *_userdata, void *_task_userdata) +static void extract_tris_single_mat_task_finish(void *_userdata_to, void *_userdata_from) { - GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_userdata); - GPUIndexBufBuilder *sub_builder = static_cast<GPUIndexBufBuilder *>(_task_userdata); - GPU_indexbuf_subbuilder_finish(elb, sub_builder); - MEM_freeN(sub_builder); + GPUIndexBufBuilder *elb_to = static_cast<GPUIndexBufBuilder *>(_userdata_to); + GPUIndexBufBuilder *elb_from = static_cast<GPUIndexBufBuilder *>(_userdata_from); + GPU_indexbuf_join_copies(elb_to, elb_from); } static void extract_tris_single_mat_finish(const MeshRenderData *mr, @@ -254,19 +242,18 @@ static void extract_tris_single_mat_finish(const MeshRenderData *mr, GPU_indexbuf_create_subrange_in_place(mbc->tris_per_mat[i], ibo, 0, len); } } - MEM_freeN(elb); } constexpr MeshExtract create_extractor_tris_single_mat() { MeshExtract extractor = {0}; extractor.init = extract_tris_single_mat_init; - extractor.task_init = extract_tris_single_mat_task_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_finish = extract_tris_single_mat_task_finish; + extractor.task_reduce = extract_tris_single_mat_task_finish; extractor.finish = extract_tris_single_mat_finish; extractor.data_type = MR_DATA_NONE; + extractor.data_size = sizeof(GPUIndexBufBuilder); extractor.use_threading = true; extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris); return extractor; diff --git a/source/blender/gpu/GPU_index_buffer.h b/source/blender/gpu/GPU_index_buffer.h index 03d60c60b4b..48f80e321b6 100644 --- a/source/blender/gpu/GPU_index_buffer.h +++ b/source/blender/gpu/GPU_index_buffer.h @@ -44,7 +44,6 @@ typedef struct GPUIndexBufBuilder { uint index_max; GPUPrimType prim_type; uint32_t *data; - const struct GPUIndexBufBuilder *parent; } GPUIndexBufBuilder; /* supports all primitive types. */ @@ -55,17 +54,12 @@ void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint ve GPUIndexBuf *GPU_indexbuf_build_on_device(uint index_len); /* - * Thread safe sub builders. + * Thread safe. * - * Note that `GPU_indexbuf_subbuilder_init` and `GPU_indexbuf_subbuilder_finish` are not thread - * safe and should be called when no threads are active. The pattern is to create a subbuilder for - * each thread/task. Each thread/task would update their sub builder. When all thread are completed - * the sub-builders can then be merged back to the parent builder. + * Function inspired by the reduction directives of multithread work APIs.. */ -void GPU_indexbuf_subbuilder_init(const GPUIndexBufBuilder *parent_builder, - GPUIndexBufBuilder *sub_builder); -void GPU_indexbuf_subbuilder_finish(GPUIndexBufBuilder *builder, - const GPUIndexBufBuilder *parent_builder); +void GPU_indexbuf_join_copies(GPUIndexBufBuilder *builder, + const GPUIndexBufBuilder *parent_builder); void GPU_indexbuf_add_generic_vert(GPUIndexBufBuilder *, uint v); void GPU_indexbuf_add_primitive_restart(GPUIndexBufBuilder *); diff --git a/source/blender/gpu/intern/gpu_index_buffer.cc b/source/blender/gpu/intern/gpu_index_buffer.cc index 3cdcaac5544..993bcdf743b 100644 --- a/source/blender/gpu/intern/gpu_index_buffer.cc +++ b/source/blender/gpu/intern/gpu_index_buffer.cc @@ -57,7 +57,6 @@ void GPU_indexbuf_init_ex(GPUIndexBufBuilder *builder, builder->index_max = 0; builder->prim_type = prim_type; builder->data = (uint *)MEM_callocN(builder->max_index_len * sizeof(uint), "GPUIndexBuf data"); - builder->parent = nullptr; } void GPU_indexbuf_init(GPUIndexBufBuilder *builder, @@ -80,21 +79,13 @@ GPUIndexBuf *GPU_indexbuf_build_on_device(uint index_len) return elem_; } -void GPU_indexbuf_subbuilder_init(const GPUIndexBufBuilder *parent_builder, - GPUIndexBufBuilder *sub_builder) +void GPU_indexbuf_join_copies(GPUIndexBufBuilder *builder_to, + const GPUIndexBufBuilder *builder_from) { - BLI_assert(parent_builder->parent == nullptr); - memcpy(sub_builder, parent_builder, sizeof(GPUIndexBufBuilder)); - sub_builder->parent = parent_builder; -} - -void GPU_indexbuf_subbuilder_finish(GPUIndexBufBuilder *parent_builder, - const GPUIndexBufBuilder *sub_builder) -{ - BLI_assert(parent_builder == sub_builder->parent); - parent_builder->index_len = max_uu(parent_builder->index_len, sub_builder->index_len); - parent_builder->index_min = min_uu(parent_builder->index_min, sub_builder->index_min); - parent_builder->index_max = max_uu(parent_builder->index_max, sub_builder->index_max); + BLI_assert(builder_to->data == builder_from->data); + builder_to->index_len = max_uu(builder_to->index_len, builder_from->index_len); + builder_to->index_min = min_uu(builder_to->index_min, builder_from->index_min); + builder_to->index_max = max_uu(builder_to->index_max, builder_from->index_max); } void GPU_indexbuf_add_generic_vert(GPUIndexBufBuilder *builder, uint v) diff --git a/source/tools b/source/tools -Subproject 01f51a0e551ab730f0934dc6488613690ac4bf8 +Subproject 2afbb8ec472cac5102eb239f57b006f8c938768 |