diff options
Diffstat (limited to 'source/blender/draw/intern/draw_cache_extract_mesh.cc')
-rw-r--r-- | source/blender/draw/intern/draw_cache_extract_mesh.cc | 817 |
1 files changed, 266 insertions, 551 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); } |