Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/intern/draw_cache_extract_mesh.cc')
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.cc817
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, &params, 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, &params, 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, &params, extractors, task_id);
- }
- else {
- ExtractPolyBMesh_Params params;
- params.poly_range[0] = 0;
- params.poly_range[1] = mr->poly_len;
- extract_iter_poly_bm(mr, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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);
}