diff options
Diffstat (limited to 'source/blender/draw/intern/draw_manager.c')
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 287 |
1 files changed, 163 insertions, 124 deletions
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 3d8a7bb1e30..6387cecc01f 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -33,6 +33,7 @@ #include "BKE_anim.h" #include "BKE_colortools.h" +#include "BKE_context.h" #include "BKE_curve.h" #include "BKE_editmesh.h" #include "BKE_global.h" @@ -41,6 +42,7 @@ #include "BKE_main.h" #include "BKE_mball.h" #include "BKE_mesh.h" +#include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_paint.h" @@ -65,7 +67,6 @@ #include "GPU_uniformbuffer.h" #include "GPU_viewport.h" #include "GPU_matrix.h" -#include "GPU_select.h" #include "IMB_colormanagement.h" @@ -98,10 +99,6 @@ #include "DRW_select_buffer.h" -#ifdef USE_GPU_SELECT -# include "GPU_select.h" -#endif - /** Render State: No persistent data between draw calls. */ DRWManager DST = {NULL}; @@ -540,8 +537,11 @@ static void drw_viewport_cache_resize(void) GPU_texture_free(*tex); } - BLI_memblock_clear(DST.vmempool->calls, NULL); - BLI_memblock_clear(DST.vmempool->states, NULL); + BLI_memblock_clear(DST.vmempool->commands, NULL); + BLI_memblock_clear(DST.vmempool->commands_small, NULL); + BLI_memblock_clear(DST.vmempool->callbuffers, NULL); + BLI_memblock_clear(DST.vmempool->obmats, NULL); + BLI_memblock_clear(DST.vmempool->obinfos, NULL); BLI_memblock_clear(DST.vmempool->cullstates, NULL); BLI_memblock_clear(DST.vmempool->shgroups, NULL); BLI_memblock_clear(DST.vmempool->uniforms, NULL); @@ -589,28 +589,28 @@ static void drw_context_state_init(void) } } -static DRWCallState *draw_unit_state_create(void) +static void draw_unit_state_create(void) { - DRWCallState *state = BLI_memblock_alloc(DST.vmempool->states); - state->flag = 0; - state->matflag = 0; + DRWObjectInfos *infos = BLI_memblock_alloc(DST.vmempool->obinfos); + DRWObjectMatrix *mats = BLI_memblock_alloc(DST.vmempool->obmats); + DRWCullingState *culling = BLI_memblock_alloc(DST.vmempool->cullstates); - unit_m4(state->model); - unit_m4(state->modelinverse); + unit_m4(mats->model); + unit_m4(mats->modelinverse); - copy_v3_fl(state->orcotexfac[0], 0.0f); - copy_v3_fl(state->orcotexfac[1], 1.0f); + copy_v3_fl(infos->orcotexfac[0], 0.0f); + copy_v3_fl(infos->orcotexfac[1], 1.0f); - state->ob_index = 0; - state->ob_random = 0.0f; - copy_v3_fl(state->ob_color, 1.0f); + infos->ob_index = 0; + infos->ob_random = 0.0f; + infos->ob_neg_scale = 1.0f; + copy_v3_fl(infos->ob_color, 1.0f); /* TODO(fclem) get rid of this. */ - state->culling = BLI_memblock_alloc(DST.vmempool->cullstates); - state->culling->bsphere.radius = -1.0f; - state->culling->user_data = NULL; + culling->bsphere.radius = -1.0f; + culling->user_data = NULL; - return state; + DRW_handle_increment(&DST.resource_handle); } /* It also stores viewport variable to an immutable place: DST @@ -635,33 +635,48 @@ static void drw_viewport_var_init(void) DST.vmempool = GPU_viewport_mempool_get(DST.viewport); - if (DST.vmempool->calls == NULL) { - DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall)); + if (DST.vmempool->commands == NULL) { + DST.vmempool->commands = BLI_memblock_create(sizeof(DRWCommandChunk)); + } + if (DST.vmempool->commands_small == NULL) { + DST.vmempool->commands_small = BLI_memblock_create(sizeof(DRWCommandSmallChunk)); + } + if (DST.vmempool->callbuffers == NULL) { + DST.vmempool->callbuffers = BLI_memblock_create(sizeof(DRWCallBuffer)); + } + if (DST.vmempool->obmats == NULL) { + uint chunk_len = sizeof(DRWObjectMatrix) * DRW_RESOURCE_CHUNK_LEN; + DST.vmempool->obmats = BLI_memblock_create_ex(sizeof(DRWObjectMatrix), chunk_len); } - if (DST.vmempool->states == NULL) { - DST.vmempool->states = BLI_memblock_create(sizeof(DRWCallState)); + if (DST.vmempool->obinfos == NULL) { + uint chunk_len = sizeof(DRWObjectInfos) * DRW_RESOURCE_CHUNK_LEN; + DST.vmempool->obinfos = BLI_memblock_create_ex(sizeof(DRWObjectInfos), chunk_len); } if (DST.vmempool->cullstates == NULL) { - DST.vmempool->cullstates = BLI_memblock_create(sizeof(DRWCullingState)); + uint chunk_len = sizeof(DRWCullingState) * DRW_RESOURCE_CHUNK_LEN; + DST.vmempool->cullstates = BLI_memblock_create_ex(sizeof(DRWCullingState), chunk_len); } if (DST.vmempool->shgroups == NULL) { DST.vmempool->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup)); } if (DST.vmempool->uniforms == NULL) { - DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniform)); + DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniformChunk)); } if (DST.vmempool->views == NULL) { DST.vmempool->views = BLI_memblock_create(sizeof(DRWView)); } if (DST.vmempool->passes == NULL) { - DST.vmempool->passes = BLI_memblock_create(sizeof(DRWPass)); + uint chunk_len = sizeof(DRWPass) * DRW_RESOURCE_CHUNK_LEN; + DST.vmempool->passes = BLI_memblock_create_ex(sizeof(DRWPass), chunk_len); } if (DST.vmempool->images == NULL) { DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *)); } - /* Alloc default unit state */ - DST.unit_state = draw_unit_state_create(); + DST.resource_handle = 0; + DST.pass_handle = 0; + + draw_unit_state_create(); DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport); DRW_instance_data_list_reset(DST.idatalist); @@ -675,8 +690,6 @@ static void drw_viewport_var_init(void) DST.default_framebuffer = NULL; DST.vmempool = NULL; - - DST.unit_state = NULL; } DST.primary_view_ct = 0; @@ -719,6 +732,10 @@ static void drw_viewport_var_init(void) G_draw.view_ubo = DRW_uniformbuffer_create(sizeof(DRWViewUboStorage), NULL); } + if (DST.draw_list == NULL) { + DST.draw_list = GPU_draw_list_create(DRW_DRAWLIST_LEN); + } + memset(DST.object_instance_data, 0x0, sizeof(DST.object_instance_data)); } @@ -1023,7 +1040,7 @@ void DRW_cache_free_old_batches(Main *bmain) for (scene = bmain->scenes.first; scene; scene = scene->id.next) { for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { - Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false); + Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, false); if (depsgraph == NULL) { continue; } @@ -1102,7 +1119,7 @@ static void drw_engines_world_update(Scene *scene) static void drw_engines_cache_populate(Object *ob) { - DST.ob_state = NULL; + DST.ob_handle = 0; /* HACK: DrawData is copied by COW from the duplicated object. * This is valid for IDs that cannot be instantiated but this @@ -1548,6 +1565,20 @@ void DRW_draw_view(const bContext *C) DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, C); } +static bool is_object_visible_in_viewport(View3D *v3d, Object *ob) +{ + if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) { + return false; + } + + if ((v3d->flag & V3D_LOCAL_COLLECTIONS) && + ((v3d->local_collections_uuid & ob->runtime.local_collections_bits) == 0)) { + return false; + } + + return true; +} + /** * Used for both regular and off-screen drawing. * Need to reset DST before calling this function @@ -1623,7 +1654,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, if ((object_type_exclude_viewport & (1 << ob->type)) != 0) { continue; } - if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) { + if (!is_object_visible_in_viewport(v3d, ob)) { continue; } DST.dupli_parent = data_.dupli_parent; @@ -1766,7 +1797,9 @@ void DRW_draw_render_loop(struct Depsgraph *depsgraph, DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, NULL); } -/* @viewport CAN be NULL, in this case we create one. */ +/** + * \param viewport: can be NULL, in this case we create one. + */ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph, RenderEngineType *engine_type, ARegion *ar, @@ -1904,6 +1937,8 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph RenderResult *render_result = RE_engine_get_result(engine); RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name); + DST.buffer_finish_called = false; + DRW_render_gpencil_to_image(engine, render_layer, &render_rect); /* Force cache to reset. */ @@ -2014,13 +2049,15 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) RE_SetActiveRenderView(render, render_view->name); drw_view_reset(); engine_type->draw_engine->render_to_image(data, engine, render_layer, &render_rect); + DST.buffer_finish_called = false; + /* grease pencil: render result is merged in the previous render result. */ if (DRW_render_check_grease_pencil(depsgraph)) { DRW_state_reset(); drw_view_reset(); DRW_render_gpencil_to_image(engine, render_layer, &render_rect); + DST.buffer_finish_called = false; } - DST.buffer_finish_called = false; } RE_engine_end_result(engine, render_result, false, false, false); @@ -2066,7 +2103,7 @@ void DRW_render_object_iter( if ((object_type_exclude_viewport & (1 << ob->type)) == 0) { DST.dupli_parent = data_.dupli_parent; DST.dupli_source = data_.dupli_object_current; - DST.ob_state = NULL; + DST.ob_handle = 0; drw_duplidata_load(DST.dupli_source); if (!DST.dupli_source) { @@ -2173,6 +2210,7 @@ void DRW_render_instance_buffer_finish(void) BLI_assert(!DST.buffer_finish_called && "DRW_render_instance_buffer_finish called twice!"); DST.buffer_finish_called = true; DRW_instance_buffer_finish(DST.idatalist); + drw_resource_buffer_finish(DST.vmempool); } /** @@ -2196,7 +2234,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, Object *obact = OBACT(view_layer); Object *obedit = OBEDIT_FROM_OBACT(obact); #ifndef USE_GPU_SELECT - UNUSED_VARS(vc, scene, view_layer, v3d, ar, rect); + UNUSED_VARS(scene, view_layer, v3d, ar, rect); #else RegionView3D *rv3d = ar->regiondata; @@ -2204,24 +2242,43 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, drw_state_prepare_clean_for_draw(&DST); bool use_obedit = false; - int obedit_mode = 0; + /* obedit_ctx_mode is used for selecting the right draw engines */ + eContextObjectMode obedit_ctx_mode; + /* object_mode is used for filtering objects in the depsgraph */ + eObjectMode object_mode; + int object_type = 0; if (obedit != NULL) { + object_type = obedit->type; + object_mode = obedit->mode; if (obedit->type == OB_MBALL) { use_obedit = true; - obedit_mode = CTX_MODE_EDIT_METABALL; + obedit_ctx_mode = CTX_MODE_EDIT_METABALL; } else if (obedit->type == OB_ARMATURE) { use_obedit = true; - obedit_mode = CTX_MODE_EDIT_ARMATURE; + obedit_ctx_mode = CTX_MODE_EDIT_ARMATURE; } } if (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT) { if (!(v3d->flag2 & V3D_HIDE_OVERLAYS)) { /* Note: don't use "BKE_object_pose_armature_get" here, it breaks selection. */ Object *obpose = OBPOSE_FROM_OBACT(obact); + if (obpose == NULL) { + Object *obweight = OBWEIGHTPAINT_FROM_OBACT(obact); + if (obweight) { + /* Only use Armature pose selection, when connected armature is in pose mode. */ + Object *ob_armature = modifiers_isDeformedByArmature(obweight); + if (ob_armature && ob_armature->mode == OB_MODE_POSE) { + obpose = ob_armature; + } + } + } + if (obpose) { use_obedit = true; - obedit_mode = CTX_MODE_POSE; + object_type = obpose->type; + object_mode = obpose->mode; + obedit_ctx_mode = CTX_MODE_POSE; } } } @@ -2235,8 +2292,8 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, /* Get list of enabled engines */ if (use_obedit) { - drw_engines_enable_from_paint_mode(obedit_mode); - drw_engines_enable_from_mode(obedit_mode); + drw_engines_enable_from_paint_mode(obedit_ctx_mode); + drw_engines_enable_from_mode(obedit_ctx_mode); } else if (!draw_surface) { /* grease pencil selection */ @@ -2283,7 +2340,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, drw_engines_world_update(scene); if (use_obedit) { - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) { + FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, object_type, object_mode, ob_iter) { drw_engines_cache_populate(ob_iter); } FOREACH_OBJECT_IN_MODE_END; @@ -2293,10 +2350,9 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, v3d->object_type_exclude_select); bool filter_exclude = false; DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) { - if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) { + if (!is_object_visible_in_viewport(v3d, ob)) { continue; } - if ((ob->base_flag & BASE_SELECTABLE) && (object_type_exclude_select & (1 << ob->type)) == 0) { if (object_filter_fn != NULL) { @@ -2386,8 +2442,38 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, /** * object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing). */ -static void drw_draw_depth_loop_imp(void) +static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph, + ARegion *ar, + View3D *v3d, + GPUViewport *viewport, + const bool use_opengl_context) { + Scene *scene = DEG_get_evaluated_scene(depsgraph); + RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + RegionView3D *rv3d = ar->regiondata; + + if (use_opengl_context) { + DRW_opengl_context_enable(); + } + + DST.viewport = viewport; + DST.options.is_depth = true; + + /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */ + DST.draw_ctx = (DRWContextState){ + .ar = ar, + .rv3d = rv3d, + .v3d = v3d, + .scene = scene, + .view_layer = view_layer, + .obact = OBACT(view_layer), + .engine_type = engine_type, + .depsgraph = depsgraph, + }; + + drw_engines_data_validate(); + /* Setup framebuffer */ DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get( DST.viewport); @@ -2409,17 +2495,14 @@ static void drw_draw_depth_loop_imp(void) drw_engines_cache_init(); drw_engines_world_update(DST.draw_ctx.scene); - View3D *v3d = DST.draw_ctx.v3d; const int object_type_exclude_viewport = v3d->object_type_exclude_viewport; DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (DST.draw_ctx.depsgraph, ob) { if ((object_type_exclude_viewport & (1 << ob->type)) != 0) { continue; } - - if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) { + if (!is_object_visible_in_viewport(v3d, ob)) { continue; } - DST.dupli_parent = data_.dupli_parent; DST.dupli_source = data_.dupli_object_current; drw_duplidata_load(DST.dupli_source); @@ -2447,6 +2530,20 @@ static void drw_draw_depth_loop_imp(void) /* TODO: Reading depth for operators should be done here. */ GPU_framebuffer_restore(); + + drw_engines_disable(); + + drw_viewport_cache_resize(); + +#ifdef DEBUG + /* Avoid accidental reuse. */ + drw_state_ensure_not_reused(&DST); +#endif + + /* Changin context */ + if (use_opengl_context) { + DRW_opengl_context_disable(); + } } /** @@ -2458,55 +2555,18 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph, GPUViewport *viewport, bool use_opengl_context) { - Scene *scene = DEG_get_evaluated_scene(depsgraph); - RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); - ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); - RegionView3D *rv3d = ar->regiondata; - - if (use_opengl_context) { - DRW_opengl_context_enable(); - } - /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); - DST.viewport = viewport; - DST.options.is_depth = true; - - /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */ - DST.draw_ctx = (DRWContextState){ - .ar = ar, - .rv3d = rv3d, - .v3d = v3d, - .scene = scene, - .view_layer = view_layer, - .obact = OBACT(view_layer), - .engine_type = engine_type, - .depsgraph = depsgraph, - }; - /* Get list of enabled engines */ { drw_engines_enable_basic(); if (DRW_state_draw_support()) { drw_engines_enable_from_object_mode(); } - drw_engines_data_validate(); } - drw_draw_depth_loop_imp(); - - drw_engines_disable(); - -#ifdef DEBUG - /* Avoid accidental reuse. */ - drw_state_ensure_not_reused(&DST); -#endif - - /* Changin context */ - if (use_opengl_context) { - DRW_opengl_context_disable(); - } + drw_draw_depth_loop_imp(depsgraph, ar, v3d, viewport, use_opengl_context); } /** @@ -2517,43 +2577,12 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, View3D *v3d, GPUViewport *viewport) { - Scene *scene = DEG_get_evaluated_scene(depsgraph); - ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); - RegionView3D *rv3d = ar->regiondata; - - DRW_opengl_context_enable(); - /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); - DST.viewport = viewport; - DST.options.is_depth = true; - - /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */ - DST.draw_ctx = (DRWContextState){ - .ar = ar, - .rv3d = rv3d, - .v3d = v3d, - .scene = scene, - .view_layer = view_layer, - .obact = OBACT(view_layer), - .depsgraph = depsgraph, - }; - use_drw_engine(&draw_engine_gpencil_type); - drw_engines_data_validate(); - - drw_draw_depth_loop_imp(); - - drw_engines_disable(); - -#ifdef DEBUG - /* Avoid accidental reuse. */ - drw_state_ensure_not_reused(&DST); -#endif - /* Changin context */ - DRW_opengl_context_disable(); + drw_draw_depth_loop_imp(depsgraph, ar, v3d, viewport, true); } void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, const rcti *rect) @@ -2601,7 +2630,13 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, const rc drw_engines_cache_finish(); +#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 + DST.buffer_finish_called = true; + // DRW_instance_buffer_finish(DST.idatalist); + drw_resource_buffer_finish(DST.vmempool); +#endif } /* Start Drawing */ @@ -2905,6 +2940,10 @@ void DRW_engines_free(void) MEM_SAFE_FREE(DST.uniform_names.buffer); + if (DST.draw_list) { + GPU_draw_list_discard(DST.draw_list); + } + DRW_opengl_context_disable(); } |