diff --git a/.clang-format b/.clang-format index bf20a4e4c4a..91df22f4d5b 100644 --- a/.clang-format +++ b/.clang-format @@ -180,6 +180,7 @@ ForEachMacros: - CTX_DATA_BEGIN_WITH_ID - DEG_OBJECT_ITER_BEGIN - DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN + - DRW_ENABLED_ENGINE_ITER - DRIVER_TARGETS_LOOPER_BEGIN - DRIVER_TARGETS_USED_LOOPER_BEGIN - FOREACH_BASE_IN_EDIT_MODE_BEGIN diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 71115c5ceb9..dd4aa1747e5 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -94,6 +94,7 @@ set(SRC intern/draw_color_management.cc intern/draw_common.c intern/draw_debug.c + intern/draw_view_data.cc intern/draw_fluid.c intern/draw_hair.c intern/draw_instance_data.c @@ -105,6 +106,7 @@ set(SRC intern/draw_manager_text.c intern/draw_manager_texture.c intern/draw_select_buffer.c + intern/draw_texture_pool.cc intern/draw_shader.c intern/draw_view.c engines/basic/basic_engine.c @@ -188,7 +190,6 @@ set(SRC engines/overlay/overlay_wireframe.c DRW_engine.h - DRW_engine_types.h DRW_select_buffer.h intern/DRW_render.h intern/draw_cache.h @@ -198,12 +199,14 @@ set(SRC intern/draw_color_management.h intern/draw_common.h intern/draw_debug.h + intern/draw_view_data.h intern/draw_hair_private.h intern/draw_instance_data.h intern/draw_manager.h intern/draw_manager_profiling.h intern/draw_manager_testing.h intern/draw_manager_text.h + intern/draw_texture_pool.h intern/draw_shader.h intern/draw_view.h intern/mesh_extractors/extract_mesh.h diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 5e7b812c37b..927a29ed6b6 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -26,13 +26,12 @@ #include "DNA_object_enums.h" -#include "DRW_engine_types.h" - #ifdef __cplusplus extern "C" { #endif struct ARegion; +struct DRWData; struct DRWInstanceDataList; struct Depsgraph; struct DrawEngineType; @@ -57,8 +56,6 @@ void DRW_engines_free(void); bool DRW_engine_render_support(struct DrawEngineType *draw_engine_type); void DRW_engine_register(struct DrawEngineType *draw_engine_type); -void DRW_engine_viewport_data_size_get( - const void *engine_type, int *r_fbl_len, int *r_txl_len, int *r_psl_len, int *r_stl_len); typedef struct DRWUpdateContext { struct Main *bmain; @@ -176,6 +173,9 @@ void DRW_deferred_shader_remove(struct GPUMaterial *mat); struct DrawDataList *DRW_drawdatalist_from_id(struct ID *id); void DRW_drawdata_free(struct ID *id); +struct DRWData *DRW_viewport_data_create(void); +void DRW_viewport_data_free(struct DRWData *drw_data); + bool DRW_opengl_context_release(void); void DRW_opengl_context_activate(bool drw_state); diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index fb8b8536897..c1cab931f6a 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -24,8 +24,6 @@ #pragma once -#include "DRW_engine_types.h" - #include "BLI_listbase.h" #include "BLI_math_matrix.h" #include "BLI_math_vector.h" @@ -56,6 +54,7 @@ #include "draw_debug.h" #include "draw_manager_profiling.h" +#include "draw_view_data.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c index e055192eb21..29112ee4788 100644 --- a/source/blender/draw/intern/draw_instance_data.c +++ b/source/blender/draw/intern/draw_instance_data.c @@ -364,6 +364,8 @@ void DRW_instance_data_list_free(DRWInstanceDataList *idatalist) BLI_memblock_destroy(idatalist->pool_batching, (MemblockValFreeFP)temp_batch_free); BLI_remlink(&g_idatalists, idatalist); + + MEM_freeN(idatalist); } void DRW_instance_data_list_reset(DRWInstanceDataList *idatalist) diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index e65fdce5f2e..7a41142b177 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -84,10 +84,12 @@ #include "wm_window.h" #include "draw_color_management.h" +#include "draw_manager.h" #include "draw_manager_profiling.h" #include "draw_manager_testing.h" #include "draw_manager_text.h" #include "draw_shader.h" +#include "draw_texture_pool.h" /* only for callbacks */ #include "draw_cache_impl.h" @@ -111,7 +113,10 @@ /** Render State: No persistent data between draw calls. */ DRWManager DST = {NULL}; -static ListBase DRW_engines = {NULL, NULL}; +static struct { + ListBase /*DRWRegisteredDrawEngine*/ engines; + int len; +} g_registered_engines = {{NULL}}; static void drw_state_prepare_clean_for_draw(DRWManager *dst) { @@ -315,35 +320,6 @@ struct DupliObject *DRW_object_get_dupli(const Object *UNUSED(ob)) /** \name Viewport (DRW_viewport) * \{ */ -void *drw_viewport_engine_data_ensure(void *engine_type) -{ - void *data = GPU_viewport_engine_data_get(DST.viewport, engine_type); - - if (data == NULL) { - data = GPU_viewport_engine_data_create(DST.viewport, engine_type); - } - return data; -} - -void DRW_engine_viewport_data_size_get( - const void *engine_type_v, int *r_fbl_len, int *r_txl_len, int *r_psl_len, int *r_stl_len) -{ - const DrawEngineType *engine_type = engine_type_v; - - if (r_fbl_len) { - *r_fbl_len = engine_type->vedata_size->fbl_len; - } - if (r_txl_len) { - *r_txl_len = engine_type->vedata_size->txl_len; - } - if (r_psl_len) { - *r_psl_len = engine_type->vedata_size->psl_len; - } - if (r_stl_len) { - *r_stl_len = engine_type->vedata_size->stl_len; - } -} - /* WARNING: only use for custom pipeline. 99% of the time, you don't want to use this. */ void DRW_render_viewport_size_set(const int size[2]) { @@ -373,39 +349,6 @@ const float *DRW_viewport_pixelsize_get(void) return &DST.pixsize; } -static void drw_viewport_cache_resize(void) -{ - /* Release the memiter before clearing the mempools that references them */ - GPU_viewport_cache_release(DST.viewport); - - if (DST.vmempool != NULL) { - /* Release Image textures. */ - BLI_memblock_iter iter; - GPUTexture **tex; - BLI_memblock_iternew(DST.vmempool->images, &iter); - while ((tex = BLI_memblock_iterstep(&iter))) { - GPU_texture_free(*tex); - } - - 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); - BLI_memblock_clear(DST.vmempool->passes, NULL); - BLI_memblock_clear(DST.vmempool->views, NULL); - BLI_memblock_clear(DST.vmempool->images, NULL); - - DRW_uniform_attrs_pool_clear_all(DST.vmempool->obattrs_ubo_pool); - } - - DRW_instance_data_list_free_unused(DST.idatalist); - DRW_instance_data_list_resize(DST.idatalist); -} - /* Not a viewport variable, we could split this out. */ static void drw_context_state_init(void) { @@ -465,107 +408,207 @@ static void draw_unit_state_create(void) DRW_handle_increment(&DST.resource_handle); } -/* It also stores viewport variable to an immutable place: DST - * This is because a cache uniform only store reference - * to its value. And we don't want to invalidate the cache - * if this value change per viewport */ -static void drw_viewport_var_init(void) +DRWData *DRW_viewport_data_create(void) { - RegionView3D *rv3d = DST.draw_ctx.rv3d; - ARegion *region = DST.draw_ctx.region; + DRWData *drw_data = MEM_callocN(sizeof(DRWData), "DRWData"); - /* Refresh DST.size */ - if (DST.viewport) { - int size[2]; - GPU_viewport_size_get(DST.viewport, size); - DST.size[0] = size[0]; - DST.size[1] = size[1]; - DST.inv_size[0] = 1.0f / size[0]; - DST.inv_size[1] = 1.0f / size[1]; + drw_data->texture_pool = DRW_texture_pool_create(); - DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get( - DST.viewport); - DST.default_framebuffer = fbl->default_fb; + drw_data->idatalist = DRW_instance_data_list_create(); - DST.vmempool = GPU_viewport_mempool_get(DST.viewport); + drw_data->commands = BLI_memblock_create(sizeof(DRWCommandChunk)); + drw_data->commands_small = BLI_memblock_create(sizeof(DRWCommandSmallChunk)); + drw_data->callbuffers = BLI_memblock_create(sizeof(DRWCallBuffer)); + drw_data->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup)); + drw_data->uniforms = BLI_memblock_create(sizeof(DRWUniformChunk)); + drw_data->views = BLI_memblock_create(sizeof(DRWView)); + drw_data->images = BLI_memblock_create(sizeof(GPUTexture *)); + drw_data->obattrs_ubo_pool = DRW_uniform_attrs_pool_new(); + { + uint chunk_len = sizeof(DRWObjectMatrix) * DRW_RESOURCE_CHUNK_LEN; + drw_data->obmats = BLI_memblock_create_ex(sizeof(DRWObjectMatrix), chunk_len); + } + { + uint chunk_len = sizeof(DRWObjectInfos) * DRW_RESOURCE_CHUNK_LEN; + drw_data->obinfos = BLI_memblock_create_ex(sizeof(DRWObjectInfos), chunk_len); + } + { + uint chunk_len = sizeof(DRWCullingState) * DRW_RESOURCE_CHUNK_LEN; + drw_data->cullstates = BLI_memblock_create_ex(sizeof(DRWCullingState), chunk_len); + } + { + uint chunk_len = sizeof(DRWPass) * DRW_RESOURCE_CHUNK_LEN; + drw_data->passes = BLI_memblock_create_ex(sizeof(DRWPass), chunk_len); + } - 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->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) { - 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(DRWUniformChunk)); - } - if (DST.vmempool->views == NULL) { - DST.vmempool->views = BLI_memblock_create(sizeof(DRWView)); - } - if (DST.vmempool->passes == NULL) { - 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 *)); - } - if (DST.vmempool->obattrs_ubo_pool == NULL) { - DST.vmempool->obattrs_ubo_pool = DRW_uniform_attrs_pool_new(); - } + for (int i = 0; i < 2; i++) { + drw_data->view_data[i] = DRW_view_data_create(&g_registered_engines.engines); + } + return drw_data; +} - DST.resource_handle = 0; - DST.pass_handle = 0; +/* Reduce ref count of the textures used by a viewport. */ +static void draw_texture_release(DRWData *drw_data) +{ + /* Release Image textures. */ + BLI_memblock_iter iter; + GPUTexture **tex; + BLI_memblock_iternew(drw_data->images, &iter); + while ((tex = BLI_memblock_iterstep(&iter))) { + GPU_texture_free(*tex); + } +} - draw_unit_state_create(); +static void drw_viewport_data_reset(DRWData *drw_data) +{ + draw_texture_release(drw_data); - DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport); - DRW_instance_data_list_reset(DST.idatalist); + BLI_memblock_clear(drw_data->commands, NULL); + BLI_memblock_clear(drw_data->commands_small, NULL); + BLI_memblock_clear(drw_data->callbuffers, NULL); + BLI_memblock_clear(drw_data->obmats, NULL); + BLI_memblock_clear(drw_data->obinfos, NULL); + BLI_memblock_clear(drw_data->cullstates, NULL); + BLI_memblock_clear(drw_data->shgroups, NULL); + BLI_memblock_clear(drw_data->uniforms, NULL); + BLI_memblock_clear(drw_data->passes, NULL); + BLI_memblock_clear(drw_data->views, NULL); + BLI_memblock_clear(drw_data->images, NULL); + DRW_uniform_attrs_pool_clear_all(drw_data->obattrs_ubo_pool); + DRW_instance_data_list_free_unused(drw_data->idatalist); + DRW_instance_data_list_resize(drw_data->idatalist); + DRW_instance_data_list_reset(drw_data->idatalist); + DRW_texture_pool_reset(drw_data->texture_pool); +} + +void DRW_viewport_data_free(DRWData *drw_data) +{ + draw_texture_release(drw_data); + + BLI_memblock_destroy(drw_data->commands, NULL); + BLI_memblock_destroy(drw_data->commands_small, NULL); + BLI_memblock_destroy(drw_data->callbuffers, NULL); + BLI_memblock_destroy(drw_data->obmats, NULL); + BLI_memblock_destroy(drw_data->obinfos, NULL); + BLI_memblock_destroy(drw_data->cullstates, NULL); + BLI_memblock_destroy(drw_data->shgroups, NULL); + BLI_memblock_destroy(drw_data->uniforms, NULL); + BLI_memblock_destroy(drw_data->views, NULL); + BLI_memblock_destroy(drw_data->passes, NULL); + BLI_memblock_destroy(drw_data->images, NULL); + DRW_uniform_attrs_pool_free(drw_data->obattrs_ubo_pool); + DRW_instance_data_list_free(drw_data->idatalist); + DRW_texture_pool_free(drw_data->texture_pool); + for (int i = 0; i < 2; i++) { + DRW_view_data_free(drw_data->view_data[i]); + } + if (drw_data->matrices_ubo != NULL) { + for (int i = 0; i < drw_data->ubo_len; i++) { + GPU_uniformbuf_free(drw_data->matrices_ubo[i]); + GPU_uniformbuf_free(drw_data->obinfos_ubo[i]); + } + MEM_freeN(drw_data->matrices_ubo); + MEM_freeN(drw_data->obinfos_ubo); + } + MEM_freeN(drw_data); +} + +static DRWData *drw_viewport_data_ensure(GPUViewport *viewport) +{ + DRWData **vmempool_p = GPU_viewport_data_get(viewport); + DRWData *vmempool = *vmempool_p; + + if (vmempool == NULL) { + *vmempool_p = vmempool = DRW_viewport_data_create(); + } + return vmempool; +} + +/** + * Sets DST.viewport, DST.size and a lot of other important variables. + * Needs to be called before enabling any draw engine. + * - viewport can be NULL. In this case the data will not be stored and will be free at + * drw_manager_exit(). + * - size can be NULL to get it from viewport. + * - if viewport and size are NULL, size is set to (1, 1). + * + * Important: drw_manager_init can be called multiple times before drw_manager_exit. + */ +static void drw_manager_init(DRWManager *dst, GPUViewport *viewport, const int size[2]) +{ + RegionView3D *rv3d = dst->draw_ctx.rv3d; + ARegion *region = dst->draw_ctx.region; + + int view = (viewport) ? GPU_viewport_active_view_get(viewport) : 0; + + if (!dst->viewport && dst->vmempool) { + /* Manager was init first without a viewport, created DRWData, but is being re-init. + * In this case, keep the old data. */ + /* If it is being re-init with a valid viewport, it means there is something wrong. */ + BLI_assert(viewport == NULL); + } + else if (viewport) { + /* Use viewport's persistent DRWData. */ + dst->vmempool = drw_viewport_data_ensure(viewport); } else { - DST.size[0] = 0; - DST.size[1] = 0; - - DST.inv_size[0] = 0; - DST.inv_size[1] = 0; - - DST.default_framebuffer = NULL; - DST.vmempool = NULL; + /* Create temporary DRWData. Freed in drw_manager_exit(). */ + dst->vmempool = DRW_viewport_data_create(); } - DST.primary_view_ct = 0; + dst->viewport = viewport; + dst->view_data_active = dst->vmempool->view_data[view]; + dst->resource_handle = 0; + dst->pass_handle = 0; + dst->primary_view_ct = 0; + + drw_viewport_data_reset(dst->vmempool); + + if (size == NULL && viewport == NULL) { + /* Avoid division by 0. Engines will either overide this or not use it. */ + dst->size[0] = 1.0f; + dst->size[1] = 1.0f; + } + else if (size == NULL) { + BLI_assert(viewport); + GPUTexture *tex = GPU_viewport_color_texture(viewport, 0); + dst->size[0] = GPU_texture_width(tex); + dst->size[1] = GPU_texture_height(tex); + } + else { + BLI_assert(size); + dst->size[0] = size[0]; + dst->size[1] = size[1]; + } + dst->inv_size[0] = 1.0f / dst->size[0]; + dst->inv_size[1] = 1.0f / dst->size[1]; + + DRW_view_data_texture_list_size_validate(dst->view_data_active, (int[2]){UNPACK2(dst->size)}); + + if (viewport) { + DRW_view_data_default_lists_from_viewport(dst->view_data_active, viewport); + } + + DefaultFramebufferList *dfbl = DRW_view_data_default_framebuffer_list_get(dst->view_data_active); + dst->default_framebuffer = dfbl->default_fb; + + draw_unit_state_create(); if (rv3d != NULL) { - normalize_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]); - normalize_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]); + normalize_v3_v3(dst->screenvecs[0], rv3d->viewinv[0]); + normalize_v3_v3(dst->screenvecs[1], rv3d->viewinv[1]); - DST.pixsize = rv3d->pixsize; - DST.view_default = DRW_view_create(rv3d->viewmat, rv3d->winmat, NULL, NULL, NULL); - DRW_view_camtexco_set(DST.view_default, rv3d->viewcamtexcofac); + dst->pixsize = rv3d->pixsize; + dst->view_default = DRW_view_create(rv3d->viewmat, rv3d->winmat, NULL, NULL, NULL); + DRW_view_camtexco_set(dst->view_default, rv3d->viewcamtexcofac); - if (DST.draw_ctx.sh_cfg == GPU_SHADER_CFG_CLIPPED) { + if (dst->draw_ctx.sh_cfg == GPU_SHADER_CFG_CLIPPED) { int plane_len = (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXCLIP) ? 4 : 6; - DRW_view_clip_planes_set(DST.view_default, rv3d->clip, plane_len); + DRW_view_clip_planes_set(dst->view_default, rv3d->clip, plane_len); } - DST.view_active = DST.view_default; - DST.view_previous = NULL; + dst->view_active = dst->view_default; + dst->view_previous = NULL; } else if (region) { View2D *v2d = ®ion->v2d; @@ -581,49 +624,64 @@ static void drw_viewport_var_init(void) winmat[3][0] = -1.0f; winmat[3][1] = -1.0f; - DST.view_default = DRW_view_create(viewmat, winmat, NULL, NULL, NULL); - DST.view_active = DST.view_default; - DST.view_previous = NULL; + dst->view_default = DRW_view_create(viewmat, winmat, NULL, NULL, NULL); + dst->view_active = dst->view_default; + dst->view_previous = NULL; } else { - zero_v3(DST.screenvecs[0]); - zero_v3(DST.screenvecs[1]); + zero_v3(dst->screenvecs[0]); + zero_v3(dst->screenvecs[1]); - DST.pixsize = 1.0f; - DST.view_default = NULL; - DST.view_active = NULL; - DST.view_previous = NULL; + dst->pixsize = 1.0f; + dst->view_default = NULL; + dst->view_active = NULL; + dst->view_previous = NULL; } /* fclem: Is this still needed ? */ - if (DST.draw_ctx.object_edit && rv3d) { - ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d); + if (dst->draw_ctx.object_edit && rv3d) { + ED_view3d_init_mats_rv3d(dst->draw_ctx.object_edit, rv3d); } if (G_draw.view_ubo == NULL) { G_draw.view_ubo = GPU_uniformbuf_create_ex(sizeof(DRWViewUboStorage), NULL, "G_draw.view_ubo"); } - if (DST.draw_list == NULL) { - DST.draw_list = GPU_draw_list_create(DRW_DRAWLIST_LEN); + 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)); + memset(dst->object_instance_data, 0x0, sizeof(dst->object_instance_data)); +} + +static void drw_manager_exit(DRWManager *dst) +{ + if (dst->vmempool != NULL && dst->viewport == NULL) { + DRW_viewport_data_free(dst->vmempool); + } + dst->vmempool = NULL; + dst->viewport = NULL; +#ifdef DEBUG + /* Avoid accidental reuse. */ + drw_state_ensure_not_reused(dst); +#endif } DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void) { - return GPU_viewport_framebuffer_list_get(DST.viewport); + return DRW_view_data_default_framebuffer_list_get(DST.view_data_active); } DefaultTextureList *DRW_viewport_texture_list_get(void) { - return GPU_viewport_texture_list_get(DST.viewport); + return DRW_view_data_default_texture_list_get(DST.view_data_active); } void DRW_viewport_request_redraw(void) { - GPU_viewport_tag_update(DST.viewport); + if (DST.viewport) { + GPU_viewport_tag_update(DST.viewport); + } } /** \} */ @@ -671,7 +729,7 @@ static void drw_duplidata_load(Object *ob) void **value; if (!BLI_ghash_ensure_p(DST.dupli_ghash, key, &value)) { - *value = MEM_callocN(sizeof(void *) * DST.enabled_engine_count, __func__); + *value = MEM_callocN(sizeof(void *) * g_registered_engines.len, __func__); /* TODO: Meh a bit out of place but this is nice as it is * only done once per instance type. */ @@ -686,7 +744,7 @@ static void drw_duplidata_load(Object *ob) static void duplidata_value_free(void *val) { void **dupli_datas = val; - for (int i = 0; i < DST.enabled_engine_count; i++) { + for (int i = 0; i < g_registered_engines.len; i++) { MEM_SAFE_FREE(dupli_datas[i]); } MEM_freeN(val); @@ -720,13 +778,9 @@ void **DRW_duplidata_get(void *vedata) if (DST.dupli_source == NULL) { return NULL; } - /* XXX Search engine index by using vedata array */ - for (int i = 0; i < DST.enabled_engine_count; i++) { - if (DST.vedata_array[i] == vedata) { - return &DST.dupli_datas[i]; - } - } - return NULL; + ViewportEngineData *ved = (ViewportEngineData *)vedata; + DRWRegisteredDrawEngine *engine_type = (DRWRegisteredDrawEngine *)ved->engine_type; + return &DST.dupli_datas[engine_type->index]; } /** \} */ @@ -873,7 +927,7 @@ DrawData *DRW_drawdata_ensure(ID *id, size_t fsize = size / sizeof(float); BLI_assert(fsize < MAX_INSTANCE_DATA_SIZE); if (DST.object_instance_data[fsize] == NULL) { - DST.object_instance_data[fsize] = DRW_instance_data_request(DST.idatalist, fsize); + DST.object_instance_data[fsize] = DRW_instance_data_request(DST.vmempool->idatalist, fsize); } dd = (DrawData *)DRW_instance_data_next(DST.object_instance_data[fsize]); memset(dd, 0, size); @@ -967,11 +1021,12 @@ void DRW_cache_free_old_batches(Main *bmain) static void drw_engines_init(void) { - LISTBASE_FOREACH (LinkData *, link, &DST.enabled_engines) { - DrawEngineType *engine = link->data; - ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) { PROFILE_START(stime); + const DrawEngineDataSize *data_size = engine->vedata_size; + memset(data->psl->passes, 0, sizeof(*data->psl->passes) * data_size->psl_len); + if (engine->engine_init) { engine->engine_init(data); } @@ -982,15 +1037,7 @@ static void drw_engines_init(void) static void drw_engines_cache_init(void) { - DST.enabled_engine_count = BLI_listbase_count(&DST.enabled_engines); - DST.vedata_array = MEM_mallocN(sizeof(void *) * DST.enabled_engine_count, __func__); - - int i = 0; - for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) { - DrawEngineType *engine = link->data; - ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); - DST.vedata_array[i] = data; - + DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) { if (data->text_draw_cache) { DRW_text_cache_destroy(data->text_draw_cache); data->text_draw_cache = NULL; @@ -1011,10 +1058,7 @@ static void drw_engines_world_update(Scene *scene) return; } - LISTBASE_FOREACH (LinkData *, link, &DST.enabled_engines) { - DrawEngineType *engine = link->data; - ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); - + DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) { if (engine->id_update) { engine->id_update(data, &scene->world->id); } @@ -1036,11 +1080,7 @@ static void drw_engines_cache_populate(Object *ob) drw_batch_cache_validate(ob); } - int i = 0; - for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) { - DrawEngineType *engine = link->data; - ViewportEngineData *data = DST.vedata_array[i]; - + DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) { if (engine->id_update) { engine->id_update(data, &ob->id); } @@ -1063,25 +1103,17 @@ static void drw_engines_cache_populate(Object *ob) static void drw_engines_cache_finish(void) { - int i = 0; - for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) { - DrawEngineType *engine = link->data; - ViewportEngineData *data = DST.vedata_array[i]; - + DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) { if (engine->cache_finish) { engine->cache_finish(data); } } - MEM_freeN(DST.vedata_array); } static void drw_engines_draw_scene(void) { - LISTBASE_FOREACH (LinkData *, link, &DST.enabled_engines) { - DrawEngineType *engine = link->data; - ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) { PROFILE_START(stime); - if (engine->draw_scene) { DRW_stats_group_start(engine->idname); engine->draw_scene(data); @@ -1091,7 +1123,6 @@ static void drw_engines_draw_scene(void) } DRW_stats_group_end(); } - PROFILE_END_UPDATE(data->render_time, stime); } /* Reset state after drawing */ @@ -1100,9 +1131,7 @@ static void drw_engines_draw_scene(void) static void drw_engines_draw_text(void) { - LISTBASE_FOREACH (LinkData *, link, &DST.enabled_engines) { - DrawEngineType *engine = link->data; - ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) { PROFILE_START(stime); if (data->text_draw_cache) { @@ -1116,10 +1145,7 @@ static void drw_engines_draw_text(void) /* Draw render engine info. */ void DRW_draw_region_engine_info(int xoffset, int *yoffset, int line_height) { - LISTBASE_FOREACH (LinkData *, link, &DST.enabled_engines) { - DrawEngineType *engine = link->data; - ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); - + DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) { if (data->info[0] != '\0') { char *chr_current = data->info; char *chr_start = chr_current; @@ -1158,12 +1184,10 @@ void DRW_draw_region_engine_info(int xoffset, int *yoffset, int line_height) static void use_drw_engine(DrawEngineType *engine) { - LinkData *ld = MEM_callocN(sizeof(LinkData), "enabled engine link data"); - ld->data = engine; - BLI_addtail(&DST.enabled_engines, ld); + DRW_view_data_use_engine(DST.view_data_active, engine); } -/* Gather all draw engines needed and store them in DST.enabled_engines +/* Gather all draw engines needed and store them in DST.view_data_active * That also define the rendering order of engines */ static void drw_engines_enable_from_engine(const RenderEngineType *engine_type, eDrawType drawtype) { @@ -1252,22 +1276,12 @@ static void drw_engines_enable(ViewLayer *UNUSED(view_layer), static void drw_engines_disable(void) { - BLI_freelistN(&DST.enabled_engines); + DRW_view_data_reset(DST.view_data_active); } static void drw_engines_data_validate(void) { - int enabled_engines = BLI_listbase_count(&DST.enabled_engines); - void **engine_handle_array = BLI_array_alloca(engine_handle_array, enabled_engines + 1); - int i = 0; - - LISTBASE_FOREACH (LinkData *, link, &DST.enabled_engines) { - DrawEngineType *engine = link->data; - engine_handle_array[i++] = engine; - } - engine_handle_array[i] = NULL; - - GPU_viewport_engines_data_validate(DST.viewport, engine_handle_array); + DRW_view_data_free_unused(DST.view_data_active); } /* Fast check to see if gpencil drawing engine is needed. @@ -1294,55 +1308,57 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx) Scene *scene = update_ctx->scene; ViewLayer *view_layer = update_ctx->view_layer; + GPUViewport *viewport = WM_draw_region_get_viewport(region); + if (!viewport) { + return; + } + const bool gpencil_engine_needed = drw_gpencil_engine_needed(depsgraph, v3d); + /* XXX Really nasty locking. But else this could + * be executed by the material previews thread + * while rendering a viewport. */ + BLI_ticket_mutex_lock(DST.gl_context_mutex); + + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + + DST.draw_ctx = (DRWContextState){ + .region = region, + .rv3d = rv3d, + .v3d = v3d, + .scene = scene, + .view_layer = view_layer, + .obact = OBACT(view_layer), + .engine_type = engine_type, + .depsgraph = depsgraph, + .object_mode = OB_MODE_OBJECT, + }; + + /* Custom lightweight init to avoid reseting the mempools. */ + DST.viewport = viewport; + DST.vmempool = drw_viewport_data_ensure(DST.viewport); + /* Separate update for each stereo view. */ - for (int view = 0; view < 2; view++) { - GPUViewport *viewport = WM_draw_region_get_viewport(region); - if (!viewport) { - continue; - } - - /* XXX Really nasty locking. But else this could - * be executed by the material previews thread - * while rendering a viewport. */ - BLI_ticket_mutex_lock(DST.gl_context_mutex); - - /* Reset before using it. */ - drw_state_prepare_clean_for_draw(&DST); - - DST.viewport = viewport; - GPU_viewport_active_view_set(viewport, view); - DST.draw_ctx = (DRWContextState){ - .region = region, - .rv3d = rv3d, - .v3d = v3d, - .scene = scene, - .view_layer = view_layer, - .obact = OBACT(view_layer), - .engine_type = engine_type, - .depsgraph = depsgraph, - .object_mode = OB_MODE_OBJECT, - }; + int view_count = GPU_viewport_is_stereo_get(viewport) ? 2 : 1; + for (int view = 0; view < view_count; view++) { + DST.view_data_active = DST.vmempool->view_data[view]; drw_engines_enable(view_layer, engine_type, gpencil_engine_needed); drw_engines_data_validate(); - LISTBASE_FOREACH (LinkData *, link, &DST.enabled_engines) { - DrawEngineType *draw_engine = link->data; - ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine); - + DRW_ENABLED_ENGINE_ITER (DST.view_data_active, draw_engine, data) { if (draw_engine->view_update) { draw_engine->view_update(data); } } - DST.viewport = NULL; - drw_engines_disable(); - - BLI_ticket_mutex_unlock(DST.gl_context_mutex); } + + drw_manager_exit(&DST); + + BLI_ticket_mutex_unlock(DST.gl_context_mutex); } /** \} */ @@ -1513,8 +1529,6 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, RegionView3D *rv3d = region->regiondata; DST.draw_ctx.evil_C = evil_C; - DST.viewport = viewport; - /* Setup viewport */ DST.draw_ctx = (DRWContextState){ .region = region, .rv3d = rv3d, @@ -1531,8 +1545,8 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, drw_task_graph_init(); drw_context_state_init(); - drw_viewport_var_init(); - DRW_viewport_colormanagement_set(DST.viewport); + drw_manager_init(&DST, viewport, NULL); + DRW_viewport_colormanagement_set(viewport); const int object_type_exclude_viewport = v3d->object_type_exclude_viewport; /* Check if scene needs to perform the populate loop */ @@ -1591,7 +1605,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, DRW_render_instance_buffer_finish(); #ifdef USE_PROFILE - double *cache_time = GPU_viewport_cache_time_get(DST.viewport); + double *cache_time = DRW_view_data_cache_time_get(DST.view_data_active); PROFILE_END_UPDATE(*cache_time, stime); #endif } @@ -1631,12 +1645,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, DRW_state_reset(); drw_engines_disable(); - drw_viewport_cache_resize(); - -#ifdef DEBUG - /* Avoid accidental reuse. */ - drw_state_ensure_not_reused(&DST); -#endif + drw_manager_exit(&DST); } void DRW_draw_render_loop(struct Depsgraph *depsgraph, @@ -1674,6 +1683,9 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph, GPU_viewport_bind_from_offscreen(render_viewport, ofs); + /* Just here to avoid an assert but shouldn't be required in practice. */ + GPU_framebuffer_restore(); + /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); DST.options.is_image_render = is_image_render; @@ -1735,7 +1747,8 @@ static void DRW_render_gpencil_to_image(RenderEngine *engine, const rcti *rect) { if (draw_engine_gpencil_type.render_to_image) { - ViewportEngineData *gpdata = drw_viewport_engine_data_ensure(&draw_engine_gpencil_type); + ViewportEngineData *gpdata = DRW_view_data_engine_data_get_ensure(DST.view_data_active, + &draw_engine_gpencil_type); draw_engine_gpencil_type.render_to_image(gpdata, engine, render_layer, rect); } } @@ -1769,11 +1782,9 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph }; drw_context_state_init(); - DST.viewport = GPU_viewport_create(); const int size[2] = {engine->resolution_x, engine->resolution_y}; - GPU_viewport_size_set(DST.viewport, size); - drw_viewport_var_init(); + drw_manager_init(&DST, NULL, size); /* Main rendering. */ rctf view_rect; @@ -1793,13 +1804,12 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph DRW_render_gpencil_to_image(engine, render_layer, &render_rect); } - /* Force cache to reset. */ - drw_viewport_cache_resize(); - GPU_viewport_free(DST.viewport); DRW_state_reset(); GPU_depth_test(GPU_DEPTH_NONE); + drw_manager_exit(&DST); + /* Restore Drawing area. */ GPU_framebuffer_restore(); @@ -1848,13 +1858,12 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) }; drw_context_state_init(); - DST.viewport = GPU_viewport_create(); const int size[2] = {engine->resolution_x, engine->resolution_y}; - GPU_viewport_size_set(DST.viewport, size); - drw_viewport_var_init(); + drw_manager_init(&DST, NULL, size); - ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine_type); + ViewportEngineData *data = DRW_view_data_engine_data_get_ensure(DST.view_data_active, + draw_engine_type); /* Main rendering. */ rctf view_rect; @@ -1898,16 +1907,9 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) engine_type->draw_engine->store_metadata(data, final_render_result); } - /* Force cache to reset. */ - drw_viewport_cache_resize(); - - GPU_viewport_free(DST.viewport); GPU_framebuffer_restore(); -#ifdef DEBUG - /* Avoid accidental reuse. */ - drw_state_ensure_not_reused(&DST); -#endif + drw_manager_exit(&DST); /* Reset state after drawing */ DRW_state_reset(); @@ -1976,21 +1978,17 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type, }; drw_context_state_init(); - DST.viewport = GPU_viewport_create(); - const int size[2] = {1, 1}; - GPU_viewport_size_set(DST.viewport, size); - - drw_viewport_var_init(); + drw_manager_init(&DST, NULL, NULL); DRW_hair_init(); - ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine_type); + ViewportEngineData *data = DRW_view_data_engine_data_get_ensure(DST.view_data_active, + draw_engine_type); /* Execute the callback */ callback(data, user_data); DST.buffer_finish_called = false; - GPU_viewport_free(DST.viewport); GPU_framebuffer_restore(); /* The use of custom pipeline in other thread using the same @@ -1999,33 +1997,18 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type, * GPU_finish to sync seems to fix the issue. (see T62997) */ GPU_finish(); -#ifdef DEBUG - /* Avoid accidental reuse. */ - drw_state_ensure_not_reused(&DST); -#endif + drw_manager_exit(&DST); } /* Used when the render engine want to redo another cache populate inside the same render frame. */ void DRW_cache_restart(void) { - /* Save viewport size. */ - float size[2], inv_size[2]; - copy_v2_v2(size, DST.size); - copy_v2_v2(inv_size, DST.inv_size); - - /* Force cache to reset. */ - drw_viewport_cache_resize(); - - drw_viewport_var_init(); + drw_manager_init(&DST, DST.viewport, (int[2]){UNPACK2(DST.size)}); DST.buffer_finish_called = false; DRW_hair_init(); - - /* Restore. */ - copy_v2_v2(DST.size, size); - copy_v2_v2(DST.inv_size, inv_size); } void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, @@ -2037,9 +2020,6 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); DST.draw_ctx.evil_C = evil_C; - DST.viewport = viewport; - - /* Setup viewport */ DST.draw_ctx = (DRWContextState){ .region = region, .scene = scene, @@ -2053,8 +2033,8 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, }; drw_context_state_init(); - drw_viewport_var_init(); - DRW_viewport_colormanagement_set(DST.viewport); + drw_manager_init(&DST, viewport, NULL); + DRW_viewport_colormanagement_set(viewport); /* TODO(jbakker): Only populate when editor needs to draw object. * for the image editor this is when showing UV's. */ @@ -2098,7 +2078,7 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, DRW_render_instance_buffer_finish(); #ifdef USE_PROFILE - double *cache_time = GPU_viewport_cache_time_get(DST.viewport); + double *cache_time = DRW_view_data_cache_time_get(DST.view_data_active); PROFILE_END_UPDATE(*cache_time, stime); #endif } @@ -2180,12 +2160,7 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, DRW_state_reset(); drw_engines_disable(); - drw_viewport_cache_resize(); - -#ifdef DEBUG - /* Avoid accidental reuse. */ - drw_state_ensure_not_reused(&DST); -#endif + drw_manager_exit(&DST); } static struct DRWSelectBuffer { @@ -2222,7 +2197,7 @@ void DRW_render_instance_buffer_finish(void) { BLI_assert_msg(!DST.buffer_finish_called, "DRW_render_instance_buffer_finish called twice!"); DST.buffer_finish_called = true; - DRW_instance_buffer_finish(DST.idatalist); + DRW_instance_buffer_finish(DST.vmempool->idatalist); drw_resource_buffer_finish(DST.vmempool); } @@ -2305,11 +2280,22 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, } } - const int viewport_size[2] = {BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)}; - struct GPUViewport *viewport = GPU_viewport_create(); - GPU_viewport_size_set(viewport, viewport_size); + /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */ + DST.draw_ctx = (DRWContextState){ + .region = region, + .rv3d = rv3d, + .v3d = v3d, + .scene = scene, + .view_layer = view_layer, + .obact = obact, + .engine_type = engine_type, + .depsgraph = depsgraph, + }; + drw_context_state_init(); + + const int viewport_size[2] = {BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)}; + drw_manager_init(&DST, NULL, viewport_size); - DST.viewport = viewport; DST.options.is_select = true; DST.options.is_material_select = do_material_sub_selection; drw_task_graph_init(); @@ -2337,22 +2323,6 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, } drw_engines_data_validate(); - /* Setup viewport */ - - /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */ - DST.draw_ctx = (DRWContextState){ - .region = region, - .rv3d = rv3d, - .v3d = v3d, - .scene = scene, - .view_layer = view_layer, - .obact = obact, - .engine_type = engine_type, - .depsgraph = depsgraph, - }; - drw_context_state_init(); - drw_viewport_var_init(); - /* Update UBO's */ DRW_globals_update(); @@ -2456,14 +2426,10 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, DRW_state_reset(); drw_engines_disable(); -# ifdef DEBUG - /* Avoid accidental reuse. */ - drw_state_ensure_not_reused(&DST); -# endif + drw_manager_exit(&DST); + GPU_framebuffer_restore(); - /* Cleanup for selection state */ - GPU_viewport_free(viewport); #endif /* USE_GPU_SELECT */ } @@ -2485,7 +2451,6 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph, 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 */ @@ -2499,18 +2464,21 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph, .engine_type = engine_type, .depsgraph = depsgraph, }; + drw_context_state_init(); drw_task_graph_init(); - drw_engines_data_validate(); /* Setup frame-buffer. */ - DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get( - DST.viewport); - GPU_framebuffer_bind(fbl->depth_only_fb); - GPU_framebuffer_clear_depth(fbl->depth_only_fb, 1.0f); + GPUTexture *depth_tx = GPU_viewport_depth_texture(viewport); - /* Setup viewport */ - drw_context_state_init(); - drw_viewport_var_init(); + GPUFrameBuffer *depth_fb = NULL; + GPU_framebuffer_ensure_config(&depth_fb, + { + GPU_ATTACHMENT_TEXTURE(depth_tx), + GPU_ATTACHMENT_NONE, + }); + + GPU_framebuffer_bind(depth_fb); + GPU_framebuffer_clear_depth(depth_fb, 1.0f); /* Update UBO's */ DRW_globals_update(); @@ -2559,15 +2527,11 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph, /* TODO: Reading depth for operators should be done here. */ GPU_framebuffer_restore(); + GPU_framebuffer_free(depth_fb); drw_engines_disable(); - drw_viewport_cache_resize(); - -#ifdef DEBUG - /* Avoid accidental reuse. */ - drw_state_ensure_not_reused(&DST); -#endif + drw_manager_exit(&DST); /* Changing context. */ if (use_opengl_context) { @@ -2586,6 +2550,11 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph, /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); + /* Required by `drw_manager_init()` */ + DST.draw_ctx.region = region; + DST.draw_ctx.rv3d = region->regiondata; + drw_manager_init(&DST, viewport, NULL); + /* Get list of enabled engines */ { /* Required by `DRW_state_draw_support()` */ @@ -2611,6 +2580,11 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); + /* Required by `drw_manager_init()` */ + DST.draw_ctx.region = region; + DST.draw_ctx.rv3d = region->regiondata; + drw_manager_init(&DST, viewport, NULL); + use_drw_engine(&draw_engine_gpencil_type); drw_draw_depth_loop_impl(depsgraph, region, v3d, viewport, false); @@ -2648,9 +2622,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons drw_task_graph_init(); drw_context_state_init(); - /* Setup viewport */ - DST.viewport = viewport; - drw_viewport_var_init(); + drw_manager_init(&DST, viewport, NULL); /* Update UBO's */ UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); @@ -2677,7 +2649,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons DRW_render_instance_buffer_finish(); #else DST.buffer_finish_called = true; - // DRW_instance_buffer_finish(DST.idatalist); + // DRW_instance_buffer_finish(DST.vmempool->idatalist); drw_resource_buffer_finish(DST.vmempool); #endif } @@ -2689,12 +2661,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons drw_engines_disable(); - drw_viewport_cache_resize(); - -#ifdef DEBUG - /* Avoid accidental reuse. */ - drw_state_ensure_not_reused(&DST); -#endif + drw_manager_exit(&DST); } /** @@ -2710,10 +2677,17 @@ void DRW_draw_depth_object( GPU_matrix_mul(object->obmat); /* Setup frame-buffer. */ - DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); + GPUTexture *depth_tx = GPU_viewport_depth_texture(viewport); - GPU_framebuffer_bind(fbl->depth_only_fb); - GPU_framebuffer_clear_depth(fbl->depth_only_fb, 1.0f); + GPUFrameBuffer *depth_fb = NULL; + GPU_framebuffer_ensure_config(&depth_fb, + { + GPU_ATTACHMENT_TEXTURE(depth_tx), + GPU_ATTACHMENT_NONE, + }); + + GPU_framebuffer_bind(depth_fb); + GPU_framebuffer_clear_depth(depth_fb, 1.0f); GPU_depth_test(GPU_DEPTH_LESS_EQUAL); const float(*world_clip_planes)[4] = NULL; @@ -2763,6 +2737,9 @@ void DRW_draw_depth_object( GPU_matrix_set(rv3d->viewmat); GPU_depth_test(GPU_DEPTH_NONE); GPU_framebuffer_restore(); + + GPU_framebuffer_free(depth_fb); + DRW_opengl_context_disable(); } /** \} */ @@ -2895,7 +2872,12 @@ bool DRW_engine_render_support(DrawEngineType *draw_engine_type) void DRW_engine_register(DrawEngineType *draw_engine_type) { - BLI_addtail(&DRW_engines, draw_engine_type); + DRWRegisteredDrawEngine *draw_engine = MEM_mallocN(sizeof(DRWRegisteredDrawEngine), __func__); + draw_engine->draw_engine = draw_engine_type; + draw_engine->index = g_registered_engines.len; + + BLI_addtail(&g_registered_engines.engines, draw_engine); + g_registered_engines.len = BLI_listbase_count(&g_registered_engines.engines); } void DRW_engines_register(void) @@ -2966,14 +2948,15 @@ void DRW_engines_free(void) DRW_stats_free(); DRW_globals_free(); - DrawEngineType *next; - for (DrawEngineType *type = DRW_engines.first; type; type = next) { + DRWRegisteredDrawEngine *next; + for (DRWRegisteredDrawEngine *type = g_registered_engines.engines.first; type; type = next) { next = type->next; BLI_remlink(&R_engines, type); - if (type->engine_free) { - type->engine_free(); + if (type->draw_engine->engine_free) { + type->draw_engine->engine_free(); } + MEM_freeN(type); } DRW_UBO_FREE_SAFE(G_draw.block_ubo); diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index c09126c98ef..1bb1ee06354 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -97,6 +97,17 @@ struct Object; #endif /* USE_PROFILE */ /* ------------ Data Structure --------------- */ +/** + * Data structure to for registered draw engines that can store draw manager + * specific data. + */ +typedef struct DRWRegisteredDrawEngine { + void /*DRWRegisteredDrawEngine*/ *next, *prev; + DrawEngineType *draw_engine; + /** Index of the type in the lists. Index is used for dupli data. */ + int index; +} DRWRegisteredDrawEngine; + /** * Data structure containing all drawcalls organized by passes and materials. * DRWPass > DRWShadingGroup > DRWCall > DRWCallState @@ -495,6 +506,35 @@ typedef struct DRWDebugSphere { float color[4]; } DRWDebugSphere; +/* ------------- Memory Pools ------------ */ + +/* Contains memory pools information */ +typedef struct DRWData { + /** Instance data. */ + DRWInstanceDataList *idatalist; + /** Mempools for drawcalls. */ + struct BLI_memblock *commands; + struct BLI_memblock *commands_small; + struct BLI_memblock *callbuffers; + struct BLI_memblock *obmats; + struct BLI_memblock *obinfos; + struct BLI_memblock *cullstates; + struct BLI_memblock *shgroups; + struct BLI_memblock *uniforms; + struct BLI_memblock *views; + struct BLI_memblock *passes; + struct BLI_memblock *images; + struct GPUUniformBuf **matrices_ubo; + struct GPUUniformBuf **obinfos_ubo; + struct GHash *obattrs_ubo_pool; + uint ubo_len; + /** Texture pool to reuse temp texture across engines. */ + /* TODO(fclem) the pool could be shared even between viewports. */ + struct DRWTexturePool *texture_pool; + /** Per stereo view data. Contains engine data and default framebuffers. */ + struct DRWViewData *view_data[2]; +} DRWData; + /* ------------- DRAW MANAGER ------------ */ typedef struct DupliKey { @@ -509,8 +549,10 @@ typedef struct DupliKey { typedef struct DRWManager { /* TODO: clean up this struct a bit. */ /* Cache generation */ - ViewportMemoryPool *vmempool; - DRWInstanceDataList *idatalist; + /* TODO(fclem) Rename to data. */ + DRWData *vmempool; + /** Active view data structure for one of the 2 stereo view. Not related to DRWView. */ + struct DRWViewData *view_data_active; /* State of the object being evaluated if already allocated. */ DRWResourceHandle ob_handle; /** True if current DST.ob_state has its matching DRWObjectInfos init. */ @@ -567,10 +609,6 @@ typedef struct DRWManager { /* Convenience pointer to text_store owned by the viewport */ struct DRWTextStore **text_store_p; - ListBase enabled_engines; /* RenderEngineType */ - void **vedata_array; /* ViewportEngineData */ - int enabled_engine_count; /* Length of enabled_engines list. */ - bool buffer_finish_called; /* Avoid bad usage of DRW_render_instance_buffer_finish */ DRWView *view_default; @@ -627,7 +665,7 @@ 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); +void drw_resource_buffer_finish(DRWData *vmempool); /* Procedural Drawing */ GPUBatch *drw_cache_procedural_points_get(void); @@ -641,6 +679,13 @@ void drw_uniform_attrs_pool_update(struct GHash *table, struct Object *dupli_parent, struct DupliObject *dupli_source); +double *drw_engine_data_cache_time_get(GPUViewport *viewport); +void *drw_engine_data_engine_data_create(GPUViewport *viewport, void *engine_type); +void *drw_engine_data_engine_data_get(GPUViewport *viewport, void *engine_handle); +bool drw_engine_data_engines_data_validate(GPUViewport *viewport, void **engine_handle_array); +void drw_engine_data_cache_release(GPUViewport *viewport); +void drw_engine_data_free(GPUViewport *viewport); + #ifdef __cplusplus } #endif diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index af331c86a8b..f96bd474aec 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -87,7 +87,7 @@ static void draw_call_sort(DRWCommand *array, DRWCommand *array_tmp, int array_l memcpy(array, array_tmp, sizeof(*array) * array_len); } -void drw_resource_buffer_finish(ViewportMemoryPool *vmempool) +void drw_resource_buffer_finish(DRWData *vmempool) { int chunk_id = DRW_handle_chunk_get(&DST.resource_handle); int elem_id = DRW_handle_id_get(&DST.resource_handle); @@ -908,7 +908,8 @@ void DRW_shgroup_call_instances_with_attrs(DRWShadingGroup *shgroup, drw_command_set_select_id(shgroup, NULL, DST.select_id); } DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : NULL, ob); - GPUBatch *batch = DRW_temp_batch_instance_request(DST.idatalist, NULL, inst_attributes, geom); + GPUBatch *batch = DRW_temp_batch_instance_request( + DST.vmempool->idatalist, NULL, inst_attributes, geom); drw_command_draw_instance(shgroup, batch, handle, 0, true); } @@ -1128,7 +1129,7 @@ DRWCallBuffer *DRW_shgroup_call_buffer(DRWShadingGroup *shgroup, BLI_assert(format != NULL); DRWCallBuffer *callbuf = BLI_memblock_alloc(DST.vmempool->callbuffers); - callbuf->buf = DRW_temp_buffer_request(DST.idatalist, format, &callbuf->count); + callbuf->buf = DRW_temp_buffer_request(DST.vmempool->idatalist, format, &callbuf->count); callbuf->buf_select = NULL; callbuf->count = 0; @@ -1138,12 +1139,12 @@ DRWCallBuffer *DRW_shgroup_call_buffer(DRWShadingGroup *shgroup, GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT); } callbuf->buf_select = DRW_temp_buffer_request( - DST.idatalist, &inst_select_format, &callbuf->count); + DST.vmempool->idatalist, &inst_select_format, &callbuf->count); drw_command_set_select_id(shgroup, callbuf->buf_select, -1); } DRWResourceHandle handle = drw_resource_handle(shgroup, NULL, NULL); - GPUBatch *batch = DRW_temp_batch_request(DST.idatalist, callbuf->buf, prim_type); + GPUBatch *batch = DRW_temp_batch_request(DST.vmempool->idatalist, callbuf->buf, prim_type); drw_command_draw(shgroup, batch, handle); return callbuf; @@ -1157,7 +1158,7 @@ DRWCallBuffer *DRW_shgroup_call_buffer_instance(DRWShadingGroup *shgroup, BLI_assert(format != NULL); DRWCallBuffer *callbuf = BLI_memblock_alloc(DST.vmempool->callbuffers); - callbuf->buf = DRW_temp_buffer_request(DST.idatalist, format, &callbuf->count); + callbuf->buf = DRW_temp_buffer_request(DST.vmempool->idatalist, format, &callbuf->count); callbuf->buf_select = NULL; callbuf->count = 0; @@ -1167,12 +1168,13 @@ DRWCallBuffer *DRW_shgroup_call_buffer_instance(DRWShadingGroup *shgroup, GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT); } callbuf->buf_select = DRW_temp_buffer_request( - DST.idatalist, &inst_select_format, &callbuf->count); + DST.vmempool->idatalist, &inst_select_format, &callbuf->count); drw_command_set_select_id(shgroup, callbuf->buf_select, -1); } DRWResourceHandle handle = drw_resource_handle(shgroup, NULL, NULL); - GPUBatch *batch = DRW_temp_batch_instance_request(DST.idatalist, callbuf->buf, NULL, geom); + GPUBatch *batch = DRW_temp_batch_instance_request( + DST.vmempool->idatalist, callbuf->buf, NULL, geom); drw_command_draw(shgroup, batch, handle); return callbuf; diff --git a/source/blender/draw/intern/draw_manager_profiling.c b/source/blender/draw/intern/draw_manager_profiling.c index d9ba2cbf932..70fe12270f5 100644 --- a/source/blender/draw/intern/draw_manager_profiling.c +++ b/source/blender/draw/intern/draw_manager_profiling.c @@ -257,10 +257,9 @@ void DRW_stats_draw(const rcti *rect) /* Engines rows */ char time_to_txt[16]; - LISTBASE_FOREACH (LinkData *, link, &DST.enabled_engines) { + DRW_ENABLED_ENGINE_ITER(DST.view_data_active, engine, data) + { u = 0; - DrawEngineType *engine = link->data; - ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); draw_stat_5row(rect, u++, v, engine->idname, sizeof(engine->idname)); @@ -297,7 +296,7 @@ void DRW_stats_draw(const rcti *rect) v += 2; u = 0; - double *cache_time = GPU_viewport_cache_time_get(DST.viewport); + double *cache_time = DRW_view_data_cache_time_get(DST.view_data_active); sprintf(col_label, "Cache Time"); draw_stat_5row(rect, u++, v, col_label, sizeof(col_label)); sprintf(time_to_txt, "%.2fms", *cache_time); diff --git a/source/blender/draw/intern/draw_manager_text.h b/source/blender/draw/intern/draw_manager_text.h index 760259018bb..4f3a6153775 100644 --- a/source/blender/draw/intern/draw_manager_text.h +++ b/source/blender/draw/intern/draw_manager_text.h @@ -22,6 +22,10 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + struct ARegion; struct DRWTextStore; struct Object; @@ -57,3 +61,7 @@ enum { /* draw_manager.c */ struct DRWTextStore *DRW_text_cache_ensure(void); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c index 99e8ba968a2..86242468e4a 100644 --- a/source/blender/draw/intern/draw_manager_texture.c +++ b/source/blender/draw/intern/draw_manager_texture.c @@ -21,6 +21,7 @@ */ #include "draw_manager.h" +#include "draw_texture_pool.h" #ifndef NDEBUG /* Maybe gpu_texture.c is a better place for this. */ @@ -147,7 +148,7 @@ GPUTexture *DRW_texture_pool_query_2d(int w, DrawEngineType *engine_type) { BLI_assert(drw_texture_format_supports_framebuffer(format)); - GPUTexture *tex = GPU_viewport_texture_pool_query(DST.viewport, engine_type, w, h, format); + GPUTexture *tex = DRW_texture_pool_query(DST.vmempool->texture_pool, w, h, format, engine_type); return tex; } diff --git a/source/blender/draw/intern/draw_texture_pool.cc b/source/blender/draw/intern/draw_texture_pool.cc new file mode 100644 index 00000000000..544a763ddb9 --- /dev/null +++ b/source/blender/draw/intern/draw_texture_pool.cc @@ -0,0 +1,140 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2021, Blender Foundation. + */ + +/** \file + * \ingroup draw + */ + +#include "BKE_global.h" + +#include "BLI_vector.hh" + +#include "draw_texture_pool.h" + +using namespace blender; + +typedef struct DRWTexturePoolHandle { + uint64_t users_bits; + GPUTexture *texture; +} DRWTexturePoolHandle; + +struct DRWTexturePool { + Vector users; + Vector handles; + /* Cache last result to avoid linear search each time. */ + int last_user_id = -1; +}; + +DRWTexturePool *DRW_texture_pool_create(void) +{ + return new DRWTexturePool(); +} + +void DRW_texture_pool_free(DRWTexturePool *pool) +{ + /* Reseting the pool twice will effectively free all textures. */ + DRW_texture_pool_reset(pool); + DRW_texture_pool_reset(pool); + delete pool; +} + +/** + * Try to find a texture corresponding to params into the texture pool. + * If no texture was found, create one and add it to the pool. + */ +GPUTexture *DRW_texture_pool_query( + DRWTexturePool *pool, int width, int height, eGPUTextureFormat format, void *user) +{ + int user_id = pool->last_user_id; + /* Try cached value. */ + if (user_id != -1) { + if (pool->users[user_id] != user) { + user_id = -1; + } + } + /* Try to find inside previous users. */ + if (user_id == -1) { + user_id = pool->users.first_index_of_try(user); + } + /* No chance, needs to add it to the user list. */ + if (user_id == -1) { + user_id = pool->users.size(); + pool->users.append(user); + /* If there is more than 63 users, better refactor this system. */ + BLI_assert(user_id < 64); + } + pool->last_user_id = user_id; + + uint64_t user_bit = 1llu << user_id; + for (DRWTexturePoolHandle &handle : pool->handles) { + /* Skip if the user is already using this texture. */ + if (user_bit & handle.users_bits) { + continue; + } + /* If everthing matches reuse the texture. */ + if ((GPU_texture_format(handle.texture) == format) && + (GPU_texture_width(handle.texture) == width) && + (GPU_texture_height(handle.texture) == height)) { + handle.users_bits |= user_bit; + return handle.texture; + } + } + + char name[16] = "DRW_tex_pool"; + if (G.debug & G_DEBUG_GPU) { + int texture_id = pool->handles.size(); + SNPRINTF(name, "DRW_tex_pool_%d", texture_id); + } + + DRWTexturePoolHandle handle; + handle.users_bits = user_bit; + handle.texture = GPU_texture_create_2d(name, width, height, 1, format, nullptr); + pool->handles.append(handle); + /* Doing filtering for depth does not make sense when not doing shadow mapping, + * and enabling texture filtering on integer texture make them unreadable. */ + bool do_filter = !GPU_texture_depth(handle.texture) && !GPU_texture_integer(handle.texture); + GPU_texture_filter_mode(handle.texture, do_filter); + + return handle.texture; +} + +/* Resets the user bits for each texture in the pool and delete unused ones. */ +void DRW_texture_pool_reset(DRWTexturePool *pool) +{ + pool->last_user_id = -1; + + for (auto it = pool->handles.rbegin(); it != pool->handles.rend(); ++it) { + DRWTexturePoolHandle &handle = *it; + if (handle.users_bits == 0) { + if (handle.texture) { + GPU_texture_free(handle.texture); + handle.texture = nullptr; + } + } + else { + handle.users_bits = 0; + } + } + + /* Reverse iteration to make sure we only reorder with known good handles. */ + for (int i = pool->handles.size() - 1; i >= 0; i--) { + if (!pool->handles[i].texture) { + pool->handles.remove_and_reorder(i); + } + } +} \ No newline at end of file diff --git a/source/blender/draw/DRW_engine_types.h b/source/blender/draw/intern/draw_texture_pool.h similarity index 54% rename from source/blender/draw/DRW_engine_types.h rename to source/blender/draw/intern/draw_texture_pool.h index 807f654f559..f0b8f775c75 100644 --- a/source/blender/draw/DRW_engine_types.h +++ b/source/blender/draw/intern/draw_texture_pool.h @@ -13,38 +13,34 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Copyright 2016, Blender Foundation. + * Copyright 2021, Blender Foundation. */ /** \file * \ingroup draw + * + * Texture pool + * A pool that gives temporary render targets that can be reused through other parts of the + * render pipeline. + * Expect texture data is garbage when acquiring it. */ #pragma once +#include "GPU_texture.h" + +typedef struct DRWTexturePool DRWTexturePool; + #ifdef __cplusplus extern "C" { #endif -/* Buffer and textures used by the viewport by default */ -typedef struct DefaultFramebufferList { - struct GPUFrameBuffer *default_fb; - struct GPUFrameBuffer *overlay_fb; - struct GPUFrameBuffer *in_front_fb; - struct GPUFrameBuffer *color_only_fb; - struct GPUFrameBuffer *depth_only_fb; - struct GPUFrameBuffer *overlay_only_fb; - struct GPUFrameBuffer *stereo_comp_fb; -} DefaultFramebufferList; +DRWTexturePool *DRW_texture_pool_create(void); +void DRW_texture_pool_free(DRWTexturePool *pool); -typedef struct DefaultTextureList { - struct GPUTexture *color; - struct GPUTexture *color_overlay; - struct GPUTexture *color_stereo; - struct GPUTexture *color_overlay_stereo; - struct GPUTexture *depth; - struct GPUTexture *depth_in_front; -} DefaultTextureList; +GPUTexture *DRW_texture_pool_query( + DRWTexturePool *pool, int width, int height, eGPUTextureFormat format, void *user); +void DRW_texture_pool_reset(DRWTexturePool *pool); #ifdef __cplusplus } diff --git a/source/blender/draw/intern/draw_view_data.cc b/source/blender/draw/intern/draw_view_data.cc new file mode 100644 index 00000000000..55ebbf82c29 --- /dev/null +++ b/source/blender/draw/intern/draw_view_data.cc @@ -0,0 +1,243 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2021, Blender Foundation. + */ + +/** \file + * \ingroup draw + */ + +#include "BLI_vector.hh" + +#include "GPU_viewport.h" + +#include "DRW_render.h" + +#include "draw_instance_data.h" + +#include "draw_manager_text.h" + +#include "draw_manager.h" +#include "draw_view_data.h" + +using namespace blender; + +struct DRWViewData { + DefaultFramebufferList dfbl = {}; + DefaultTextureList dtxl = {}; + /** True indicates the textures inside dtxl are from the viewport and should not be freed. */ + bool from_viewport = false; + /** Common size for texture in the engines texture list. + * We free all texture lists if it changes. */ + int texture_list_size[2] = {0, 0}; + + double cache_time = 0.0; + + Vector engines; + Vector enabled_engines; +}; + +/** + * Creates a view data with all possible engines type for this view. + * + * `engine_types` contains `DRWRegisteredDrawEngine`. + * */ +DRWViewData *DRW_view_data_create(ListBase *engine_types) +{ + DRWViewData *view_data = new DRWViewData(); + LISTBASE_FOREACH (DRWRegisteredDrawEngine *, type, engine_types) { + ViewportEngineData engine = {}; + engine.engine_type = type; + view_data->engines.append(engine); + } + return view_data; +} + +void DRW_view_data_default_lists_from_viewport(DRWViewData *view_data, GPUViewport *viewport) +{ + int active_view = GPU_viewport_active_view_get(viewport); + view_data->from_viewport = true; + + DefaultFramebufferList *dfbl = &view_data->dfbl; + DefaultTextureList *dtxl = &view_data->dtxl; + /* Depth texture is shared between both stereo views. */ + dtxl->depth = GPU_viewport_depth_texture(viewport); + dtxl->color = GPU_viewport_color_texture(viewport, active_view); + dtxl->color_overlay = GPU_viewport_overlay_texture(viewport, active_view); + + GPU_framebuffer_ensure_config(&dfbl->default_fb, + { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(dtxl->color), + }); + GPU_framebuffer_ensure_config(&dfbl->overlay_fb, + { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay), + }); + GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, + { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_NONE, + }); + GPU_framebuffer_ensure_config(&dfbl->color_only_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(dtxl->color), + }); + GPU_framebuffer_ensure_config(&dfbl->overlay_only_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay), + }); +} + +static void draw_viewport_engines_data_clear(ViewportEngineData *data) +{ + DrawEngineType *engine_type = data->engine_type->draw_engine; + const DrawEngineDataSize *data_size = engine_type->vedata_size; + + for (int i = 0; data->fbl && i < data_size->fbl_len; i++) { + GPU_FRAMEBUFFER_FREE_SAFE(data->fbl->framebuffers[i]); + } + for (int i = 0; data->txl && i < data_size->txl_len; i++) { + GPU_TEXTURE_FREE_SAFE(data->txl->textures[i]); + } + for (int i = 0; data->stl && i < data_size->stl_len; i++) { + MEM_SAFE_FREE(data->stl->storage[i]); + } + + MEM_SAFE_FREE(data->fbl); + MEM_SAFE_FREE(data->txl); + MEM_SAFE_FREE(data->psl); + MEM_SAFE_FREE(data->stl); + + if (data->text_draw_cache) { + DRW_text_cache_destroy(data->text_draw_cache); + data->text_draw_cache = nullptr; + } +} + +static void draw_view_data_clear(DRWViewData *view_data) +{ + GPU_FRAMEBUFFER_FREE_SAFE(view_data->dfbl.default_fb); + GPU_FRAMEBUFFER_FREE_SAFE(view_data->dfbl.overlay_fb); + GPU_FRAMEBUFFER_FREE_SAFE(view_data->dfbl.in_front_fb); + GPU_FRAMEBUFFER_FREE_SAFE(view_data->dfbl.color_only_fb); + GPU_FRAMEBUFFER_FREE_SAFE(view_data->dfbl.depth_only_fb); + GPU_FRAMEBUFFER_FREE_SAFE(view_data->dfbl.overlay_only_fb); + + if (!view_data->from_viewport) { + GPU_TEXTURE_FREE_SAFE(view_data->dtxl.color); + GPU_TEXTURE_FREE_SAFE(view_data->dtxl.color_overlay); + GPU_TEXTURE_FREE_SAFE(view_data->dtxl.depth); + } + GPU_TEXTURE_FREE_SAFE(view_data->dtxl.depth_in_front); + + for (ViewportEngineData &engine : view_data->engines) { + draw_viewport_engines_data_clear(&engine); + } + + view_data->texture_list_size[0] = view_data->texture_list_size[1] = 0; + view_data->cache_time = 0.0f; +} + +void DRW_view_data_free(DRWViewData *view_data) +{ + draw_view_data_clear(view_data); + delete view_data; +} + +void DRW_view_data_texture_list_size_validate(DRWViewData *view_data, const int size[2]) +{ + if (!equals_v2v2_int(view_data->texture_list_size, size)) { + draw_view_data_clear(view_data); + copy_v2_v2_int(view_data->texture_list_size, size); + } +} + +ViewportEngineData *DRW_view_data_engine_data_get_ensure(DRWViewData *view_data, + DrawEngineType *engine_type) +{ + for (ViewportEngineData &engine : view_data->engines) { + if (engine.engine_type->draw_engine == engine_type) { + if (engine.fbl == nullptr) { + const DrawEngineDataSize *data_size = engine_type->vedata_size; + engine.fbl = (FramebufferList *)MEM_calloc_arrayN( + data_size->fbl_len, sizeof(GPUFrameBuffer *), "FramebufferList"); + engine.txl = (TextureList *)MEM_calloc_arrayN( + data_size->txl_len, sizeof(GPUTexture *), "TextureList"); + engine.psl = (PassList *)MEM_calloc_arrayN( + data_size->psl_len, sizeof(DRWPass *), "PassList"); + engine.stl = (StorageList *)MEM_calloc_arrayN( + data_size->stl_len, sizeof(void *), "StorageList"); + } + return &engine; + } + } + return nullptr; +} + +void DRW_view_data_use_engine(DRWViewData *view_data, DrawEngineType *engine_type) +{ + ViewportEngineData *engine = DRW_view_data_engine_data_get_ensure(view_data, engine_type); + view_data->enabled_engines.append(engine); +} + +void DRW_view_data_reset(DRWViewData *view_data) +{ + view_data->enabled_engines.clear(); +} + +void DRW_view_data_free_unused(DRWViewData *view_data) +{ + for (ViewportEngineData &engine : view_data->engines) { + if (view_data->enabled_engines.first_index_of_try(&engine) == -1) { + draw_viewport_engines_data_clear(&engine); + } + } +} + +double *DRW_view_data_cache_time_get(DRWViewData *view_data) +{ + return &view_data->cache_time; +} + +DefaultFramebufferList *DRW_view_data_default_framebuffer_list_get(DRWViewData *view_data) +{ + return &view_data->dfbl; +} + +DefaultTextureList *DRW_view_data_default_texture_list_get(DRWViewData *view_data) +{ + return &view_data->dtxl; +} + +void DRW_view_data_enabled_engine_iter_begin(DRWEngineIterator *iterator, DRWViewData *view_data) +{ + iterator->id = 0; + iterator->end = view_data->enabled_engines.size(); + iterator->engines = view_data->enabled_engines.data(); +} + +ViewportEngineData *DRW_view_data_enabled_engine_iter_step(DRWEngineIterator *iterator) +{ + if (iterator->id >= iterator->end) { + return nullptr; + } + ViewportEngineData *engine = iterator->engines[iterator->id++]; + return engine; +} diff --git a/source/blender/draw/intern/draw_view_data.h b/source/blender/draw/intern/draw_view_data.h new file mode 100644 index 00000000000..c8176170a61 --- /dev/null +++ b/source/blender/draw/intern/draw_view_data.h @@ -0,0 +1,139 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2021, Blender Foundation. + */ + +/** \file + * \ingroup draw + * + * Engine data + * Structure containing each draw engine instance data. + */ + +#pragma once + +#define GPU_INFO_SIZE 512 /* IMA_MAX_RENDER_TEXT */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct GPUViewport; +struct DrawEngineType; +struct DRWRegisteredDrawEngine; + +/* NOTE these structs are only here for reading the actual lists from the engine. + * The actual length of them is stored in a ViewportEngineData_Info. + * The length of 1 is just here to avoid compiler warning. */ +typedef struct FramebufferList { + struct GPUFrameBuffer *framebuffers[1]; +} FramebufferList; + +typedef struct TextureList { + struct GPUTexture *textures[1]; +} TextureList; + +typedef struct PassList { + struct DRWPass *passes[1]; +} PassList; + +/* Stores custom structs from the engine that have been MEM_(m/c)allocN'ed. */ +typedef struct StorageList { + void *storage[1]; +} StorageList; + +typedef struct ViewportEngineData { + /* Not owning pointer to the draw engine. */ + struct DRWRegisteredDrawEngine *engine_type; + + FramebufferList *fbl; + TextureList *txl; + PassList *psl; + StorageList *stl; + char info[GPU_INFO_SIZE]; + + /* we may want to put this elsewhere */ + struct DRWTextStore *text_draw_cache; + + /* Profiling data */ + double init_time; + double render_time; + double background_time; +} ViewportEngineData; + +typedef struct ViewportEngineData_Info { + int fbl_len; + int txl_len; + int psl_len; + int stl_len; +} ViewportEngineData_Info; + +/* Buffer and textures used by the viewport by default */ +typedef struct DefaultFramebufferList { + struct GPUFrameBuffer *default_fb; + struct GPUFrameBuffer *overlay_fb; + struct GPUFrameBuffer *in_front_fb; + struct GPUFrameBuffer *color_only_fb; + struct GPUFrameBuffer *depth_only_fb; + struct GPUFrameBuffer *overlay_only_fb; +} DefaultFramebufferList; + +typedef struct DefaultTextureList { + struct GPUTexture *color; + struct GPUTexture *color_overlay; + struct GPUTexture *depth; + struct GPUTexture *depth_in_front; +} DefaultTextureList; + +typedef struct DRWViewData DRWViewData; + +DRWViewData *DRW_view_data_create(ListBase *engine_types); +void DRW_view_data_free(DRWViewData *view_data); + +void DRW_view_data_default_lists_from_viewport(DRWViewData *view_data, + struct GPUViewport *viewport); +void DRW_view_data_texture_list_size_validate(DRWViewData *view_data, const int size[2]); +ViewportEngineData *DRW_view_data_engine_data_get_ensure(DRWViewData *view_data, + struct DrawEngineType *engine_type_); +void DRW_view_data_use_engine(DRWViewData *view_data, struct DrawEngineType *engine_type); +void DRW_view_data_reset(DRWViewData *view_data); +void DRW_view_data_free_unused(DRWViewData *view_data); +double *DRW_view_data_cache_time_get(DRWViewData *view_data); +DefaultFramebufferList *DRW_view_data_default_framebuffer_list_get(DRWViewData *view_data); +DefaultTextureList *DRW_view_data_default_texture_list_get(DRWViewData *view_data); + +typedef struct DRWEngineIterator { + int id, end; + ViewportEngineData **engines; +} DRWEngineIterator; + +/* Iterate over used engines of this view_data. */ +void DRW_view_data_enabled_engine_iter_begin(DRWEngineIterator *iterator, DRWViewData *view_data); +ViewportEngineData *DRW_view_data_enabled_engine_iter_step(DRWEngineIterator *iterator); + +#define DRW_ENABLED_ENGINE_ITER(view_data_, engine_, data_) \ + DRWEngineIterator iterator; \ + ViewportEngineData *data_; \ + struct DrawEngineType *engine_; \ + DRW_view_data_enabled_engine_iter_begin(&iterator, view_data_); \ + /* WATCH Comma operator trickery ahead! This tests engine_ == NULL. */ \ + while ((data_ = DRW_view_data_enabled_engine_iter_step(&iterator), \ + engine_ = (data_ != NULL) ? (struct DrawEngineType *)data_->engine_type->draw_engine : \ + NULL)) + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 79148035a25..1cfd83c503e 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2180,13 +2180,17 @@ static void validate_object_select_id(struct Depsgraph *depsgraph, * Calling this function should be avoided during interactive drawing. */ static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void *data) { - DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport); + GPUTexture *depth_tx = GPU_viewport_depth_texture(viewport); - GPUFrameBuffer *tmp_fb = GPU_framebuffer_create(__func__); - GPU_framebuffer_texture_attach(tmp_fb, dtxl->depth, 0, 0); - GPU_framebuffer_bind(tmp_fb); + GPUFrameBuffer *depth_read_fb = NULL; + GPU_framebuffer_ensure_config(&depth_read_fb, + { + GPU_ATTACHMENT_TEXTURE(depth_tx), + GPU_ATTACHMENT_NONE, + }); - GPU_framebuffer_read_depth(tmp_fb, + GPU_framebuffer_bind(depth_read_fb); + GPU_framebuffer_read_depth(depth_read_fb, rect->xmin, rect->ymin, BLI_rcti_size_x(rect), @@ -2195,7 +2199,7 @@ static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void data); GPU_framebuffer_restore(); - GPU_framebuffer_free(tmp_fb); + GPU_framebuffer_free(depth_read_fb); } void ED_view3d_select_id_validate(ViewContext *vc) @@ -2265,12 +2269,11 @@ static ViewDepths *view3d_depths_create(ARegion *region) ViewDepths *d = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); d->w = region->winx; d->h = region->winy; - d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); { GPUViewport *viewport = WM_draw_region_get_viewport(region); - DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); - GPU_framebuffer_read_depth(fbl->depth_only_fb, 0, 0, d->w, d->h, GPU_DATA_FLOAT, d->depths); + GPUTexture *depth_tx = GPU_viewport_depth_texture(viewport); + d->depths = GPU_texture_read(depth_tx, GPU_DATA_FLOAT, 0); /* Assumed to be this as they are never changed. */ d->depth_range[0] = 0.0; diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index 9a1885160b6..deff9e47871 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -52,6 +52,14 @@ typedef enum eGPUSamplerState { GPU_SAMPLER_REPEAT = (GPU_SAMPLER_REPEAT_S | GPU_SAMPLER_REPEAT_T | GPU_SAMPLER_REPEAT_R), } eGPUSamplerState; +#define GPU_TEXTURE_FREE_SAFE(texture) \ + do { \ + if (texture != NULL) { \ + GPU_texture_free(texture); \ + texture = NULL; \ + } \ + } while (0) + /* `GPU_SAMPLER_MAX` is not a valid enum value, but only a limit. * It also creates a bad mask for the `NOT` operator in `ENUM_OPERATORS`. */ diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index 0ecd5f3eb7b..4d9970dac90 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -35,76 +35,15 @@ extern "C" { #endif -#define GPU_INFO_SIZE 512 /* IMA_MAX_RENDER_TEXT */ #define GLA_PIXEL_OFS 0.375f typedef struct GHash GHash; typedef struct GPUViewport GPUViewport; struct GPUFrameBuffer; - -/* Contains memory pools information. */ -typedef struct ViewportMemoryPool { - struct BLI_memblock *commands; - struct BLI_memblock *commands_small; - struct BLI_memblock *callbuffers; - struct BLI_memblock *obmats; - struct BLI_memblock *obinfos; - struct BLI_memblock *cullstates; - struct BLI_memblock *shgroups; - struct BLI_memblock *uniforms; - struct BLI_memblock *views; - struct BLI_memblock *passes; - struct BLI_memblock *images; - struct GPUUniformBuf **matrices_ubo; - struct GPUUniformBuf **obinfos_ubo; - struct GHash *obattrs_ubo_pool; - uint ubo_len; -} ViewportMemoryPool; - -/* All FramebufferLists are just the same pointers with different names. */ -typedef struct FramebufferList { - struct GPUFrameBuffer *framebuffers[1]; -} FramebufferList; - -typedef struct TextureList { - struct GPUTexture *textures[1]; -} TextureList; - -typedef struct PassList { - struct DRWPass *passes[1]; -} PassList; - -typedef struct StorageList { - void *storage[1]; /* Custom structs from the engine. */ -} StorageList; - -typedef struct ViewportEngineData { - void *engine_type; - - FramebufferList *fbl; - TextureList *txl; - PassList *psl; - StorageList *stl; - char info[GPU_INFO_SIZE]; - - TextureList *txl_stereo; - StorageList *stl_stereo; - /* We may want to put this elsewhere. */ - struct DRWTextStore *text_draw_cache; - - /* Profiling data. */ - double init_time; - double render_time; - double background_time; -} ViewportEngineData; - -typedef struct ViewportEngineData_Info { - int fbl_len; - int txl_len; - int psl_len; - int stl_len; -} ViewportEngineData_Info; +struct DefaultFramebufferList; +struct DefaultTextureList; +struct DRWData; GPUViewport *GPU_viewport_create(void); GPUViewport *GPU_viewport_stereo_create(void); @@ -129,35 +68,21 @@ void GPU_viewport_unbind_from_offscreen(GPUViewport *viewport, bool display_colorspace, bool do_overlay_merge); -ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport); -struct DRWInstanceDataList *GPU_viewport_instance_data_list_get(GPUViewport *viewport); +struct DRWData **GPU_viewport_data_get(GPUViewport *viewport); -void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type); -void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_handle); -void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport); void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo_format); -void *GPU_viewport_texture_list_get(GPUViewport *viewport); -void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]); -void GPU_viewport_size_set(GPUViewport *viewport, const int size[2]); -void GPU_viewport_active_view_set(GPUViewport *viewport, int view); - -/* Profiling. */ -double *GPU_viewport_cache_time_get(GPUViewport *viewport); void GPU_viewport_tag_update(GPUViewport *viewport); bool GPU_viewport_do_update(GPUViewport *viewport); +int GPU_viewport_active_view_get(GPUViewport *viewport); +bool GPU_viewport_is_stereo_get(GPUViewport *viewport); + GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport, int view); +GPUTexture *GPU_viewport_overlay_texture(GPUViewport *viewport, int view); +GPUTexture *GPU_viewport_depth_texture(GPUViewport *viewport); -/* Texture pool. */ -GPUTexture *GPU_viewport_texture_pool_query( - GPUViewport *viewport, void *engine, int width, int height, int format); - -bool GPU_viewport_engines_data_validate(GPUViewport *viewport, void **engine_handle_array); -void GPU_viewport_cache_release(GPUViewport *viewport); - -struct GPUFrameBuffer *GPU_viewport_framebuffer_default_get(GPUViewport *viewport); -struct GPUFrameBuffer *GPU_viewport_framebuffer_overlay_get(GPUViewport *viewport); +GPUFrameBuffer *GPU_viewport_framebuffer_overlay_get(GPUViewport *viewport); #ifdef __cplusplus } diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index dd63edea0db..ccd9a4c061b 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -48,22 +48,6 @@ #include "MEM_guardedalloc.h" -static const int default_fbl_len = (sizeof(DefaultFramebufferList)) / sizeof(void *); -static const int default_txl_len = (sizeof(DefaultTextureList)) / sizeof(void *); - -#define MAX_ENABLE_ENGINE 8 - -/* Maximum number of simultaneous engine enabled at the same time. - * Setting it lower than the real number will do lead to - * higher VRAM usage due to sub-efficient buffer reuse. */ -#define MAX_ENGINE_BUFFER_SHARING 5 - -typedef struct ViewportTempTexture { - struct ViewportTempTexture *next, *prev; - void *user[MAX_ENGINE_BUFFER_SHARING]; - GPUTexture *texture; -} ViewportTempTexture; - /* Struct storing a viewport specific GPUBatch. * The end-goal is to have a single batch shared across viewport and use a model matrix to place * the batch. Due to OCIO and Image/UV editor we are not able to use an model matrix yet. */ @@ -89,23 +73,17 @@ struct GPUViewport { /* Set the active view (for stereoscopic viewport rendering). */ int active_view; - /* If engine_handles mismatch we free all #ViewportEngineData in this viewport. */ - struct { - void *handle; - ViewportEngineData *data; - } engine_data[MAX_ENABLE_ENGINE]; - - DefaultFramebufferList *fbl; - DefaultTextureList *txl; - - ViewportMemoryPool vmempool; /* Used for rendering data structure. */ - struct DRWInstanceDataList *idatalist; /* Used for rendering data structure. */ - - ListBase - tex_pool; /* ViewportTempTexture list : Temporary textures shared across draw engines. */ - - /* Profiling data. */ - double cache_time; + /* Viewport Resources. */ + struct DRWData *draw_data; + /** Color buffers, one for each stereo view. Only one if not stereo viewport. */ + GPUTexture *color_render_tx[2]; + GPUTexture *color_overlay_tx[2]; + /** Depth buffer. Can be shared with GPUOffscreen. */ + GPUTexture *depth_tx; + /** Compositing framebuffer for stereo viewport. */ + GPUFrameBuffer *stereo_comp_fb; + /** Overlay framebuffer for drawing outside of DRW module. */ + GPUFrameBuffer *overlay_fb; /* Color management. */ ColorManagedViewSettings view_settings; @@ -123,12 +101,6 @@ enum { GPU_VIEWPORT_STEREO = (1 << 1), }; -static void gpu_viewport_buffers_free( - FramebufferList *fbl, int fbl_len, TextureList *txl, TextureList *txl_stereo, int txl_len); -static void gpu_viewport_storage_free(StorageList *stl, int stl_len); -static void gpu_viewport_passes_free(PassList *psl, int psl_len); -static void gpu_viewport_texture_pool_free(GPUViewport *viewport); - void GPU_viewport_tag_update(GPUViewport *viewport) { viewport->flag |= DO_UPDATE; @@ -144,12 +116,9 @@ bool GPU_viewport_do_update(GPUViewport *viewport) GPUViewport *GPU_viewport_create(void) { GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport"); - viewport->fbl = MEM_callocN(sizeof(DefaultFramebufferList), "FramebufferList"); - viewport->txl = MEM_callocN(sizeof(DefaultTextureList), "TextureList"); - viewport->idatalist = DRW_instance_data_list_create(); viewport->do_color_management = false; viewport->size[0] = viewport->size[1] = -1; - viewport->active_view = -1; + viewport->active_view = 0; return viewport; } @@ -160,343 +129,55 @@ GPUViewport *GPU_viewport_stereo_create(void) return viewport; } -static void gpu_viewport_framebuffer_view_set(GPUViewport *viewport, int view) +struct DRWData **GPU_viewport_data_get(GPUViewport *viewport) { - /* Early check if the view is the latest requested. */ - if (viewport->active_view == view) { - return; - } - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; - - /* Only swap the texture when this is a Stereo Viewport. */ - if (((viewport->flag & GPU_VIEWPORT_STEREO) != 0)) { - SWAP(GPUTexture *, dtxl->color, dtxl->color_stereo); - SWAP(GPUTexture *, dtxl->color_overlay, dtxl->color_overlay_stereo); - - for (int i = 0; i < MAX_ENABLE_ENGINE; i++) { - if (viewport->engine_data[i].handle != NULL) { - ViewportEngineData *data = viewport->engine_data[i].data; - SWAP(StorageList *, data->stl, data->stl_stereo); - SWAP(TextureList *, data->txl, data->txl_stereo); - } - else { - break; - } - } - } - - GPU_framebuffer_ensure_config(&dfbl->default_fb, - { - GPU_ATTACHMENT_TEXTURE(dtxl->depth), - GPU_ATTACHMENT_TEXTURE(dtxl->color), - }); - - GPU_framebuffer_ensure_config(&dfbl->overlay_fb, - { - GPU_ATTACHMENT_TEXTURE(dtxl->depth), - GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay), - }); - - GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, - { - GPU_ATTACHMENT_TEXTURE(dtxl->depth), - GPU_ATTACHMENT_NONE, - }); - - GPU_framebuffer_ensure_config(&dfbl->color_only_fb, - { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(dtxl->color), - }); - - GPU_framebuffer_ensure_config(&dfbl->overlay_only_fb, - { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay), - }); - - viewport->active_view = view; + return &viewport->draw_data; } -void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type) +static void gpu_viewport_textures_create(GPUViewport *viewport) { - ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData"); - int fbl_len, txl_len, psl_len, stl_len; - - DRW_engine_viewport_data_size_get(engine_type, &fbl_len, &txl_len, &psl_len, &stl_len); - - data->engine_type = engine_type; - - data->fbl = MEM_callocN((sizeof(void *) * fbl_len) + sizeof(FramebufferList), "FramebufferList"); - data->txl = MEM_callocN((sizeof(void *) * txl_len) + sizeof(TextureList), "TextureList"); - data->psl = MEM_callocN((sizeof(void *) * psl_len) + sizeof(PassList), "PassList"); - data->stl = MEM_callocN((sizeof(void *) * stl_len) + sizeof(StorageList), "StorageList"); - - if ((viewport->flag & GPU_VIEWPORT_STEREO) != 0) { - data->txl_stereo = MEM_callocN((sizeof(void *) * txl_len) + sizeof(TextureList), - "TextureList"); - data->stl_stereo = MEM_callocN((sizeof(void *) * stl_len) + sizeof(StorageList), - "StorageList"); - } - - for (int i = 0; i < MAX_ENABLE_ENGINE; i++) { - if (viewport->engine_data[i].handle == NULL) { - viewport->engine_data[i].handle = engine_type; - viewport->engine_data[i].data = data; - return data; - } - } - - BLI_assert_msg(0, "Too many draw engines enabled at the same time"); - return NULL; -} - -static void gpu_viewport_engines_data_free(GPUViewport *viewport) -{ - int fbl_len, txl_len, psl_len, stl_len; - - for (int i = 0; i < MAX_ENABLE_ENGINE && viewport->engine_data[i].handle; i++) { - ViewportEngineData *data = viewport->engine_data[i].data; - - DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, &psl_len, &stl_len); - - gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, data->txl_stereo, txl_len); - gpu_viewport_passes_free(data->psl, psl_len); - gpu_viewport_storage_free(data->stl, stl_len); - - MEM_freeN(data->fbl); - MEM_freeN(data->txl); - MEM_freeN(data->psl); - MEM_freeN(data->stl); - - if ((viewport->flag & GPU_VIEWPORT_STEREO) != 0) { - gpu_viewport_storage_free(data->stl_stereo, stl_len); - MEM_freeN(data->txl_stereo); - MEM_freeN(data->stl_stereo); - } - /* We could handle this in the DRW module */ - if (data->text_draw_cache) { - extern void DRW_text_cache_destroy(struct DRWTextStore * dt); - DRW_text_cache_destroy(data->text_draw_cache); - data->text_draw_cache = NULL; - } - - MEM_freeN(data); - - /* Mark as unused. */ - viewport->engine_data[i].handle = NULL; - } - - gpu_viewport_texture_pool_free(viewport); -} - -void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_handle) -{ - BLI_assert(engine_handle != NULL); - - for (int i = 0; i < MAX_ENABLE_ENGINE; i++) { - if (viewport->engine_data[i].handle == engine_handle) { - return viewport->engine_data[i].data; - } - } - return NULL; -} - -ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport) -{ - return &viewport->vmempool; -} - -struct DRWInstanceDataList *GPU_viewport_instance_data_list_get(GPUViewport *viewport) -{ - return viewport->idatalist; -} - -/* Note this function is only allowed to be called from `DRW_notify_view_update`. The rest - * should bind the correct viewport. - * - * The reason is that DRW_notify_view_update can be called from a different thread, but needs - * access to the engine data. */ -void GPU_viewport_active_view_set(GPUViewport *viewport, int view) -{ - gpu_viewport_framebuffer_view_set(viewport, view); -} - -void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport) -{ - return viewport->fbl; -} - -void *GPU_viewport_texture_list_get(GPUViewport *viewport) -{ - return viewport->txl; -} - -void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]) -{ - copy_v2_v2_int(size, viewport->size); -} - -/** - * Special case, this is needed for when we have a viewport without a frame-buffer output - * (occlusion queries for eg) - * but still need to set the size since it may be used for other calculations. - */ -void GPU_viewport_size_set(GPUViewport *viewport, const int size[2]) -{ - copy_v2_v2_int(viewport->size, size); -} - -double *GPU_viewport_cache_time_get(GPUViewport *viewport) -{ - return &viewport->cache_time; -} - -/** - * Try to find a texture corresponding to params into the texture pool. - * If no texture was found, create one and add it to the pool. - */ -GPUTexture *GPU_viewport_texture_pool_query( - GPUViewport *viewport, void *engine, int width, int height, int format) -{ - GPUTexture *tex; - - LISTBASE_FOREACH (ViewportTempTexture *, tmp_tex, &viewport->tex_pool) { - if ((GPU_texture_format(tmp_tex->texture) == format) && - (GPU_texture_width(tmp_tex->texture) == width) && - (GPU_texture_height(tmp_tex->texture) == height)) { - /* Search if the engine is not already using this texture */ - for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; i++) { - if (tmp_tex->user[i] == engine) { - break; - } - - if (tmp_tex->user[i] == NULL) { - tmp_tex->user[i] = engine; - return tmp_tex->texture; - } - } - } - } - - tex = GPU_texture_create_2d("temp_from_pool", width, height, 1, format, NULL); - /* Doing filtering for depth does not make sense when not doing shadow mapping, - * and enabling texture filtering on integer texture make them unreadable. */ - bool do_filter = !GPU_texture_depth(tex) && !GPU_texture_integer(tex); - GPU_texture_filter_mode(tex, do_filter); - - ViewportTempTexture *tmp_tex = MEM_callocN(sizeof(ViewportTempTexture), "ViewportTempTexture"); - tmp_tex->texture = tex; - tmp_tex->user[0] = engine; - BLI_addtail(&viewport->tex_pool, tmp_tex); - - return tex; -} - -static void gpu_viewport_texture_pool_clear_users(GPUViewport *viewport) -{ - ViewportTempTexture *tmp_tex_next; - - for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex_next) { - tmp_tex_next = tmp_tex->next; - bool no_user = true; - for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; i++) { - if (tmp_tex->user[i] != NULL) { - tmp_tex->user[i] = NULL; - no_user = false; - } - } - - if (no_user) { - GPU_texture_free(tmp_tex->texture); - BLI_freelinkN(&viewport->tex_pool, tmp_tex); - } - } -} - -static void gpu_viewport_texture_pool_free(GPUViewport *viewport) -{ - LISTBASE_FOREACH (ViewportTempTexture *, tmp_tex, &viewport->tex_pool) { - GPU_texture_free(tmp_tex->texture); - } - - BLI_freelistN(&viewport->tex_pool); -} - -/* Takes an NULL terminated array of engine_handle. Returns true is data is still valid. */ -bool GPU_viewport_engines_data_validate(GPUViewport *viewport, void **engine_handle_array) -{ - for (int i = 0; i < MAX_ENABLE_ENGINE && engine_handle_array[i]; i++) { - if (viewport->engine_data[i].handle != engine_handle_array[i]) { - gpu_viewport_engines_data_free(viewport); - return false; - } - } - return true; -} - -void GPU_viewport_cache_release(GPUViewport *viewport) -{ - for (int i = 0; i < MAX_ENABLE_ENGINE && viewport->engine_data[i].handle; i++) { - ViewportEngineData *data = viewport->engine_data[i].data; - int psl_len; - DRW_engine_viewport_data_size_get(data->engine_type, NULL, NULL, &psl_len, NULL); - gpu_viewport_passes_free(data->psl, psl_len); - } -} - -static void gpu_viewport_default_fb_create(GPUViewport *viewport) -{ - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; int *size = viewport->size; - bool ok = true; - dtxl->color = GPU_texture_create_2d("dtxl_color", UNPACK2(size), 1, GPU_RGBA16F, NULL); - dtxl->color_overlay = GPU_texture_create_2d( - "dtxl_color_overlay", UNPACK2(size), 1, GPU_SRGB8_A8, NULL); + if (viewport->color_render_tx[0] == NULL) { + viewport->color_render_tx[0] = GPU_texture_create_2d( + "dtxl_color", UNPACK2(size), 1, GPU_RGBA16F, NULL); + viewport->color_overlay_tx[0] = GPU_texture_create_2d( + "dtxl_color_overlay", UNPACK2(size), 1, GPU_SRGB8_A8, NULL); + } - if (viewport->flag & GPU_VIEWPORT_STEREO) { - dtxl->color_stereo = GPU_texture_create_2d( + if ((viewport->flag & GPU_VIEWPORT_STEREO) != 0 && viewport->color_render_tx[1] == NULL) { + viewport->color_render_tx[1] = GPU_texture_create_2d( "dtxl_color_stereo", UNPACK2(size), 1, GPU_RGBA16F, NULL); - dtxl->color_overlay_stereo = GPU_texture_create_2d( + viewport->color_overlay_tx[1] = GPU_texture_create_2d( "dtxl_color_overlay_stereo", UNPACK2(size), 1, GPU_SRGB8_A8, NULL); } /* Can be shared with GPUOffscreen. */ - if (dtxl->depth == NULL) { - dtxl->depth = GPU_texture_create_2d( + if (viewport->depth_tx == NULL) { + viewport->depth_tx = GPU_texture_create_2d( "dtxl_depth", UNPACK2(size), 1, GPU_DEPTH24_STENCIL8, NULL); } - if (!dtxl->depth || !dtxl->color) { - ok = false; - goto cleanup; - } - - gpu_viewport_framebuffer_view_set(viewport, 0); - - ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL); - ok = ok && GPU_framebuffer_check_valid(dfbl->overlay_fb, NULL); - ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL); - ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL); - ok = ok && GPU_framebuffer_check_valid(dfbl->overlay_only_fb, NULL); -cleanup: - if (!ok) { + if (!viewport->depth_tx || !viewport->color_render_tx[0] || !viewport->color_overlay_tx[0]) { GPU_viewport_free(viewport); - DRW_opengl_context_disable(); - return; + } +} + +static void gpu_viewport_textures_free(GPUViewport *viewport) +{ + GPU_FRAMEBUFFER_FREE_SAFE(viewport->stereo_comp_fb); + GPU_FRAMEBUFFER_FREE_SAFE(viewport->overlay_fb); + + for (int i = 0; i < 2; i++) { + GPU_TEXTURE_FREE_SAFE(viewport->color_render_tx[i]); + GPU_TEXTURE_FREE_SAFE(viewport->color_overlay_tx[i]); } - GPU_framebuffer_restore(); + GPU_TEXTURE_FREE_SAFE(viewport->depth_tx); } void GPU_viewport_bind(GPUViewport *viewport, int view, const rcti *rect) { - DefaultFramebufferList *dfbl = viewport->fbl; - int fbl_len, txl_len; - int rect_size[2]; /* add one pixel because of scissor test */ rect_size[0] = BLI_rcti_size_x(rect) + 1; @@ -504,39 +185,18 @@ void GPU_viewport_bind(GPUViewport *viewport, int view, const rcti *rect) DRW_opengl_context_enable(); - if (dfbl->default_fb) { - if (!equals_v2v2_int(viewport->size, rect_size)) { - gpu_viewport_buffers_free((FramebufferList *)viewport->fbl, - default_fbl_len, - (TextureList *)viewport->txl, - NULL, - default_txl_len); - - for (int i = 0; i < MAX_ENABLE_ENGINE && viewport->engine_data[i].handle; i++) { - ViewportEngineData *data = viewport->engine_data[i].data; - DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, NULL, NULL); - gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, data->txl_stereo, txl_len); - } - - gpu_viewport_texture_pool_free(viewport); - viewport->active_view = -1; - } + if (!equals_v2v2_int(viewport->size, rect_size)) { + copy_v2_v2_int(viewport->size, rect_size); + gpu_viewport_textures_free(viewport); + gpu_viewport_textures_create(viewport); } - copy_v2_v2_int(viewport->size, rect_size); - - gpu_viewport_texture_pool_clear_users(viewport); - - if (!dfbl->default_fb) { - gpu_viewport_default_fb_create(viewport); - } - gpu_viewport_framebuffer_view_set(viewport, view); + viewport->active_view = view; } +/* Should be called from DRW after DRW_opengl_context_enable. */ void GPU_viewport_bind_from_offscreen(GPUViewport *viewport, struct GPUOffScreen *ofs) { - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; GPUTexture *color, *depth; GPUFrameBuffer *fb; viewport->size[0] = GPU_offscreen_width(ofs); @@ -544,14 +204,12 @@ void GPU_viewport_bind_from_offscreen(GPUViewport *viewport, struct GPUOffScreen GPU_offscreen_viewport_data_get(ofs, &fb, &color, &depth); + gpu_viewport_textures_free(viewport); + /* This is the only texture we can share. */ - dtxl->depth = depth; + viewport->depth_tx = depth; - gpu_viewport_texture_pool_clear_users(viewport); - - if (!dfbl->default_fb) { - gpu_viewport_default_fb_create(viewport); - } + gpu_viewport_textures_create(viewport); } void GPU_viewport_colorspace_set(GPUViewport *viewport, @@ -608,21 +266,17 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo * done from a single viewport. See `wm_stereo.c` */ return; } - gpu_viewport_framebuffer_view_set(viewport, 0); - DefaultTextureList *dtxl = viewport->txl; - DefaultFramebufferList *dfbl = viewport->fbl; - /* The composite framebuffer object needs to be created in the window context. */ - GPU_framebuffer_ensure_config(&dfbl->stereo_comp_fb, + GPU_framebuffer_ensure_config(&viewport->stereo_comp_fb, { GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay), - GPU_ATTACHMENT_TEXTURE(dtxl->color), + GPU_ATTACHMENT_TEXTURE(viewport->color_overlay_tx[0]), + GPU_ATTACHMENT_TEXTURE(viewport->color_render_tx[0]), }); GPUVertFormat *vert_format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - GPU_framebuffer_bind(dfbl->stereo_comp_fb); + GPU_framebuffer_bind(viewport->stereo_comp_fb); GPU_matrix_push(); GPU_matrix_push_projection(); GPU_matrix_identity_set(); @@ -650,8 +304,8 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo } immUniform1i("stereoDisplaySettings", settings); - GPU_texture_bind(dtxl->color_stereo, 0); - GPU_texture_bind(dtxl->color_overlay_stereo, 1); + GPU_texture_bind(viewport->color_render_tx[1], 0); + GPU_texture_bind(viewport->color_overlay_tx[1], 1); immBegin(GPU_PRIM_TRI_STRIP, 4); @@ -662,8 +316,8 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo immEnd(); - GPU_texture_unbind(dtxl->color_stereo); - GPU_texture_unbind(dtxl->color_overlay_stereo); + GPU_texture_unbind(viewport->color_render_tx[1]); + GPU_texture_unbind(viewport->color_overlay_tx[1]); immUnbindProgram(); GPU_matrix_pop_projection(); @@ -747,14 +401,14 @@ static void gpu_viewport_batch_free(GPUViewport *viewport) /** \} */ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport, + int view, const rctf *rect_pos, const rctf *rect_uv, bool display_colorspace, bool do_overlay_merge) { - DefaultTextureList *dtxl = viewport->txl; - GPUTexture *color = dtxl->color; - GPUTexture *color_overlay = dtxl->color_overlay; + GPUTexture *color = viewport->color_render_tx[view]; + GPUTexture *color_overlay = viewport->color_overlay_tx[view]; bool use_ocio = false; @@ -808,12 +462,9 @@ void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport, bool display_colorspace, bool do_overlay_merge) { - gpu_viewport_framebuffer_view_set(viewport, view); - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; - GPUTexture *color = dtxl->color; + GPUTexture *color = viewport->color_render_tx[view]; - if (dfbl->default_fb == NULL) { + if (color == NULL) { return; } @@ -854,7 +505,7 @@ void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport, } gpu_viewport_draw_colormanaged( - viewport, &pos_rect, &uv_rect, display_colorspace, do_overlay_merge); + viewport, view, &pos_rect, &uv_rect, display_colorspace, do_overlay_merge); } /** @@ -877,10 +528,7 @@ void GPU_viewport_unbind_from_offscreen(GPUViewport *viewport, bool display_colorspace, bool do_overlay_merge) { - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; - - if (dfbl->default_fb == NULL) { + if (viewport->color_render_tx == NULL) { return; } @@ -902,10 +550,10 @@ void GPU_viewport_unbind_from_offscreen(GPUViewport *viewport, }; gpu_viewport_draw_colormanaged( - viewport, &pos_rect, &uv_rect, display_colorspace, do_overlay_merge); + viewport, 0, &pos_rect, &uv_rect, display_colorspace, do_overlay_merge); /* This one is from the offscreen. Don't free it with the viewport. */ - dtxl->depth = NULL; + viewport->depth_tx = NULL; } void GPU_viewport_unbind(GPUViewport *UNUSED(viewport)) @@ -914,149 +562,53 @@ void GPU_viewport_unbind(GPUViewport *UNUSED(viewport)) DRW_opengl_context_disable(); } +int GPU_viewport_active_view_get(GPUViewport *viewport) +{ + return viewport->active_view; +} + +bool GPU_viewport_is_stereo_get(GPUViewport *viewport) +{ + return (viewport->flag & GPU_VIEWPORT_STEREO) != 0; +} + GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport, int view) { - DefaultFramebufferList *dfbl = viewport->fbl; - - if (dfbl->default_fb) { - DefaultTextureList *dtxl = viewport->txl; - if (viewport->active_view == view) { - return dtxl->color; - } - - return dtxl->color_stereo; - } - - return NULL; + return viewport->color_render_tx[view]; } -static void gpu_viewport_buffers_free( - FramebufferList *fbl, int fbl_len, TextureList *txl, TextureList *txl_stereo, int txl_len) +GPUTexture *GPU_viewport_overlay_texture(GPUViewport *viewport, int view) { - for (int i = 0; i < fbl_len; i++) { - GPUFrameBuffer *fb = fbl->framebuffers[i]; - if (fb) { - GPU_framebuffer_free(fb); - fbl->framebuffers[i] = NULL; - } - } - for (int i = 0; i < txl_len; i++) { - GPUTexture *tex = txl->textures[i]; - if (tex) { - GPU_texture_free(tex); - txl->textures[i] = NULL; - } - } - if (txl_stereo != NULL) { - for (int i = 0; i < txl_len; i++) { - GPUTexture *tex = txl_stereo->textures[i]; - if (tex) { - GPU_texture_free(tex); - txl_stereo->textures[i] = NULL; - } - } - } + return viewport->color_overlay_tx[view]; } -static void gpu_viewport_storage_free(StorageList *stl, int stl_len) +GPUTexture *GPU_viewport_depth_texture(GPUViewport *viewport) { - for (int i = 0; i < stl_len; i++) { - void *storage = stl->storage[i]; - if (storage) { - MEM_freeN(storage); - stl->storage[i] = NULL; - } - } + return viewport->depth_tx; } -static void gpu_viewport_passes_free(PassList *psl, int psl_len) +/* Overlay framebuffer for drawing outside of DRW module. */ +GPUFrameBuffer *GPU_viewport_framebuffer_overlay_get(GPUViewport *viewport) { - memset(psl->passes, 0, sizeof(*psl->passes) * psl_len); + GPU_framebuffer_ensure_config(&viewport->overlay_fb, + { + GPU_ATTACHMENT_TEXTURE(viewport->depth_tx), + GPU_ATTACHMENT_TEXTURE(viewport->color_overlay_tx[0]), + }); + return viewport->overlay_fb; } /* Must be executed inside Draw-manager OpenGL Context. */ void GPU_viewport_free(GPUViewport *viewport) { - gpu_viewport_engines_data_free(viewport); - - gpu_viewport_buffers_free((FramebufferList *)viewport->fbl, - default_fbl_len, - (TextureList *)viewport->txl, - NULL, - default_txl_len); - - gpu_viewport_texture_pool_free(viewport); - - MEM_freeN(viewport->fbl); - MEM_freeN(viewport->txl); - - if (viewport->vmempool.commands != NULL) { - BLI_memblock_destroy(viewport->vmempool.commands, NULL); - } - if (viewport->vmempool.commands_small != NULL) { - BLI_memblock_destroy(viewport->vmempool.commands_small, NULL); - } - if (viewport->vmempool.callbuffers != NULL) { - BLI_memblock_destroy(viewport->vmempool.callbuffers, NULL); - } - if (viewport->vmempool.obmats != NULL) { - BLI_memblock_destroy(viewport->vmempool.obmats, NULL); - } - if (viewport->vmempool.obinfos != NULL) { - BLI_memblock_destroy(viewport->vmempool.obinfos, NULL); - } - if (viewport->vmempool.cullstates != NULL) { - BLI_memblock_destroy(viewport->vmempool.cullstates, NULL); - } - if (viewport->vmempool.shgroups != NULL) { - BLI_memblock_destroy(viewport->vmempool.shgroups, NULL); - } - if (viewport->vmempool.uniforms != NULL) { - BLI_memblock_destroy(viewport->vmempool.uniforms, NULL); - } - if (viewport->vmempool.views != NULL) { - BLI_memblock_destroy(viewport->vmempool.views, NULL); - } - if (viewport->vmempool.passes != NULL) { - BLI_memblock_destroy(viewport->vmempool.passes, NULL); - } - if (viewport->vmempool.images != NULL) { - BLI_memblock_iter iter; - GPUTexture **tex; - BLI_memblock_iternew(viewport->vmempool.images, &iter); - while ((tex = BLI_memblock_iterstep(&iter))) { - GPU_texture_free(*tex); - } - BLI_memblock_destroy(viewport->vmempool.images, NULL); - } - if (viewport->vmempool.obattrs_ubo_pool != NULL) { - DRW_uniform_attrs_pool_free(viewport->vmempool.obattrs_ubo_pool); + if (viewport->draw_data) { + DRW_viewport_data_free(viewport->draw_data); } - for (int i = 0; i < viewport->vmempool.ubo_len; i++) { - GPU_uniformbuf_free(viewport->vmempool.matrices_ubo[i]); - GPU_uniformbuf_free(viewport->vmempool.obinfos_ubo[i]); - } - MEM_SAFE_FREE(viewport->vmempool.matrices_ubo); - MEM_SAFE_FREE(viewport->vmempool.obinfos_ubo); - - DRW_instance_data_list_free(viewport->idatalist); - MEM_freeN(viewport->idatalist); + gpu_viewport_textures_free(viewport); BKE_color_managed_view_settings_free(&viewport->view_settings); gpu_viewport_batch_free(viewport); MEM_freeN(viewport); } - -GPUFrameBuffer *GPU_viewport_framebuffer_default_get(GPUViewport *viewport) -{ - DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); - return fbl->default_fb; -} - -GPUFrameBuffer *GPU_viewport_framebuffer_overlay_get(GPUViewport *viewport) -{ - DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); - return fbl->overlay_fb; -}