Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/intern')
-rw-r--r--source/blender/draw/intern/DRW_render.h3
-rw-r--r--source/blender/draw/intern/draw_instance_data.c2
-rw-r--r--source/blender/draw/intern/draw_manager.c747
-rw-r--r--source/blender/draw/intern/draw_manager.h59
-rw-r--r--source/blender/draw/intern/draw_manager_data.c18
-rw-r--r--source/blender/draw/intern/draw_manager_profiling.c7
-rw-r--r--source/blender/draw/intern/draw_manager_text.h8
-rw-r--r--source/blender/draw/intern/draw_manager_texture.c3
-rw-r--r--source/blender/draw/intern/draw_texture_pool.cc140
-rw-r--r--source/blender/draw/intern/draw_texture_pool.h47
-rw-r--r--source/blender/draw/intern/draw_view_data.cc243
-rw-r--r--source/blender/draw/intern/draw_view_data.h139
12 files changed, 1012 insertions, 404 deletions
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();
+
+ drw_data->idatalist = DRW_instance_data_list_create();
- DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get(
- DST.viewport);
- DST.default_framebuffer = fbl->default_fb;
+ 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);
+ }
- DST.vmempool = GPU_viewport_mempool_get(DST.viewport);
+ for (int i = 0; i < 2; i++) {
+ drw_data->view_data[i] = DRW_view_data_create(&g_registered_engines.engines);
+ }
+ return drw_data;
+}
- 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();
+/* 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);
+ }
+}
+
+static void drw_viewport_data_reset(DRWData *drw_data)
+{
+ draw_texture_release(drw_data);
+
+ 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);
+}
- DST.resource_handle = 0;
- DST.pass_handle = 0;
+static DRWData *drw_viewport_data_ensure(GPUViewport *viewport)
+{
+ DRWData **vmempool_p = GPU_viewport_data_get(viewport);
+ DRWData *vmempool = *vmempool_p;
- draw_unit_state_create();
+ if (vmempool == NULL) {
+ *vmempool_p = vmempool = DRW_viewport_data_create();
+ }
+ return vmempool;
+}
- DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport);
- DRW_instance_data_list_reset(DST.idatalist);
+/**
+ * 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;
+ /* Create temporary DRWData. Freed in drw_manager_exit(). */
+ dst->vmempool = DRW_viewport_data_create();
+ }
- DST.inv_size[0] = 0;
- DST.inv_size[1] = 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;
- DST.default_framebuffer = NULL;
- DST.vmempool = NULL;
+ 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;
- DST.primary_view_ct = 0;
+ 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 = &region->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);
- /* 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);
- /* 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);
- /* 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,
+ };
- 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,
- };
+ /* 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. */
+ 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,
}
}
+ /* 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)};
- struct GPUViewport *viewport = GPU_viewport_create();
- GPU_viewport_size_set(viewport, viewport_size);
+ 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);
+
+ GPUFrameBuffer *depth_fb = NULL;
+ GPU_framebuffer_ensure_config(&depth_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(depth_tx),
+ GPU_ATTACHMENT_NONE,
+ });
- GPU_framebuffer_bind(fbl->depth_only_fb);
- GPU_framebuffer_clear_depth(fbl->depth_only_fb, 1.0f);
+ 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
@@ -98,6 +98,17 @@ struct Object;
/* ------------ 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
* > DRWUniform
@@ -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<void *, 16> users;
+ Vector<DRWTexturePoolHandle> 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/intern/draw_texture_pool.h b/source/blender/draw/intern/draw_texture_pool.h
new file mode 100644
index 00000000000..f0b8f775c75
--- /dev/null
+++ b/source/blender/draw/intern/draw_texture_pool.h
@@ -0,0 +1,47 @@
+/*
+ * 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
+ *
+ * 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
+
+DRWTexturePool *DRW_texture_pool_create(void);
+void DRW_texture_pool_free(DRWTexturePool *pool);
+
+GPUTexture *DRW_texture_pool_query(
+ DRWTexturePool *pool, int width, int height, eGPUTextureFormat format, void *user);
+void DRW_texture_pool_reset(DRWTexturePool *pool);
+
+#ifdef __cplusplus
+}
+#endif
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<ViewportEngineData> engines;
+ Vector<ViewportEngineData *> 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