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 | 189 |
1 files changed, 134 insertions, 55 deletions
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index 8d6064179ad..7b2c0da4dd9 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -24,11 +24,15 @@ */ #include "MEM_guardedalloc.h" +#include <optional> + #include "atomic_ops.h" #include "DNA_mesh_types.h" #include "DNA_scene_types.h" +#include "BLI_array.hh" +#include "BLI_math_bits.h" #include "BLI_task.h" #include "BLI_vector.hh" @@ -53,6 +57,8 @@ namespace blender::draw { /* ---------------------------------------------------------------------- */ /** \name Mesh Elements Extract Struct * \{ */ +using TaskId = int; +using TaskLen = int; struct ExtractorRunData { /* Extractor where this run data belongs to. */ @@ -62,11 +68,23 @@ struct ExtractorRunData { /* 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; 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 @@ -111,7 +129,7 @@ class ExtractorRunDatas : public Vector<ExtractorRunData> { } } - eMRIterType iter_types() + eMRIterType iter_types() const { eMRIterType iter_type = static_cast<eMRIterType>(0); @@ -122,6 +140,13 @@ class ExtractorRunDatas : public Vector<ExtractorRunData> { return iter_type; } + const uint iter_types_len() const + { + const eMRIterType iter_type = iter_types(); + uint bits = static_cast<uint>(iter_type); + return count_bits_i(bits); + } + eMRDataType data_types() { eMRDataType data_type = static_cast<eMRDataType>(0); @@ -158,7 +183,8 @@ BLI_INLINE void extract_init(const MeshRenderData *mr, BLI_INLINE void extract_iter_looptri_bm(const MeshRenderData *mr, const ExtractTriBMesh_Params *params, - const ExtractorRunDatas &all_extractors) + const ExtractorRunDatas &all_extractors, + const TaskId task_id) { ExtractorRunDatas extractors; all_extractors.filter_into(extractors, MR_ITER_LOOPTRI); @@ -166,7 +192,7 @@ BLI_INLINE void extract_iter_looptri_bm(const MeshRenderData *mr, 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.user_data); + run_data.extractor->iter_looptri_bm(mr, elt, elt_index, run_data[task_id]); } } EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END; @@ -174,7 +200,8 @@ BLI_INLINE void extract_iter_looptri_bm(const MeshRenderData *mr, BLI_INLINE void extract_iter_looptri_mesh(const MeshRenderData *mr, const ExtractTriMesh_Params *params, - const ExtractorRunDatas &all_extractors) + const ExtractorRunDatas &all_extractors, + const TaskId task_id) { ExtractorRunDatas extractors; all_extractors.filter_into(extractors, MR_ITER_LOOPTRI); @@ -182,7 +209,7 @@ BLI_INLINE void extract_iter_looptri_mesh(const MeshRenderData *mr, 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.user_data); + run_data.extractor->iter_looptri_mesh(mr, mlt, mlt_index, run_data[task_id]); } } EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END; @@ -190,7 +217,8 @@ BLI_INLINE void extract_iter_looptri_mesh(const MeshRenderData *mr, BLI_INLINE void extract_iter_poly_bm(const MeshRenderData *mr, const ExtractPolyBMesh_Params *params, - const ExtractorRunDatas &all_extractors) + const ExtractorRunDatas &all_extractors, + const TaskId task_id) { ExtractorRunDatas extractors; all_extractors.filter_into(extractors, MR_ITER_POLY); @@ -198,7 +226,7 @@ BLI_INLINE void extract_iter_poly_bm(const MeshRenderData *mr, 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.user_data); + run_data.extractor->iter_poly_bm(mr, f, f_index, run_data[task_id]); } } EXTRACT_POLY_FOREACH_BM_END; @@ -206,7 +234,8 @@ BLI_INLINE void extract_iter_poly_bm(const MeshRenderData *mr, BLI_INLINE void extract_iter_poly_mesh(const MeshRenderData *mr, const ExtractPolyMesh_Params *params, - const ExtractorRunDatas &all_extractors) + const ExtractorRunDatas &all_extractors, + const TaskId task_id) { ExtractorRunDatas extractors; all_extractors.filter_into(extractors, MR_ITER_POLY); @@ -214,7 +243,7 @@ BLI_INLINE void extract_iter_poly_mesh(const MeshRenderData *mr, 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.user_data); + run_data.extractor->iter_poly_mesh(mr, mp, mp_index, run_data[task_id]); } } EXTRACT_POLY_FOREACH_MESH_END; @@ -222,7 +251,8 @@ BLI_INLINE void extract_iter_poly_mesh(const MeshRenderData *mr, BLI_INLINE void extract_iter_ledge_bm(const MeshRenderData *mr, const ExtractLEdgeBMesh_Params *params, - const ExtractorRunDatas &all_extractors) + const ExtractorRunDatas &all_extractors, + const TaskId task_id) { ExtractorRunDatas extractors; all_extractors.filter_into(extractors, MR_ITER_LEDGE); @@ -230,7 +260,7 @@ BLI_INLINE void extract_iter_ledge_bm(const MeshRenderData *mr, 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.user_data); + run_data.extractor->iter_ledge_bm(mr, eed, ledge_index, run_data[task_id]); } } EXTRACT_LEDGE_FOREACH_BM_END; @@ -238,7 +268,8 @@ BLI_INLINE void extract_iter_ledge_bm(const MeshRenderData *mr, BLI_INLINE void extract_iter_ledge_mesh(const MeshRenderData *mr, const ExtractLEdgeMesh_Params *params, - const ExtractorRunDatas &all_extractors) + const ExtractorRunDatas &all_extractors, + const TaskId task_id) { ExtractorRunDatas extractors; all_extractors.filter_into(extractors, MR_ITER_LEDGE); @@ -246,7 +277,7 @@ BLI_INLINE void extract_iter_ledge_mesh(const MeshRenderData *mr, 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.user_data); + run_data.extractor->iter_ledge_mesh(mr, med, ledge_index, run_data[task_id]); } } EXTRACT_LEDGE_FOREACH_MESH_END; @@ -254,7 +285,8 @@ BLI_INLINE void extract_iter_ledge_mesh(const MeshRenderData *mr, BLI_INLINE void extract_iter_lvert_bm(const MeshRenderData *mr, const ExtractLVertBMesh_Params *params, - const ExtractorRunDatas &all_extractors) + const ExtractorRunDatas &all_extractors, + const TaskId task_id) { ExtractorRunDatas extractors; all_extractors.filter_into(extractors, MR_ITER_LVERT); @@ -262,7 +294,7 @@ BLI_INLINE void extract_iter_lvert_bm(const MeshRenderData *mr, 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.user_data); + run_data.extractor->iter_lvert_bm(mr, eve, lvert_index, run_data[task_id]); } } EXTRACT_LVERT_FOREACH_BM_END; @@ -270,7 +302,8 @@ BLI_INLINE void extract_iter_lvert_bm(const MeshRenderData *mr, BLI_INLINE void extract_iter_lvert_mesh(const MeshRenderData *mr, const ExtractLVertMesh_Params *params, - const ExtractorRunDatas &all_extractors) + const ExtractorRunDatas &all_extractors, + const TaskId task_id) { ExtractorRunDatas extractors; all_extractors.filter_into(extractors, MR_ITER_LVERT); @@ -278,7 +311,7 @@ BLI_INLINE void extract_iter_lvert_mesh(const MeshRenderData *mr, 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.user_data); + run_data.extractor->iter_lvert_mesh(mr, mv, lvert_index, run_data[task_id]); } } EXTRACT_LVERT_FOREACH_MESH_END; @@ -296,6 +329,35 @@ BLI_INLINE void extract_finish(const MeshRenderData *mr, } } +BLI_INLINE void extract_task_init(ExtractorRunDatas &extractors, const TaskLen task_len) +{ + 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; + } + } +} + +BLI_INLINE void extract_task_finish(ExtractorRunDatas &extractors, const TaskLen task_len) +{ + 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; + } + } + } +} + /* Single Thread. */ BLI_INLINE void extract_run_single_threaded(const MeshRenderData *mr, struct MeshBatchCache *cache, @@ -303,7 +365,11 @@ BLI_INLINE void extract_run_single_threaded(const MeshRenderData *mr, eMRIterType iter_type, MeshBufferCache *mbc) { + const TaskLen task_len = 1; + const TaskId task_id = 0; + extract_init(mr, cache, extractors, mbc); + extract_task_init(extractors, task_len); bool is_mesh = mr->extract_type != MR_EXTRACT_BMESH; if (iter_type & MR_ITER_LOOPTRI) { @@ -312,14 +378,14 @@ BLI_INLINE void extract_run_single_threaded(const MeshRenderData *mr, params.mlooptri = mr->mlooptri; params.tri_range[0] = 0; params.tri_range[1] = mr->tri_len; - extract_iter_looptri_mesh(mr, ¶ms, extractors); + 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); + extract_iter_looptri_bm(mr, ¶ms, extractors, task_id); } } if (iter_type & MR_ITER_POLY) { @@ -327,13 +393,13 @@ BLI_INLINE void extract_run_single_threaded(const MeshRenderData *mr, ExtractPolyMesh_Params params; params.poly_range[0] = 0; params.poly_range[1] = mr->poly_len; - extract_iter_poly_mesh(mr, ¶ms, extractors); + 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); + extract_iter_poly_bm(mr, ¶ms, extractors, task_id); } } if (iter_type & MR_ITER_LEDGE) { @@ -342,14 +408,14 @@ BLI_INLINE void extract_run_single_threaded(const MeshRenderData *mr, params.ledge = mr->ledges; params.ledge_range[0] = 0; params.ledge_range[1] = mr->edge_loose_len; - extract_iter_ledge_mesh(mr, ¶ms, extractors); + 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); + extract_iter_ledge_bm(mr, ¶ms, extractors, task_id); } } if (iter_type & MR_ITER_LVERT) { @@ -358,16 +424,17 @@ BLI_INLINE void extract_run_single_threaded(const MeshRenderData *mr, params.lvert = mr->lverts; params.lvert_range[0] = 0; params.lvert_range[1] = mr->vert_loose_len; - extract_iter_lvert_mesh(mr, ¶ms, extractors); + 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); + extract_iter_lvert_bm(mr, ¶ms, extractors, task_id); } } + extract_task_finish(extractors, task_len); extract_finish(mr, cache, extractors); } @@ -390,6 +457,13 @@ struct ExtractTaskData { 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; @@ -399,8 +473,14 @@ struct ExtractTaskData { struct MeshBatchCache *cache, ExtractorRunDatas *extractors, MeshBufferCache *mbc, - int32_t *task_counter) - : mr(mr), cache(cache), extractors(extractors), mbc(mbc), task_counter(task_counter) + 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(); }; @@ -417,17 +497,6 @@ struct ExtractTaskData { #endif }; -static ExtractTaskData *extract_extract_iter_task_data_create_mesh(const MeshRenderData *mr, - MeshBatchCache *cache, - ExtractorRunDatas *extractors, - MeshBufferCache *mbc, - int32_t *task_counter) - -{ - ExtractTaskData *taskdata = new ExtractTaskData(mr, cache, extractors, mbc, task_counter); - return taskdata; -} - static void extract_task_data_free(void *data) { ExtractTaskData *task_data = static_cast<ExtractTaskData *>(data); @@ -445,7 +514,8 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr, const eMRIterType iter_type, int start, int end, - ExtractorRunDatas &extractors) + ExtractorRunDatas &extractors, + const TaskId task_id) { switch (mr->extract_type) { case MR_EXTRACT_BMESH: @@ -454,27 +524,27 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr, 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); + 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); + 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); + 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); + extract_iter_lvert_bm(mr, ¶ms, extractors, task_id); } break; case MR_EXTRACT_MAPPED: @@ -484,27 +554,27 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr, 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); + 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); + 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); + 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); + extract_iter_lvert_mesh(mr, ¶ms, extractors, task_id); } break; } @@ -513,16 +583,19 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr, static void extract_task_init(ExtractTaskData *data) { 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); + 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); } } @@ -668,7 +741,8 @@ static void extract_range_task_create(struct TaskGraph *task_graph, int length) { taskdata = new ExtractTaskData(*taskdata); - atomic_add_and_fetch_int32(taskdata->task_counter, 1); + 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; @@ -900,8 +974,8 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, if (!extractor->use_threading) { ExtractorRunDatas *single_threaded_extractors = new ExtractorRunDatas(); single_threaded_extractors->append(extractor); - ExtractTaskData *taskdata = extract_extract_iter_task_data_create_mesh( - mr, cache, single_threaded_extractors, mbc, nullptr); + 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); BLI_task_graph_edge_create(task_node_mesh_render_data, task_node); @@ -920,13 +994,19 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, */ 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 = extract_extract_iter_task_data_create_mesh( - mr, cache, multi_threaded_extractors, mbc, &user_data_init_task_data->task_counter); + 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); @@ -941,8 +1021,7 @@ 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 = extract_extract_iter_task_data_create_mesh( - mr, cache, extractors_copy, mbc, nullptr); + ExtractTaskData *taskdata = new ExtractTaskData(mr, cache, extractors_copy, mbc, nullptr, 1); 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); |