diff options
author | Jeroen Bakker <jbakker> | 2020-06-15 17:46:56 +0300 |
---|---|---|
committer | Jeroen Bakker <j.bakker@atmind.nl> | 2020-06-15 17:47:21 +0300 |
commit | 624994caa2544823a1c89a868e9bf6760f525269 (patch) | |
tree | 8a907f7d8b17914a46dbb128af90f2967c816903 /source | |
parent | df1ff76ee207f97fd274f3400c305e1fd8c19f19 (diff) |
Fix T77496: Bones Custom Shapes Wires not drawn
Lines loose extraction cannot happen on the fly as the render data isn't
complete. This patch will do the lines loose subbuffer extraction as a
simple task and not on the fly.
This patch introduces 2 sub-types of tasks that are executed single threaded.
`EXTRACT_MESH_EXTRACT` would do the extraction using Mesh/BMesh geometry.
`EXTRACT_LINES_LOOSE` creates the `lines_loose` subbuffer from already cached
`lines` IBO.
Reviewed By: Clément Foucault
Differential Revision: https://developer.blender.org/D7964
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/intern/draw_cache_extract_mesh.c | 107 |
1 files changed, 70 insertions, 37 deletions
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index 6013bdb2883..f3dc8f0fd2a 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -4558,10 +4558,16 @@ typedef struct ExtractUserData { void *user_data; } ExtractUserData; +typedef enum ExtractTaskDataType { + EXTRACT_MESH_EXTRACT, + EXTRACT_LINES_LOOSE, +} ExtractTaskDataType; + typedef struct ExtractTaskData { void *next, *prev; const MeshRenderData *mr; const MeshExtract *extract; + ExtractTaskDataType tasktype; eMRIterType iter_type; int start, end; /** Decremented each time a task is finished. */ @@ -4570,6 +4576,41 @@ typedef struct ExtractTaskData { ExtractUserData *user_data; } ExtractTaskData; +static ExtractTaskData *extract_task_data_create_mesh_extract(const MeshRenderData *mr, + const MeshExtract *extract, + void *buf, + int32_t *task_counter) +{ + ExtractTaskData *taskdata = MEM_mallocN(sizeof(*taskdata), __func__); + taskdata->next = NULL; + taskdata->prev = NULL; + taskdata->tasktype = EXTRACT_MESH_EXTRACT; + taskdata->mr = mr; + taskdata->extract = extract; + taskdata->buf = buf; + + /* ExtractUserData is shared between the iterations as it holds counters to detect if the + * extraction is finished. To make sure the duplication of the userdata does not create a new + * instance of the counters we allocate the userdata in its own container. + * + * This structure makes sure that when extract_init is called, that the user data of all + * iterations are updated. */ + taskdata->user_data = MEM_callocN(sizeof(ExtractUserData), __func__); + taskdata->iter_type = mesh_extract_iter_type(extract); + taskdata->task_counter = task_counter; + taskdata->start = 0; + taskdata->end = INT_MAX; + return taskdata; +} + +static ExtractTaskData *extract_task_data_create_lines_loose(const MeshRenderData *mr) +{ + ExtractTaskData *taskdata = MEM_callocN(sizeof(*taskdata), __func__); + taskdata->tasktype = EXTRACT_LINES_LOOSE; + taskdata->mr = mr; + return taskdata; +} + static void extract_task_data_free(void *data) { ExtractTaskData *task_data = data; @@ -4655,23 +4696,30 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr, static void extract_init(ExtractTaskData *data) { - data->user_data->user_data = data->extract->init(data->mr, data->buf); + if (data->tasktype == EXTRACT_MESH_EXTRACT) { + data->user_data->user_data = data->extract->init(data->mr, data->buf); + } } static void extract_run(void *__restrict taskdata) { ExtractTaskData *data = (ExtractTaskData *)taskdata; - mesh_extract_iter(data->mr, - data->iter_type, - data->start, - data->end, - data->extract, - data->user_data->user_data); - - /* 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 && data->extract->finish != NULL) { - data->extract->finish(data->mr, data->buf, data->user_data->user_data); + if (data->tasktype == EXTRACT_MESH_EXTRACT) { + mesh_extract_iter(data->mr, + data->iter_type, + data->start, + data->end, + data->extract, + data->user_data->user_data); + + /* 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 && data->extract->finish != NULL) { + data->extract->finish(data->mr, data->buf, data->user_data->user_data); + } + } + else if (data->tasktype == EXTRACT_LINES_LOOSE) { + extract_lines_loose_subbuffer(data->mr); } } @@ -4695,7 +4743,8 @@ typedef struct MeshRenderDataUpdateTaskData { static void mesh_render_data_update_task_data_free(MeshRenderDataUpdateTaskData *taskdata) { BLI_assert(taskdata); - mesh_render_data_free(taskdata->mr); + MeshRenderData *mr = taskdata->mr; + mesh_render_data_free(mr); MEM_freeN(taskdata); } @@ -4851,24 +4900,8 @@ static void extract_task_create(struct TaskGraph *task_graph, } /* Divide extraction of the VBO/IBO into sensible chunks of works. */ - ExtractTaskData *taskdata = MEM_mallocN(sizeof(*taskdata), "ExtractTaskData"); - taskdata->next = NULL; - taskdata->prev = NULL; - taskdata->mr = mr; - taskdata->extract = extract; - taskdata->buf = buf; - - /* ExtractUserData is shared between the iterations as it holds counters to detect if the - * extraction is finished. To make sure the duplication of the userdata does not create a new - * instance of the counters we allocate the userdata in its own container. - * - * This structure makes sure that when extract_init is called, that the user data of all - * iterations are updated. */ - taskdata->user_data = MEM_callocN(sizeof(ExtractUserData), __func__); - taskdata->iter_type = mesh_extract_iter_type(extract); - taskdata->task_counter = task_counter; - taskdata->start = 0; - taskdata->end = INT_MAX; + ExtractTaskData *taskdata = extract_task_data_create_mesh_extract( + mr, extract, buf, task_counter); /* Simple heuristic. */ const int chunk_size = 8192; @@ -5009,6 +5042,10 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, TEST_ASSIGN(IBO, ibo, edituv_points); TEST_ASSIGN(IBO, ibo, edituv_fdots); + if (do_lines_loose_subbuffer) { + iter_flag |= MR_ITER_LEDGE; + } + #undef TEST_ASSIGN #ifdef DEBUG_TIME @@ -5106,12 +5143,8 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, } else { if (do_lines_loose_subbuffer) { - /* When `lines_loose` is requested without `lines` we can create the sub-buffer on the fly as - * the `lines` buffer should then already be up-to-date. - * (see `DRW_batch_requested(cache->batch.loose_edges, GPU_PRIM_LINES)` in - * `DRW_mesh_batch_cache_create_requested`). - */ - extract_lines_loose_subbuffer(mr); + ExtractTaskData *taskdata = extract_task_data_create_lines_loose(mr); + BLI_addtail(&single_threaded_task_data->task_datas, taskdata); } } EXTRACT(ibo, points); |