diff options
Diffstat (limited to 'source/blender/draw')
10 files changed, 313 insertions, 222 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index 95fd918f8c1..481dec340ba 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -510,7 +510,7 @@ static void drw_shgroup_bone_envelope(ArmatureDrawContext *ctx, /* Custom (geometry) */ extern void drw_batch_cache_validate(Object *custom); -extern void drw_batch_cache_generate_requested(Object *custom); +extern void drw_batch_cache_generate_requested_delayed(Object *custom); BLI_INLINE DRWCallBuffer *custom_bone_instance_shgroup(ArmatureDrawContext *ctx, DRWShadingGroup *grp, @@ -567,7 +567,7 @@ static void drw_shgroup_bone_custom_solid(ArmatureDrawContext *ctx, } /* TODO(fclem) needs to be moved elsewhere. */ - drw_batch_cache_generate_requested(custom); + drw_batch_cache_generate_requested_delayed(custom); } static void drw_shgroup_bone_custom_wire(ArmatureDrawContext *ctx, @@ -591,7 +591,7 @@ static void drw_shgroup_bone_custom_wire(ArmatureDrawContext *ctx, } /* TODO(fclem) needs to be moved elsewhere. */ - drw_batch_cache_generate_requested(custom); + drw_batch_cache_generate_requested_delayed(custom); } static void drw_shgroup_bone_custom_empty(ArmatureDrawContext *ctx, diff --git a/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl b/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl index 306fbb473ee..a400aadb052 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl @@ -52,7 +52,7 @@ void main() bool edge_selected = (((vertFlag[1] | vertFlag[0]) & VERT_SELECTED) != 0); bool handle_selected = (showCurveHandles && - (((vertFlag[1] | vertFlag[0]) & HANDLE_SELECTED) != 0)); + (((vertFlag[1] | vertFlag[0]) & VERT_SELECTED_BEZT_HANDLE) != 0)); /* If handle type is only selected and the edge is not selected, don't show. */ if ((curveHandleDisplay != CURVE_HANDLE_ALL) && (!handle_selected)) { diff --git a/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl index b1e1c0879a5..a811fcca0d4 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl @@ -37,7 +37,7 @@ void main() #endif bool show_handle = showCurveHandles; - if ((curveHandleDisplay == CURVE_HANDLE_SELECTED) && ((data & HANDLE_SELECTED) == 0)) { + if ((curveHandleDisplay == CURVE_HANDLE_SELECTED) && ((data & VERT_SELECTED_BEZT_HANDLE) == 0)) { show_handle = false; } diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index c23ea3d7c82..af5b9cd05dd 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -3552,6 +3552,11 @@ void drw_batch_cache_generate_requested(Object *ob) } } +void drw_batch_cache_generate_requested_delayed(Object *ob) +{ + BLI_gset_add(DST.delayed_extraction, ob); +} + void DRW_batch_cache_free_old(Object *ob, int ctime) { struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index 06462d5b9c5..f3dc8f0fd2a 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -134,6 +134,183 @@ typedef struct MeshRenderData { float (*poly_normals)[3]; int *lverts, *ledges; } MeshRenderData; + +static void mesh_render_data_update_loose_geom(MeshRenderData *mr, + const eMRIterType iter_type, + const eMRDataType UNUSED(data_flag)) +{ + if (mr->extract_type != MR_EXTRACT_BMESH) { + /* Mesh */ + if (iter_type & (MR_ITER_LEDGE | MR_ITER_LVERT)) { + mr->vert_loose_len = 0; + mr->edge_loose_len = 0; + + BLI_bitmap *lvert_map = BLI_BITMAP_NEW(mr->vert_len, "lvert map"); + + mr->ledges = MEM_mallocN(mr->edge_len * sizeof(int), __func__); + const MEdge *medge = mr->medge; + for (int e = 0; e < mr->edge_len; e++, medge++) { + if (medge->flag & ME_LOOSEEDGE) { + mr->ledges[mr->edge_loose_len++] = e; + } + /* Tag verts as not loose. */ + BLI_BITMAP_ENABLE(lvert_map, medge->v1); + BLI_BITMAP_ENABLE(lvert_map, medge->v2); + } + if (mr->edge_loose_len < mr->edge_len) { + mr->ledges = MEM_reallocN(mr->ledges, mr->edge_loose_len * sizeof(*mr->ledges)); + } + + mr->lverts = MEM_mallocN(mr->vert_len * sizeof(*mr->lverts), __func__); + for (int v = 0; v < mr->vert_len; v++) { + if (!BLI_BITMAP_TEST(lvert_map, v)) { + mr->lverts[mr->vert_loose_len++] = v; + } + } + if (mr->vert_loose_len < mr->vert_len) { + mr->lverts = MEM_reallocN(mr->lverts, mr->vert_loose_len * sizeof(*mr->lverts)); + } + + MEM_freeN(lvert_map); + + mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2; + } + } + else { + /* BMesh */ + BMesh *bm = mr->bm; + if (iter_type & (MR_ITER_LEDGE | MR_ITER_LVERT)) { + int elem_id; + BMIter iter; + BMVert *eve; + BMEdge *ede; + mr->vert_loose_len = 0; + mr->edge_loose_len = 0; + + mr->lverts = MEM_mallocN(mr->vert_len * sizeof(*mr->lverts), __func__); + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, elem_id) { + if (eve->e == NULL) { + mr->lverts[mr->vert_loose_len++] = elem_id; + } + } + if (mr->vert_loose_len < mr->vert_len) { + mr->lverts = MEM_reallocN(mr->lverts, mr->vert_loose_len * sizeof(*mr->lverts)); + } + + mr->ledges = MEM_mallocN(mr->edge_len * sizeof(*mr->ledges), __func__); + BM_ITER_MESH_INDEX (ede, &iter, bm, BM_EDGES_OF_MESH, elem_id) { + if (ede->l == NULL) { + mr->ledges[mr->edge_loose_len++] = elem_id; + } + } + if (mr->edge_loose_len < mr->edge_len) { + mr->ledges = MEM_reallocN(mr->ledges, mr->edge_loose_len * sizeof(*mr->ledges)); + } + + mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2; + } + } +} + +/* Part of the creation of the MeshRenderData that happens in a thread. */ +static void mesh_render_data_update_looptris(MeshRenderData *mr, + const eMRIterType iter_type, + const eMRDataType data_flag) +{ + Mesh *me = mr->me; + if (mr->extract_type != MR_EXTRACT_BMESH) { + /* Mesh */ + if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) { + mr->mlooptri = MEM_mallocN(sizeof(*mr->mlooptri) * mr->tri_len, "MR_DATATYPE_LOOPTRI"); + BKE_mesh_recalc_looptri( + me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mr->mlooptri); + } + } + else { + /* BMesh */ + if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) { + /* Edit mode ensures this is valid, no need to calculate. */ + BLI_assert((mr->bm->totloop == 0) || (mr->edit_bmesh->looptris != NULL)); + } + } +} + +static void mesh_render_data_update_normals(MeshRenderData *mr, + const eMRIterType UNUSED(iter_type), + const eMRDataType data_flag) +{ + Mesh *me = mr->me; + const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0; + const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI; + + if (mr->extract_type != MR_EXTRACT_BMESH) { + /* Mesh */ + if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) { + mr->poly_normals = MEM_mallocN(sizeof(*mr->poly_normals) * mr->poly_len, __func__); + BKE_mesh_calc_normals_poly((MVert *)mr->mvert, + NULL, + mr->vert_len, + mr->mloop, + mr->mpoly, + mr->loop_len, + mr->poly_len, + mr->poly_normals, + true); + } + if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { + mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__); + short(*clnors)[2] = CustomData_get_layer(&mr->me->ldata, CD_CUSTOMLOOPNORMAL); + BKE_mesh_normals_loop_split(mr->me->mvert, + mr->vert_len, + mr->me->medge, + mr->edge_len, + mr->me->mloop, + mr->loop_normals, + mr->loop_len, + mr->me->mpoly, + mr->poly_normals, + mr->poly_len, + is_auto_smooth, + split_angle, + NULL, + clnors, + NULL); + } + } + else { + /* BMesh */ + if (data_flag & MR_DATA_POLY_NOR) { + /* Use bmface->no instead. */ + } + if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { + + const float(*vert_coords)[3] = NULL; + const float(*vert_normals)[3] = NULL; + const float(*poly_normals)[3] = NULL; + + if (mr->edit_data && mr->edit_data->vertexCos) { + vert_coords = mr->bm_vert_coords; + vert_normals = mr->bm_vert_normals; + poly_normals = mr->bm_poly_normals; + } + + mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__); + int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL); + BM_loops_calc_normal_vcos(mr->bm, + vert_coords, + vert_normals, + poly_normals, + is_auto_smooth, + split_angle, + mr->loop_normals, + NULL, + NULL, + clnors_offset, + false); + } + } +} + static MeshRenderData *mesh_render_data_create(Mesh *me, const bool is_editmode, const bool is_paint_mode, @@ -141,7 +318,9 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const bool do_final, const bool do_uvedit, const DRW_MeshCDMask *UNUSED(cd_used), - const ToolSettings *ts) + const ToolSettings *ts, + const eMRIterType iter_type, + const eMRDataType data_flag) { MeshRenderData *mr = MEM_callocN(sizeof(*mr), __func__); mr->toolsettings = ts; @@ -249,165 +428,11 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, mr->poly_len = bm->totface; mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len); } + mesh_render_data_update_loose_geom(mr, iter_type, data_flag); return mr; } -/* Part of the creation of the MeshRenderData that happens in a thread. */ -static void mesh_render_data_update(MeshRenderData *mr, - const eMRIterType iter_type, - const eMRDataType data_flag) -{ - Mesh *me = mr->me; - const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0; - const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI; - - if (mr->extract_type != MR_EXTRACT_BMESH) { - /* Mesh */ - if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) { - mr->poly_normals = MEM_mallocN(sizeof(*mr->poly_normals) * mr->poly_len, __func__); - BKE_mesh_calc_normals_poly((MVert *)mr->mvert, - NULL, - mr->vert_len, - mr->mloop, - mr->mpoly, - mr->loop_len, - mr->poly_len, - mr->poly_normals, - true); - } - if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { - mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__); - short(*clnors)[2] = CustomData_get_layer(&mr->me->ldata, CD_CUSTOMLOOPNORMAL); - BKE_mesh_normals_loop_split(mr->me->mvert, - mr->vert_len, - mr->me->medge, - mr->edge_len, - mr->me->mloop, - mr->loop_normals, - mr->loop_len, - mr->me->mpoly, - mr->poly_normals, - mr->poly_len, - is_auto_smooth, - split_angle, - NULL, - clnors, - NULL); - } - if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) { - mr->mlooptri = MEM_mallocN(sizeof(*mr->mlooptri) * mr->tri_len, "MR_DATATYPE_LOOPTRI"); - BKE_mesh_recalc_looptri(mr->me->mloop, - mr->me->mpoly, - mr->me->mvert, - mr->me->totloop, - mr->me->totpoly, - mr->mlooptri); - } - if (iter_type & (MR_ITER_LEDGE | MR_ITER_LVERT)) { - mr->vert_loose_len = 0; - mr->edge_loose_len = 0; - - BLI_bitmap *lvert_map = BLI_BITMAP_NEW(mr->vert_len, "lvert map"); - - mr->ledges = MEM_mallocN(mr->edge_len * sizeof(int), __func__); - const MEdge *medge = mr->medge; - for (int e = 0; e < mr->edge_len; e++, medge++) { - if (medge->flag & ME_LOOSEEDGE) { - mr->ledges[mr->edge_loose_len++] = e; - } - /* Tag verts as not loose. */ - BLI_BITMAP_ENABLE(lvert_map, medge->v1); - BLI_BITMAP_ENABLE(lvert_map, medge->v2); - } - if (mr->edge_loose_len < mr->edge_len) { - mr->ledges = MEM_reallocN(mr->ledges, mr->edge_loose_len * sizeof(*mr->ledges)); - } - - mr->lverts = MEM_mallocN(mr->vert_len * sizeof(*mr->lverts), __func__); - for (int v = 0; v < mr->vert_len; v++) { - if (!BLI_BITMAP_TEST(lvert_map, v)) { - mr->lverts[mr->vert_loose_len++] = v; - } - } - if (mr->vert_loose_len < mr->vert_len) { - mr->lverts = MEM_reallocN(mr->lverts, mr->vert_loose_len * sizeof(*mr->lverts)); - } - - MEM_freeN(lvert_map); - - mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2; - } - } - else { - /* BMesh */ - BMesh *bm = mr->bm; - if (data_flag & MR_DATA_POLY_NOR) { - /* Use bmface->no instead. */ - } - if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { - - const float(*vert_coords)[3] = NULL; - const float(*vert_normals)[3] = NULL; - const float(*poly_normals)[3] = NULL; - - if (mr->edit_data && mr->edit_data->vertexCos) { - vert_coords = mr->bm_vert_coords; - vert_normals = mr->bm_vert_normals; - poly_normals = mr->bm_poly_normals; - } - - mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__); - int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL); - BM_loops_calc_normal_vcos(mr->bm, - vert_coords, - vert_normals, - poly_normals, - is_auto_smooth, - split_angle, - mr->loop_normals, - NULL, - NULL, - clnors_offset, - false); - } - if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) { - /* Edit mode ensures this is valid, no need to calculate. */ - BLI_assert((bm->totloop == 0) || (mr->edit_bmesh->looptris != NULL)); - } - if (iter_type & (MR_ITER_LEDGE | MR_ITER_LVERT)) { - int elem_id; - BMIter iter; - BMVert *eve; - BMEdge *ede; - mr->vert_loose_len = 0; - mr->edge_loose_len = 0; - - mr->lverts = MEM_mallocN(mr->vert_len * sizeof(*mr->lverts), __func__); - BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, elem_id) { - if (eve->e == NULL) { - mr->lverts[mr->vert_loose_len++] = elem_id; - } - } - if (mr->vert_loose_len < mr->vert_len) { - mr->lverts = MEM_reallocN(mr->lverts, mr->vert_loose_len * sizeof(*mr->lverts)); - } - - mr->ledges = MEM_mallocN(mr->edge_len * sizeof(*mr->ledges), __func__); - BM_ITER_MESH_INDEX (ede, &iter, bm, BM_EDGES_OF_MESH, elem_id) { - if (ede->l == NULL) { - mr->ledges[mr->edge_loose_len++] = elem_id; - } - } - if (mr->edge_loose_len < mr->edge_len) { - mr->ledges = MEM_reallocN(mr->ledges, mr->edge_loose_len * sizeof(*mr->ledges)); - } - - mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2; - } - } -} - static void mesh_render_data_free(MeshRenderData *mr) { MEM_SAFE_FREE(mr->mlooptri); @@ -4533,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. */ @@ -4545,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; @@ -4630,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); } } @@ -4670,15 +4743,20 @@ 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); } static void mesh_extract_render_data_node_exec(void *__restrict task_data) { MeshRenderDataUpdateTaskData *update_task_data = task_data; - mesh_render_data_update( - update_task_data->mr, update_task_data->iter_type, update_task_data->data_flag); + MeshRenderData *mr = update_task_data->mr; + const eMRIterType iter_type = update_task_data->iter_type; + const eMRDataType data_flag = update_task_data->data_flag; + + mesh_render_data_update_normals(mr, iter_type, data_flag); + mesh_render_data_update_looptris(mr, iter_type, data_flag); } static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *task_graph, @@ -4822,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; @@ -4980,14 +5042,26 @@ 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 double rdata_start = PIL_check_seconds_timer(); #endif - MeshRenderData *mr = mesh_render_data_create( - me, is_editmode, is_paint_mode, obmat, do_final, do_uvedit, cd_layer_used, ts); + MeshRenderData *mr = mesh_render_data_create(me, + is_editmode, + is_paint_mode, + obmat, + do_final, + do_uvedit, + cd_layer_used, + ts, + iter_flag, + data_flag); mr->cache = cache; /* HACK */ mr->use_hide = use_hide; mr->use_subsurf_fdots = use_subsurf_fdots; @@ -5069,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); diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 80649143537..191d75342d0 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -201,18 +201,19 @@ struct GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis(struct Mesh *me); int DRW_mesh_material_count_get(struct Mesh *me); +/* See 'common_globals_lib.glsl' for duplicate defines. */ + /* Edit mesh bitflags (is this the right place?) */ enum { VFLAG_VERT_ACTIVE = 1 << 0, VFLAG_VERT_SELECTED = 1 << 1, - VFLAG_EDGE_ACTIVE = 1 << 2, - VFLAG_EDGE_SELECTED = 1 << 3, - VFLAG_EDGE_SEAM = 1 << 4, - VFLAG_EDGE_SHARP = 1 << 5, - VFLAG_EDGE_FREESTYLE = 1 << 6, - VFLAG_HANDLE_SELECTED = 1 << 7, - /* Beware to not go over 1 << 7 (it's a byte flag) - * (see gpu_shader_edit_mesh_overlay_geom.glsl) */ + VFLAG_VERT_SELECTED_BEZT_HANDLE = 1 << 2, + VFLAG_EDGE_ACTIVE = 1 << 3, + VFLAG_EDGE_SELECTED = 1 << 4, + VFLAG_EDGE_SEAM = 1 << 5, + VFLAG_EDGE_SHARP = 1 << 6, + VFLAG_EDGE_FREESTYLE = 1 << 7, + /* Beware to not go over 1 << 7 (it's a byte flag). */ }; enum { @@ -224,8 +225,7 @@ enum { VFLAG_EDGE_UV_SELECT = 1 << 5, VFLAG_FACE_UV_ACTIVE = 1 << 6, VFLAG_FACE_UV_SELECT = 1 << 7, - /* Beware to not go over 1 << 7 (it's a byte flag) - * (see gpu_shader_edit_mesh_overlay_geom.glsl) */ + /* Beware to not go over 1 << 7 (it's a byte flag). */ }; /* Particles */ diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c index c6112994b65..8798549a416 100644 --- a/source/blender/draw/intern/draw_cache_impl_curve.c +++ b/source/blender/draw/intern/draw_cache_impl_curve.c @@ -47,6 +47,7 @@ #include "draw_cache_impl.h" /* own include */ +/* See: edit_curve_point_vert.glsl for duplicate includes. */ #define SELECT 1 #define ACTIVE_NURB 1 << 2 #define BEZIER_HANDLE 1 << 3 @@ -698,7 +699,9 @@ static char beztriple_vflag_get(CurveRenderData *rdata, SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert && nu_id == rdata->actnu), VFLAG_VERT_ACTIVE); SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB); SET_FLAG_FROM_TEST(vflag, handle_point, BEZIER_HANDLE); - SET_FLAG_FROM_TEST(vflag, handle_selected, VFLAG_HANDLE_SELECTED); + SET_FLAG_FROM_TEST(vflag, handle_selected, VFLAG_VERT_SELECTED_BEZT_HANDLE); + /* Setting flags that overlap with will cause the color id not to work properly. */ + BLI_assert((vflag >> COLOR_SHIFT) == 0); /* handle color id */ vflag |= col_id << COLOR_SHIFT; return vflag; @@ -711,6 +714,8 @@ static char bpoint_vflag_get(CurveRenderData *rdata, char flag, int v_idx, int n SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert && nu_id == rdata->actnu), VFLAG_VERT_ACTIVE); SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB); SET_FLAG_FROM_TEST(vflag, ((u % 2) == 0), EVEN_U_BIT); + /* Setting flags that overlap with will cause the color id not to work properly. */ + BLI_assert((vflag >> COLOR_SHIFT) == 0); vflag |= COLOR_NURB_ULINE_ID << COLOR_SHIFT; return vflag; } diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 2ba766f4729..10ef8d9c4c8 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -132,11 +132,17 @@ static void drw_task_graph_init(void) { BLI_assert(DST.task_graph == NULL); DST.task_graph = BLI_task_graph_create(); + DST.delayed_extraction = BLI_gset_ptr_new(__func__); } static void drw_task_graph_deinit(void) { BLI_task_graph_work_and_wait(DST.task_graph); + + BLI_gset_free(DST.delayed_extraction, (void (*)(void *key))drw_batch_cache_generate_requested); + DST.delayed_extraction = NULL; + BLI_task_graph_work_and_wait(DST.task_graph); + BLI_task_graph_free(DST.task_graph); DST.task_graph = NULL; } @@ -1486,6 +1492,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, drw_duplidata_free(); drw_engines_cache_finish(); + drw_task_graph_deinit(); DRW_render_instance_buffer_finish(); #ifdef USE_PROFILE @@ -1494,7 +1501,6 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, #endif } - drw_task_graph_deinit(); DRW_stats_begin(); GPU_framebuffer_bind(DST.default_framebuffer); @@ -2292,9 +2298,9 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph, drw_duplidata_free(); drw_engines_cache_finish(); + drw_task_graph_deinit(); DRW_render_instance_buffer_finish(); } - drw_task_graph_deinit(); /* Start Drawing */ DRW_state_reset(); @@ -2411,6 +2417,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons drw_engines_cache_finish(); + drw_task_graph_deinit(); #if 0 /* This is a workaround to a nasty bug that seems to be a nasty driver bug. (See T69377) */ DRW_render_instance_buffer_finish(); #else @@ -2419,7 +2426,6 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons drw_resource_buffer_finish(DST.vmempool); #endif } - drw_task_graph_deinit(); /* Start Drawing */ DRW_state_reset(); diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 6cae2a4f9f6..31a2dd7f0fe 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -548,6 +548,8 @@ typedef struct DRWManager { #endif struct TaskGraph *task_graph; + /* Contains list of objects that needs to be extracted from other objects. */ + struct GSet *delayed_extraction; /* ---------- Nothing after this point is cleared after use ----------- */ @@ -585,6 +587,7 @@ eDRWCommandType command_type_get(uint64_t *command_type_bits, int index); void drw_batch_cache_validate(Object *ob); void drw_batch_cache_generate_requested(struct Object *ob); +void drw_batch_cache_generate_requested_delayed(Object *ob); void drw_resource_buffer_finish(ViewportMemoryPool *vmempool); diff --git a/source/blender/draw/intern/shaders/common_globals_lib.glsl b/source/blender/draw/intern/shaders/common_globals_lib.glsl index a479a87e14b..40a527a6ba4 100644 --- a/source/blender/draw/intern/shaders/common_globals_lib.glsl +++ b/source/blender/draw/intern/shaders/common_globals_lib.glsl @@ -123,6 +123,8 @@ layout(std140) uniform globalsBlock #define sizeViewportInv (sizeViewport.zw) +/* See: 'draw_cache_impl.h' for matching includes. */ + /* data[0] (1st byte flags) */ #define FACE_ACTIVE (1 << 0) #define FACE_SELECTED (1 << 1) @@ -135,9 +137,9 @@ layout(std140) uniform globalsBlock /* data[1] (2st byte flags) */ #define VERT_ACTIVE (1 << 0) #define VERT_SELECTED (1 << 1) -#define EDGE_ACTIVE (1 << 2) -#define EDGE_SELECTED (1 << 3) -#define EDGE_SEAM (1 << 4) -#define EDGE_SHARP (1 << 5) -#define EDGE_FREESTYLE (1 << 6) -#define HANDLE_SELECTED (1 << 7) +#define VERT_SELECTED_BEZT_HANDLE (1 << 2) +#define EDGE_ACTIVE (1 << 3) +#define EDGE_SELECTED (1 << 4) +#define EDGE_SEAM (1 << 5) +#define EDGE_SHARP (1 << 6) +#define EDGE_FREESTYLE (1 << 7) |