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:
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.cc189
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh_private.h6
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc21
-rw-r--r--source/blender/gpu/CMakeLists.txt2
-rw-r--r--source/blender/gpu/GPU_index_buffer.h14
-rw-r--r--source/blender/gpu/intern/gpu_index_buffer.cc19
-rw-r--r--source/blender/gpu/tests/gpu_index_buffer_test.cc47
7 files changed, 241 insertions, 57 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, &params, extractors);
+ 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);
+ extract_iter_looptri_bm(mr, &params, 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, &params, extractors);
+ 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);
+ extract_iter_poly_bm(mr, &params, 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, &params, extractors);
+ 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);
+ extract_iter_ledge_bm(mr, &params, 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, &params, extractors);
+ 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);
+ extract_iter_lvert_bm(mr, &params, 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, &params, extractors);
+ 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);
+ 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);
+ 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);
+ extract_iter_lvert_bm(mr, &params, 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, &params, extractors);
+ 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);
+ 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);
+ 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);
+ extract_iter_lvert_mesh(mr, &params, 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);
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 a1249203060..e4ea3e44843 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh_private.h
+++ b/source/blender/draw/intern/draw_cache_extract_mesh_private.h
@@ -406,7 +406,6 @@ typedef void(ExtractLVertMeshFn)(const MeshRenderData *mr,
/* ---------------------------------------------------------------------- */
/** \name Mesh Elements Extract Struct
* \{ */
-
/* TODO(jbakker): move parameters inside a struct. */
typedef void *(ExtractInitFn)(const MeshRenderData *mr,
struct MeshBatchCache *cache,
@@ -415,10 +414,14 @@ typedef void(ExtractFinishFn)(const MeshRenderData *mr,
struct MeshBatchCache *cache,
void *buffer,
void *data);
+typedef void *(ExtractTaskInitFn)(void *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;
@@ -429,6 +432,7 @@ typedef struct MeshExtract {
ExtractLVertBMeshFn *iter_lvert_bm;
ExtractLVertMeshFn *iter_lvert_mesh;
/** Executed on one worker thread after all elements iterations. */
+ ExtractTaskFinishFn *task_finish;
ExtractFinishFn *finish;
/** Used to request common data. */
eMRDataType data_type;
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 d749a3ab8d1..9220198d799 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
@@ -41,6 +41,15 @@ static void *extract_points_init(const MeshRenderData *mr,
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)
{
const int v_index = BM_elem_index_get(eve);
@@ -137,6 +146,14 @@ 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)
+{
+ 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);
+}
+
static void extract_points_finish(const MeshRenderData *UNUSED(mr),
struct MeshBatchCache *UNUSED(cache),
void *buf,
@@ -152,15 +169,17 @@ 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.finish = extract_points_finish;
+ extractor.use_threading = true;
extractor.data_type = MR_DATA_NONE;
- extractor.use_threading = false;
extractor.mesh_buffer_offset = offsetof(MeshBufferCache, ibo.points);
return extractor;
}
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index cf6009c2881..8468985309f 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -394,6 +394,8 @@ if(WITH_GTESTS)
if(WITH_OPENGL_DRAW_TESTS)
set(TEST_SRC
tests/gpu_testing.cc
+
+ tests/gpu_index_buffer_test.cc
tests/gpu_shader_test.cc
tests/gpu_testing.hh
diff --git a/source/blender/gpu/GPU_index_buffer.h b/source/blender/gpu/GPU_index_buffer.h
index 4e8d854c7ce..03d60c60b4b 100644
--- a/source/blender/gpu/GPU_index_buffer.h
+++ b/source/blender/gpu/GPU_index_buffer.h
@@ -44,6 +44,7 @@ typedef struct GPUIndexBufBuilder {
uint index_max;
GPUPrimType prim_type;
uint32_t *data;
+ const struct GPUIndexBufBuilder *parent;
} GPUIndexBufBuilder;
/* supports all primitive types. */
@@ -53,6 +54,19 @@ void GPU_indexbuf_init_ex(GPUIndexBufBuilder *, GPUPrimType, uint index_len, uin
void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len);
GPUIndexBuf *GPU_indexbuf_build_on_device(uint index_len);
+/*
+ * Thread safe sub builders.
+ *
+ * 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.
+ */
+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_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 9f283a3a944..3cdcaac5544 100644
--- a/source/blender/gpu/intern/gpu_index_buffer.cc
+++ b/source/blender/gpu/intern/gpu_index_buffer.cc
@@ -25,6 +25,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_math_base.h"
#include "BLI_utildefines.h"
#include "gpu_backend.hh"
@@ -56,6 +57,7 @@ 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,
@@ -78,6 +80,23 @@ GPUIndexBuf *GPU_indexbuf_build_on_device(uint index_len)
return elem_;
}
+void GPU_indexbuf_subbuilder_init(const GPUIndexBufBuilder *parent_builder,
+ GPUIndexBufBuilder *sub_builder)
+{
+ 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);
+}
+
void GPU_indexbuf_add_generic_vert(GPUIndexBufBuilder *builder, uint v)
{
#if TRUST_NO_ONE
diff --git a/source/blender/gpu/tests/gpu_index_buffer_test.cc b/source/blender/gpu/tests/gpu_index_buffer_test.cc
new file mode 100644
index 00000000000..ebc110056e3
--- /dev/null
+++ b/source/blender/gpu/tests/gpu_index_buffer_test.cc
@@ -0,0 +1,47 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "GPU_index_buffer.h"
+
+#include "gpu_testing.hh"
+
+namespace blender::gpu::tests {
+
+TEST_F(GPUTest, gpu_index_buffer_subbuilders)
+{
+ const uint num_subbuilders = 10;
+ const uint verts_per_subbuilders = 100;
+ const uint vertex_len = num_subbuilders * verts_per_subbuilders;
+
+ GPUIndexBufBuilder builder;
+ GPU_indexbuf_init(&builder, GPU_PRIM_POINTS, vertex_len, vertex_len);
+
+ GPUIndexBufBuilder subbuilders[num_subbuilders];
+ for (int subbuilder_index = 0; subbuilder_index < num_subbuilders; subbuilder_index++) {
+ GPU_indexbuf_subbuilder_init(&builder, &subbuilders[subbuilder_index]);
+ }
+
+ for (int subbuilder_index = 0; subbuilder_index < num_subbuilders; subbuilder_index++) {
+ GPUIndexBufBuilder &subbuilder = subbuilders[subbuilder_index];
+ for (int subbuilder_vert_index = 0; subbuilder_vert_index < verts_per_subbuilders;
+ subbuilder_vert_index++) {
+ int vert_index_to_update = subbuilder_index * verts_per_subbuilders + subbuilder_vert_index;
+ GPU_indexbuf_set_point_vert(&subbuilder, vert_index_to_update, vert_index_to_update);
+ }
+ }
+
+ for (int subbuilder_index = 0; subbuilder_index < num_subbuilders; subbuilder_index++) {
+ EXPECT_EQ(builder.index_len, subbuilder_index * verts_per_subbuilders);
+ GPU_indexbuf_subbuilder_finish(&builder, &subbuilders[subbuilder_index]);
+ EXPECT_EQ(builder.index_len, (subbuilder_index + 1) * verts_per_subbuilders);
+ }
+
+ GPUIndexBuf *index_buffer = GPU_indexbuf_build(&builder);
+ EXPECT_NE(index_buffer, nullptr);
+ GPU_INDEXBUF_DISCARD_SAFE(index_buffer);
+}
+
+} // namespace blender::gpu::tests