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
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/draw/CMakeLists.txt1
-rw-r--r--source/blender/draw/DRW_engine.h2
-rw-r--r--source/blender/draw/engines/clay/clay_engine.c69
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_frag.glsl7
-rw-r--r--source/blender/draw/engines/eevee/eevee_bloom.c67
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c11
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c92
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c142
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c61
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c184
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c57
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c23
-rw-r--r--source/blender/draw/engines/eevee/eevee_mist.c18
-rw-r--r--source/blender/draw/engines/eevee/eevee_motion_blur.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c75
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h70
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c117
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c94
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c198
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c22
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c67
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl15
-rw-r--r--source/blender/draw/intern/DRW_render.h60
-rw-r--r--source/blender/draw/intern/draw_manager.c27
-rw-r--r--source/blender/draw/intern/draw_manager_framebuffer.c189
-rw-r--r--source/blender/draw/intern/draw_manager_texture.c27
-rw-r--r--source/blender/draw/modes/edit_mesh_mode.c39
-rw-r--r--source/blender/draw/modes/object_mode.c66
-rw-r--r--source/blender/gpu/GPU_framebuffer.h106
-rw-r--r--source/blender/gpu/GPU_texture.h5
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c841
-rw-r--r--source/blender/gpu/intern/gpu_lamp.c79
-rw-r--r--source/blender/gpu/intern/gpu_texture.c58
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c154
-rw-r--r--source/blender/windowmanager/intern/wm_window.c8
35 files changed, 1387 insertions, 1666 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index f7d3a37246e..eb66e9c20ea 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -66,7 +66,6 @@ set(SRC
intern/draw_manager.c
intern/draw_manager_data.c
intern/draw_manager_exec.c
- intern/draw_manager_framebuffer.c
intern/draw_manager_shader.c
intern/draw_manager_text.c
intern/draw_manager_texture.c
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index cc4c0ed10e8..e42b5a49d64 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -58,6 +58,8 @@ struct WorkSpace;
/* Buffer and textures used by the viewport by default */
typedef struct DefaultFramebufferList {
struct GPUFrameBuffer *default_fb;
+ struct GPUFrameBuffer *color_only_fb;
+ struct GPUFrameBuffer *depth_only_fb;
struct GPUFrameBuffer *multisample_fb;
} DefaultFramebufferList;
diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c
index 382551b16e4..86ff52045db 100644
--- a/source/blender/draw/engines/clay/clay_engine.c
+++ b/source/blender/draw/engines/clay/clay_engine.c
@@ -148,14 +148,11 @@ typedef struct CLAY_PassList {
struct DRWPass *hair_pass;
} CLAY_PassList;
-typedef struct CLAY_TextureList {
- struct GPUTexture *color_copy; /* only used if fxaa */
-} CLAY_TextureList;
typedef struct CLAY_Data {
void *engine_type;
CLAY_FramebufferList *fbl;
- CLAY_TextureList *txl;
+ DRWViewportEmptyList *txl;
CLAY_PassList *psl;
CLAY_StorageList *stl;
} CLAY_Data;
@@ -201,6 +198,7 @@ typedef struct CLAY_PrivateData {
struct GPUTexture *depth_tx; /* ref only, not alloced */
struct GPUTexture *normal_tx; /* ref only, not alloced */
struct GPUTexture *id_tx; /* ref only, not alloced */
+ struct GPUTexture *color_copy; /* ref only, not alloced */
bool enable_deferred_path;
/* Ssao */
float winmat[4][4];
@@ -351,9 +349,9 @@ static struct GPUTexture *create_jitter_texture(int num_samples)
static void clay_engine_init(void *vedata)
{
CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
- CLAY_TextureList *txl = ((CLAY_Data *)vedata)->txl;
CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
/* Create Texture Array */
if (!e_data.matcap_array) {
@@ -463,19 +461,29 @@ static void clay_engine_init(void *vedata)
}
}
- if (DRW_state_is_fbo()) {
+ /* FBO setup */
+ {
const float *viewport_size = DRW_viewport_size_get();
- DRWFboTexture texs[2] = {{&g_data->normal_tx, DRW_TEX_RG_8, DRW_TEX_TEMP},
- {&g_data->id_tx, DRW_TEX_R_16I, DRW_TEX_TEMP}};
- DRW_framebuffer_init(&fbl->prepass_fb, &draw_engine_clay_type,
- (int)viewport_size[0], (int)viewport_size[1],
- texs, 2);
+ const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
+
+ g_data->normal_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_RG_8, &draw_engine_clay_type);
+ g_data->id_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_R_16I, &draw_engine_clay_type);
+
+ GPU_framebuffer_ensure_config(&fbl->prepass_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(g_data->normal_tx),
+ GPU_ATTACHMENT_TEXTURE(g_data->id_tx)
+ });
/* For FXAA */
- DRWFboTexture tex = {&txl->color_copy, DRW_TEX_RGBA_8, DRW_TEX_FILTER};
- DRW_framebuffer_init(&fbl->antialias_fb, &draw_engine_clay_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex, 1);
+ /* TODO(fclem): OPTI: we could merge normal_tx and id_tx into a DRW_TEX_RGBA_8
+ * and reuse it for the fxaa target. */
+ g_data->color_copy = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_RGBA_8, &draw_engine_clay_type);
+
+ GPU_framebuffer_ensure_config(&fbl->antialias_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(g_data->color_copy)
+ });
}
/* SSAO setup */
@@ -809,7 +817,6 @@ static void clay_cache_init(void *vedata)
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
- CLAY_TextureList *txl = ((CLAY_Data *)vedata)->txl;
/* Disable AO unless a material needs it. */
stl->g_data->enable_deferred_path = false;
@@ -854,7 +861,7 @@ static void clay_cache_init(void *vedata)
psl->copy_ps = DRW_pass_create("Copy", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.copy_sh, psl->copy_ps);
- DRW_shgroup_uniform_buffer(grp, "colortex", &txl->color_copy);
+ DRW_shgroup_uniform_buffer(grp, "colortex", &stl->g_data->color_copy);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
}
@@ -956,37 +963,25 @@ static void clay_draw_scene(void *vedata)
DRW_draw_pass(psl->hair_pass);
if (stl->g_data->enable_deferred_path) {
- if (DRW_state_is_fbo()) {
- DRW_framebuffer_texture_detach(dtxl->depth);
- DRW_framebuffer_texture_attach(fbl->prepass_fb, dtxl->depth, 0, 0);
- DRW_framebuffer_texture_attach(fbl->prepass_fb, stl->g_data->normal_tx, 0, 0);
- DRW_framebuffer_texture_attach(fbl->prepass_fb, stl->g_data->id_tx, 1, 0);
- DRW_framebuffer_bind(fbl->prepass_fb);
- /* We need to clear the id texture unfortunately. */
- DRW_framebuffer_clear(true, false, false, (float[4]){0.0f, 0.0f, 0.0f, 0.0f}, 0.0f);
- }
+ GPU_framebuffer_bind(fbl->prepass_fb);
+ /* We need to clear the id texture unfortunately. */
+ const float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ GPU_framebuffer_clear_color(fbl->prepass_fb, clear_col);
DRW_draw_pass(psl->clay_pre_cull_ps);
DRW_draw_pass(psl->clay_flat_pre_cull_ps);
DRW_draw_pass(psl->clay_pre_ps);
DRW_draw_pass(psl->clay_flat_pre_ps);
- if (DRW_state_is_fbo()) {
- DRW_framebuffer_texture_detach(dtxl->depth);
- DRW_framebuffer_bind(dfbl->default_fb);
-
- DRW_draw_pass(psl->clay_deferred_ps);
-
- DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
- DRW_framebuffer_bind(dfbl->default_fb);
- }
+ GPU_framebuffer_bind(dfbl->color_only_fb);
+ DRW_draw_pass(psl->clay_deferred_ps);
}
if (true) { /* Always on for now. We might want a parameter for this. */
- DRW_framebuffer_bind(fbl->antialias_fb);
+ GPU_framebuffer_bind(fbl->antialias_fb);
DRW_draw_pass(psl->fxaa_ps);
- DRW_framebuffer_bind(dfbl->default_fb);
+ GPU_framebuffer_bind(dfbl->color_only_fb);
DRW_draw_pass(psl->copy_ps);
}
}
diff --git a/source/blender/draw/engines/clay/shaders/clay_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_frag.glsl
index f2c6cd5f780..1939e4b735d 100644
--- a/source/blender/draw/engines/clay/shaders/clay_frag.glsl
+++ b/source/blender/draw/engines/clay/shaders/clay_frag.glsl
@@ -225,14 +225,15 @@ void main()
vec2 screenco = vec2(gl_FragCoord.xy) * invscreenres;
#ifdef DEFERRED_SHADING
- mat_id = texture(idtex, screenco).r;
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+ mat_id = texelFetch(idtex, texel, 0).r;
/* early out (manual stencil test) */
if (mat_id == 0)
discard;
- float depth = texture(depthtex, screenco).r;
- vec3 N = normal_decode(texture(normaltex, screenco).rg);
+ float depth = texelFetch(depthtex, texel, 0).r;
+ vec3 N = normal_decode(texelFetch(normaltex, texel, 0).rg);
/* see the prepass for explanations. */
if (mat_id < 0) {
N = -N;
diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c
index c62f35a70e7..29f6ca3988c 100644
--- a/source/blender/draw/engines/eevee/eevee_bloom.c
+++ b/source/blender/draw/engines/eevee/eevee_bloom.c
@@ -84,7 +84,6 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -112,10 +111,13 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
effects->blit_texel_size[0] = 1.0f / (float)blitsize[0];
effects->blit_texel_size[1] = 1.0f / (float)blitsize[1];
- DRWFboTexture tex_blit = {&txl->bloom_blit, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER};
- DRW_framebuffer_init(&fbl->bloom_blit_fb, &draw_engine_eevee_type,
- (int)blitsize[0], (int)blitsize[1],
- &tex_blit, 1);
+ effects->bloom_blit = DRW_texture_pool_query_2D(blitsize[0], blitsize[1], DRW_TEX_RGB_11_11_10,
+ &draw_engine_eevee_type);
+
+ GPU_framebuffer_ensure_config(&fbl->bloom_blit_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->bloom_blit)
+ });
/* Parameters */
float threshold = BKE_collection_engine_property_value_get_float(props, "bloom_threshold");
@@ -151,10 +153,12 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
effects->downsamp_texel_size[i][0] = 1.0f / (float)texsize[0];
effects->downsamp_texel_size[i][1] = 1.0f / (float)texsize[1];
- DRWFboTexture tex_bloom = {&txl->bloom_downsample[i], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER};
- DRW_framebuffer_init(&fbl->bloom_down_fb[i], &draw_engine_eevee_type,
- (int)texsize[0], (int)texsize[1],
- &tex_bloom, 1);
+ effects->bloom_downsample[i] = DRW_texture_pool_query_2D(texsize[0], texsize[1], DRW_TEX_RGB_11_11_10,
+ &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->bloom_down_fb[i], {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->bloom_downsample[i])
+ });
}
/* Upsample buffers */
@@ -165,30 +169,23 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
texsize[0] = MAX2(texsize[0], 2);
texsize[1] = MAX2(texsize[1], 2);
- DRWFboTexture tex_bloom = {&txl->bloom_upsample[i], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER};
- DRW_framebuffer_init(&fbl->bloom_accum_fb[i], &draw_engine_eevee_type,
- (int)texsize[0], (int)texsize[1],
- &tex_bloom, 1);
+ effects->bloom_upsample[i] = DRW_texture_pool_query_2D(texsize[0], texsize[1], DRW_TEX_RGB_11_11_10,
+ &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->bloom_accum_fb[i], {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->bloom_upsample[i])
+ });
}
return EFFECT_BLOOM | EFFECT_POST_BUFFER;
}
/* Cleanup to release memory */
- DRW_TEXTURE_FREE_SAFE(txl->bloom_blit);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->bloom_blit_fb);
-
- /* Bloom and dof share this buffer. This
- * tells dof to reconfigure it's framebuffer. */
- if (txl->bloom_downsample[0] != NULL) {
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->dof_down_fb);
- }
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->bloom_blit_fb);
for (int i = 0; i < MAX_BLOOM_STEP - 1; ++i) {
- DRW_TEXTURE_FREE_SAFE(txl->bloom_downsample[i]);
- DRW_TEXTURE_FREE_SAFE(txl->bloom_upsample[i]);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->bloom_down_fb[i]);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->bloom_accum_fb[i]);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->bloom_down_fb[i]);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->bloom_accum_fb[i]);
}
return 0;
@@ -280,39 +277,39 @@ void EEVEE_bloom_draw(EEVEE_Data *vedata)
copy_v2_v2(effects->unf_source_texel_size, effects->source_texel_size);
effects->unf_source_buffer = effects->source_buffer;
- DRW_framebuffer_bind(fbl->bloom_blit_fb);
+ GPU_framebuffer_bind(fbl->bloom_blit_fb);
DRW_draw_pass(psl->bloom_blit);
/* Downsample */
copy_v2_v2(effects->unf_source_texel_size, effects->blit_texel_size);
- effects->unf_source_buffer = txl->bloom_blit;
+ effects->unf_source_buffer = effects->bloom_blit;
- DRW_framebuffer_bind(fbl->bloom_down_fb[0]);
+ GPU_framebuffer_bind(fbl->bloom_down_fb[0]);
DRW_draw_pass(psl->bloom_downsample_first);
- last = txl->bloom_downsample[0];
+ last = effects->bloom_downsample[0];
for (int i = 1; i < effects->bloom_iteration_ct; ++i) {
copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i - 1]);
effects->unf_source_buffer = last;
- DRW_framebuffer_bind(fbl->bloom_down_fb[i]);
+ GPU_framebuffer_bind(fbl->bloom_down_fb[i]);
DRW_draw_pass(psl->bloom_downsample);
/* Used in next loop */
- last = txl->bloom_downsample[i];
+ last = effects->bloom_downsample[i];
}
/* Upsample and accumulate */
for (int i = effects->bloom_iteration_ct - 2; i >= 0; --i) {
copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i]);
- effects->unf_source_buffer = txl->bloom_downsample[i];
+ effects->unf_source_buffer = effects->bloom_downsample[i];
effects->unf_base_buffer = last;
- DRW_framebuffer_bind(fbl->bloom_accum_fb[i]);
+ GPU_framebuffer_bind(fbl->bloom_accum_fb[i]);
DRW_draw_pass(psl->bloom_upsample);
- last = txl->bloom_upsample[i];
+ last = effects->bloom_upsample[i];
}
/* Resolve */
@@ -320,7 +317,7 @@ void EEVEE_bloom_draw(EEVEE_Data *vedata)
effects->unf_source_buffer = last;
effects->unf_base_buffer = effects->source_buffer;
- DRW_framebuffer_bind(effects->target_buffer);
+ GPU_framebuffer_bind(effects->target_buffer);
DRW_draw_pass(psl->bloom_resolve);
SWAP_BUFFERS();
}
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index 0b6ab905e32..5adcf9e9ffb 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -38,8 +38,9 @@ static void eevee_view_layer_data_free(void *storage)
DRW_UBO_FREE_SAFE(sldata->light_ubo);
DRW_UBO_FREE_SAFE(sldata->shadow_ubo);
DRW_UBO_FREE_SAFE(sldata->shadow_render_ubo);
- DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_target_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_store_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cube_target_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cascade_target_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_store_fb);
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target);
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_blur);
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target);
@@ -57,8 +58,10 @@ static void eevee_view_layer_data_free(void *storage)
DRW_UBO_FREE_SAFE(sldata->planar_ubo);
DRW_UBO_FREE_SAFE(sldata->common_ubo);
DRW_UBO_FREE_SAFE(sldata->clip_ubo);
- DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_filter_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(sldata->probe_filter_fb);
+ for (int i = 0; i < 6; ++i) {
+ GPU_FRAMEBUFFER_FREE_SAFE(sldata->probe_face_fb[i]);
+ }
DRW_TEXTURE_FREE_SAFE(sldata->probe_rt);
DRW_TEXTURE_FREE_SAFE(sldata->probe_depth_rt);
DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
index dcd45e27337..c137aa8da24 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -79,7 +79,6 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
{
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -104,39 +103,36 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
int buffer_size[2] = {(int)viewport_size[0] / 2, (int)viewport_size[1] / 2};
- /* Reuse buffer from Bloom if available */
- /* WATCH IT : must have the same size */
- struct GPUTexture **dof_down_near;
-
- if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
- dof_down_near = &txl->bloom_downsample[0];
- }
- else {
- dof_down_near = &txl->dof_down_near;
- }
+ effects->dof_down_near = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], DRW_TEX_RGB_11_11_10,
+ &draw_engine_eevee_type);
+ effects->dof_down_far = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], DRW_TEX_RGB_11_11_10,
+ &draw_engine_eevee_type);
+ effects->dof_coc = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], DRW_TEX_RG_16,
+ &draw_engine_eevee_type);
- /* Setup buffers */
- DRWFboTexture tex_down[3] = {
- {dof_down_near, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}, /* filter to not interfeer with bloom */
- {&txl->dof_down_far, DRW_TEX_RGB_11_11_10, 0},
- {&txl->dof_coc, DRW_TEX_RG_16, 0},
- };
- DRW_framebuffer_init(
- &fbl->dof_down_fb, &draw_engine_eevee_type,
- buffer_size[0], buffer_size[1], tex_down, 3);
+ GPU_framebuffer_ensure_config(&fbl->dof_down_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->dof_down_near),
+ GPU_ATTACHMENT_TEXTURE(effects->dof_down_far),
+ GPU_ATTACHMENT_TEXTURE(effects->dof_coc)
+ });
/* Go full 32bits for rendering and reduce the color artifacts. */
DRWTextureFormat fb_format = DRW_state_is_image_render() ? DRW_TEX_RGBA_32 : DRW_TEX_RGBA_16;
- DRWFboTexture tex_scatter_far = {&txl->dof_far_blur, fb_format, DRW_TEX_FILTER};
- DRW_framebuffer_init(
- &fbl->dof_scatter_far_fb, &draw_engine_eevee_type,
- buffer_size[0], buffer_size[1], &tex_scatter_far, 1);
+ effects->dof_far_blur = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], fb_format,
+ &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->dof_scatter_far_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->dof_far_blur),
+ });
- DRWFboTexture tex_scatter_near = {&txl->dof_near_blur, fb_format, DRW_TEX_FILTER};
- DRW_framebuffer_init(
- &fbl->dof_scatter_near_fb, &draw_engine_eevee_type,
- buffer_size[0], buffer_size[1], &tex_scatter_near, 1);
+ effects->dof_near_blur = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], fb_format,
+ &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->dof_scatter_near_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->dof_near_blur),
+ });
/* Parameters */
/* TODO UI Options */
@@ -178,14 +174,9 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
}
/* Cleanup to release memory */
- DRW_TEXTURE_FREE_SAFE(txl->dof_down_near);
- DRW_TEXTURE_FREE_SAFE(txl->dof_down_far);
- DRW_TEXTURE_FREE_SAFE(txl->dof_coc);
- DRW_TEXTURE_FREE_SAFE(txl->dof_far_blur);
- DRW_TEXTURE_FREE_SAFE(txl->dof_near_blur);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->dof_down_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->dof_scatter_far_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->dof_scatter_near_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->dof_down_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->dof_scatter_far_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->dof_scatter_near_fb);
return 0;
}
@@ -194,7 +185,6 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
@@ -229,7 +219,7 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_
grp = DRW_shgroup_empty_tri_batch_create(e_data.dof_scatter_sh, psl->dof_scatter, sprite_ct);
DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->unf_source_buffer);
- DRW_shgroup_uniform_buffer(grp, "cocBuffer", &txl->dof_coc);
+ DRW_shgroup_uniform_buffer(grp, "cocBuffer", &effects->dof_coc);
DRW_shgroup_uniform_vec2(grp, "layerSelection", effects->dof_layer_select, 1);
DRW_shgroup_uniform_vec4(grp, "bokehParams", effects->dof_bokeh, 1);
@@ -237,8 +227,8 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_
grp = DRW_shgroup_create(e_data.dof_resolve_sh, psl->dof_resolve);
DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->source_buffer);
- DRW_shgroup_uniform_buffer(grp, "nearBuffer", &txl->dof_near_blur);
- DRW_shgroup_uniform_buffer(grp, "farBuffer", &txl->dof_far_blur);
+ DRW_shgroup_uniform_buffer(grp, "nearBuffer", &effects->dof_near_blur);
+ DRW_shgroup_uniform_buffer(grp, "farBuffer", &effects->dof_far_blur);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1);
DRW_shgroup_uniform_vec3(grp, "dofParams", effects->dof_params, 1);
@@ -259,31 +249,25 @@ void EEVEE_depth_of_field_draw(EEVEE_Data *vedata)
float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
/* Downsample */
- DRW_framebuffer_bind(fbl->dof_down_fb);
+ GPU_framebuffer_bind(fbl->dof_down_fb);
DRW_draw_pass(psl->dof_down);
/* Scatter Far */
- effects->unf_source_buffer = txl->dof_down_far;
+ effects->unf_source_buffer = effects->dof_down_far;
copy_v2_fl2(effects->dof_layer_select, 0.0f, 1.0f);
- DRW_framebuffer_bind(fbl->dof_scatter_far_fb);
- DRW_framebuffer_clear(true, false, false, clear_col, 0.0f);
+ GPU_framebuffer_bind(fbl->dof_scatter_far_fb);
+ GPU_framebuffer_clear_color(fbl->dof_scatter_far_fb, clear_col);
DRW_draw_pass(psl->dof_scatter);
/* Scatter Near */
- if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
- /* Reuse bloom half res buffer */
- effects->unf_source_buffer = txl->bloom_downsample[0];
- }
- else {
- effects->unf_source_buffer = txl->dof_down_near;
- }
+ effects->unf_source_buffer = effects->dof_down_near;
copy_v2_fl2(effects->dof_layer_select, 1.0f, 0.0f);
- DRW_framebuffer_bind(fbl->dof_scatter_near_fb);
- DRW_framebuffer_clear(true, false, false, clear_col, 0.0f);
+ GPU_framebuffer_bind(fbl->dof_scatter_near_fb);
+ GPU_framebuffer_clear_color(fbl->dof_scatter_near_fb, clear_col);
DRW_draw_pass(psl->dof_scatter);
/* Resolve */
- DRW_framebuffer_bind(effects->target_buffer);
+ GPU_framebuffer_bind(effects->target_buffer);
DRW_draw_pass(psl->dof_resolve);
SWAP_BUFFERS();
}
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 1030fe1ce3a..d7fa9e76370 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -105,6 +105,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
@@ -141,31 +142,45 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object
* Ping Pong buffer
*/
if ((effects->enabled_effects & EFFECT_POST_BUFFER) != 0) {
- DRWFboTexture tex = {&txl->color_post, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
- DRW_framebuffer_init(&fbl->effect_fb, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex, 1);
+ DRW_texture_ensure_fullscreen_2D(&txl->color_post, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP);
+
+ GPU_framebuffer_ensure_config(&fbl->effect_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(txl->color_post),
+ });
+
+ GPU_framebuffer_ensure_config(&fbl->effect_color_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->color_post),
+ });
}
else {
/* Cleanup to release memory */
DRW_TEXTURE_FREE_SAFE(txl->color_post);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->effect_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->effect_fb);
}
/**
* MinMax Pyramid
*/
- DRWFboTexture texmax = {&txl->maxzbuffer, DRW_TEX_DEPTH_24, DRW_TEX_MIPMAP};
+ int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
+ size[0] = max_ii(size[0] / 2, 1);
+ size[1] = max_ii(size[1] / 2, 1);
if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
/* Intel gpu seems to have problem rendering to only depth format */
- texmax.format = DRW_TEX_R_32;
+ DRW_texture_ensure_2D(&txl->maxzbuffer, size[0], size[1], DRW_TEX_R_32, DRW_TEX_MIPMAP);
+ GPU_framebuffer_ensure_config(&fbl->downsample_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->maxzbuffer)
+ });
+ }
+ else {
+ DRW_texture_ensure_2D(&txl->maxzbuffer, size[0], size[1], DRW_TEX_DEPTH_24, DRW_TEX_MIPMAP);
+ GPU_framebuffer_ensure_config(&fbl->downsample_fb, {
+ GPU_ATTACHMENT_TEXTURE(txl->maxzbuffer)
+ });
}
-
- DRW_framebuffer_init(&fbl->downsample_fb, &draw_engine_eevee_type,
- max_ii((int)viewport_size[0] / 2, 1), max_ii((int)viewport_size[1] / 2, 1),
- &texmax, 1);
-
/**
* Compute Mipmap texel alignement.
@@ -185,34 +200,37 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object
* Normal buffer for deferred passes.
*/
if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
- if (txl->ssr_normal_input == NULL) {
- DRWTextureFormat nor_format = DRW_TEX_RG_16;
- txl->ssr_normal_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], nor_format, 0, NULL);
- }
+ int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]};
+
+ effects->ssr_normal_input = DRW_texture_pool_query_2D(size_fs[0], size_fs[1], DRW_TEX_RG_16,
+ &draw_engine_eevee_type);
- /* Reattach textures to the right buffer (because we are alternating between buffers) */
- /* TODO multiple FBO per texture!!!! */
- DRW_framebuffer_texture_detach(txl->ssr_normal_input);
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0);
+ GPU_framebuffer_texture_attach(fbl->main_fb, effects->ssr_normal_input, 1, 0);
}
else {
- /* Cleanup to release memory */
- DRW_TEXTURE_FREE_SAFE(txl->ssr_normal_input);
+ effects->ssr_normal_input = NULL;
}
/**
* Setup double buffer so we can access last frame as it was before post processes.
*/
if ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0) {
- DRWFboTexture tex_double_buffer = {&txl->color_double_buffer, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
- DRW_framebuffer_init(&fbl->double_buffer, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex_double_buffer, 1);
+ DRW_texture_ensure_fullscreen_2D(&txl->color_double_buffer, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP);
+
+ GPU_framebuffer_ensure_config(&fbl->double_buffer_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(txl->color_double_buffer)
+ });
+
+ GPU_framebuffer_ensure_config(&fbl->double_buffer_color_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->color_double_buffer)
+ });
}
else {
/* Cleanup to release memory */
DRW_TEXTURE_FREE_SAFE(txl->color_double_buffer);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer_fb);
}
}
@@ -253,53 +271,24 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* Perform min/max downsample */
DRWShadingGroup *grp;
-#if 0 /* Not used for now */
- psl->minz_downlevel_ps = DRW_pass_create("HiZ Min Down Level", downsample_write | DRW_STATE_DEPTH_ALWAYS);
- grp = DRW_shgroup_create(e_data.minz_downlevel_sh, psl->minz_downlevel_ps);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &stl->g_data->minzbuffer);
- DRW_shgroup_call_add(grp, quad, NULL);
-#endif
-
psl->maxz_downlevel_ps = DRW_pass_create("HiZ Max Down Level", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_downlevel_sh, psl->maxz_downlevel_ps);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &txl->maxzbuffer);
DRW_shgroup_call_add(grp, quad, NULL);
/* Copy depth buffer to halfres top level of HiZ */
-#if 0 /* Not used for now */
- psl->minz_downdepth_ps = DRW_pass_create("HiZ Min Copy Depth Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
- grp = DRW_shgroup_create(e_data.minz_downdepth_sh, psl->minz_downdepth_ps);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
- DRW_shgroup_call_add(grp, quad, NULL);
-#endif
psl->maxz_downdepth_ps = DRW_pass_create("HiZ Max Copy Depth Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_downdepth_sh, psl->maxz_downdepth_ps);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_call_add(grp, quad, NULL);
-#if 0 /* Not used for now */
- psl->minz_downdepth_layer_ps = DRW_pass_create("HiZ Min Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
- grp = DRW_shgroup_create(e_data.minz_downdepth_layer_sh, psl->minz_downdepth_layer_ps);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
- DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1);
- DRW_shgroup_call_add(grp, quad, NULL);
-#endif
-
psl->maxz_downdepth_layer_ps = DRW_pass_create("HiZ Max Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_downdepth_layer_sh, psl->maxz_downdepth_layer_ps);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1);
DRW_shgroup_call_add(grp, quad, NULL);
- /* Copy depth buffer to halfres top level of HiZ */
-#if 0 /* Not used for now */
- psl->minz_copydepth_ps = DRW_pass_create("HiZ Min Copy Depth Fullres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
- grp = DRW_shgroup_create(e_data.minz_copydepth_sh, psl->minz_copydepth_ps);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
- DRW_shgroup_call_add(grp, quad, NULL);
-#endif
-
psl->maxz_copydepth_ps = DRW_pass_create("HiZ Max Copy Depth Fullres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_copydepth_sh, psl->maxz_copydepth_ps);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
@@ -346,64 +335,67 @@ void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src, int l
#if 0 /* Not required for now */
DRW_stats_group_start("Min buffer");
/* Copy depth buffer to min texture top level */
- DRW_framebuffer_texture_attach(fbl->downsample_fb, stl->g_data->minzbuffer, 0, 0);
- DRW_framebuffer_bind(fbl->downsample_fb);
+ GPU_framebuffer_texture_attach(fbl->downsample_fb, stl->g_data->minzbuffer, 0, 0);
+ GPU_framebuffer_bind(fbl->downsample_fb);
if (layer >= 0) {
DRW_draw_pass(psl->minz_downdepth_layer_ps);
}
else {
DRW_draw_pass(psl->minz_downdepth_ps);
}
- DRW_framebuffer_texture_detach(stl->g_data->minzbuffer);
+ GPU_framebuffer_texture_detach(stl->g_data->minzbuffer);
/* Create lower levels */
- DRW_framebuffer_recursive_downsample(fbl->downsample_fb, stl->g_data->minzbuffer, 8, &min_downsample_cb, vedata);
+ GPU_framebuffer_recursive_downsample(fbl->downsample_fb, stl->g_data->minzbuffer, 8, &min_downsample_cb, vedata);
DRW_stats_group_end();
#endif
DRW_stats_group_start("Max buffer");
/* Copy depth buffer to max texture top level */
- DRW_framebuffer_texture_attach(fbl->downsample_fb, txl->maxzbuffer, 0, 0);
- DRW_framebuffer_bind(fbl->downsample_fb);
+ GPU_framebuffer_texture_attach(fbl->downsample_fb, txl->maxzbuffer, 0, 0);
+ GPU_framebuffer_bind(fbl->downsample_fb);
if (layer >= 0) {
DRW_draw_pass(psl->maxz_downdepth_layer_ps);
}
else {
DRW_draw_pass(psl->maxz_downdepth_ps);
}
- DRW_framebuffer_texture_detach(txl->maxzbuffer);
/* Create lower levels */
- DRW_framebuffer_recursive_downsample(fbl->downsample_fb, txl->maxzbuffer, 8, &max_downsample_cb, vedata);
+ GPU_framebuffer_recursive_downsample(fbl->downsample_fb, 8, &max_downsample_cb, vedata);
DRW_stats_group_end();
/* Restore */
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
}
/**
* Simple downsampling algorithm. Reconstruct mip chain up to mip level.
**/
-void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, GPUTexture *texture_src, int level)
+void EEVEE_downsample_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int level)
{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
e_data.color_src = texture_src;
- DRW_stats_group_start("Downsample buffer");
/* Create lower levels */
- DRW_framebuffer_recursive_downsample(fb_src, texture_src, level, &simple_downsample_cb, vedata);
+ DRW_stats_group_start("Downsample buffer");
+ GPU_framebuffer_texture_attach(fbl->downsample_fb, texture_src, 0, 0);
+ GPU_framebuffer_recursive_downsample(fbl->downsample_fb, level, &simple_downsample_cb, vedata);
DRW_stats_group_end();
}
/**
* Simple downsampling algorithm for cubemap. Reconstruct mip chain up to mip level.
**/
-void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, GPUTexture *texture_src, int level)
+void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int level)
{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
e_data.color_src = texture_src;
- DRW_stats_group_start("Downsample Cube buffer");
/* Create lower levels */
- DRW_framebuffer_recursive_downsample(fb_src, texture_src, level, &simple_downsample_cube_cb, vedata);
+ DRW_stats_group_start("Downsample Cube buffer");
+ GPU_framebuffer_texture_attach(fbl->downsample_fb, texture_src, 0, 0);
+ GPU_framebuffer_recursive_downsample(fbl->downsample_fb, level, &simple_downsample_cube_cb, vedata);
DRW_stats_group_end();
}
@@ -413,21 +405,17 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
/* only once per frame after the first post process */
effects->swap_double_buffer = ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0);
/* Init pointers */
effects->source_buffer = txl->color; /* latest updated texture */
- effects->target_buffer = fbl->effect_fb; /* next target to render to */
+ effects->target_buffer = fbl->effect_color_fb; /* next target to render to */
/* Temporal Anti-Aliasing MUST come first */
EEVEE_temporal_sampling_draw(vedata);
- /* Detach depth for effects to use it */
- DRW_framebuffer_texture_detach(dtxl->depth);
-
/* Post process stack (order matters) */
EEVEE_motion_blur_draw(vedata);
EEVEE_depth_of_field_draw(vedata);
@@ -435,7 +423,7 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
/* Save the final texture and framebuffer for final transformation or read. */
effects->final_tx = effects->source_buffer;
- effects->final_fb = (effects->target_buffer != fbl->main) ? fbl->main : fbl->effect_fb;
+ effects->final_fb = (effects->target_buffer != fbl->main_fb) ? fbl->main_fb : fbl->effect_fb;
/* If no post processes is enabled, buffers are still not swapped, do it now. */
SWAP_DOUBLE_BUFFERS();
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index 6cfecd0a226..276f23c7cf7 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -55,6 +55,7 @@ static void eevee_engine_init(void *ved)
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
@@ -68,12 +69,22 @@ static void eevee_engine_init(void *ved)
stl->g_data->background_alpha = DRW_state_draw_background() ? 1.0f : 0.0f;
stl->g_data->valid_double_buffer = (txl->color_double_buffer != NULL);
- DRWFboTexture tex = {&txl->color, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
+ /* Main Buffer */
+ DRW_texture_ensure_fullscreen_2D(&txl->color, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP);
+
+ GPU_framebuffer_ensure_config(&fbl->main_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(txl->color),
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE
+ });
- const float *viewport_size = DRW_viewport_size_get();
- DRW_framebuffer_init(&fbl->main, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex, 1);
+ GPU_framebuffer_ensure_config(&fbl->main_color_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->color)
+ });
if (sldata->common_ubo == NULL) {
sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), &sldata->common_data);
@@ -170,6 +181,7 @@ static void eevee_draw_background(void *vedata)
EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
+ EEVEE_EffectsInfo *effects = stl->effects;
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
/* Default framebuffer and texture */
@@ -185,6 +197,9 @@ static void eevee_draw_background(void *vedata)
(stl->effects->enabled_effects & (EFFECT_VOLUMETRIC | EFFECT_SSR)) != 0) ? 4 : 1;
while (loop_ct--) {
+ float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float clear_depth = 1.0f;
+ unsigned int clear_stencil = 0xFF;
unsigned int primes[3] = {2, 3, 7};
double offset[3] = {0.0, 0.0, 0.0};
double r[3];
@@ -228,18 +243,11 @@ static void eevee_draw_background(void *vedata)
EEVEE_draw_shadows(sldata, psl);
DRW_stats_group_end();
- /* Attach depth to the hdr buffer and bind it */
- DRW_framebuffer_texture_detach(dtxl->depth);
- DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
- DRW_framebuffer_bind(fbl->main);
- if (DRW_state_draw_background()) {
- DRW_framebuffer_clear(false, true, true, NULL, 1.0f);
- }
- else {
- /* We need to clear the alpha chanel in this case. */
- float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- DRW_framebuffer_clear(true, true, true, clear_col, 1.0f);
- }
+ GPU_framebuffer_bind(fbl->main_fb);
+ GPUFrameBufferBits clear_bits = GPU_DEPTH_BIT;
+ clear_bits |= (DRW_state_draw_background()) ? 0 : GPU_COLOR_BIT;
+ clear_bits |= ((stl->effects->enabled_effects & EFFECT_SSS) != 0) ? GPU_STENCIL_BIT : 0;
+ GPU_framebuffer_clear(fbl->main_fb, clear_bits, clear_col, clear_depth, clear_stencil);
/* Depth prepass */
DRW_stats_group_start("Prepass");
@@ -295,11 +303,8 @@ static void eevee_draw_background(void *vedata)
}
}
- /* Restore default framebuffer */
- DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
- DRW_framebuffer_bind(dfbl->default_fb);
-
- /* Tonemapping */
+ /* Tonemapping and transfer result to default framebuffer. */
+ GPU_framebuffer_bind(dfbl->default_fb);
DRW_transform_to_display(stl->effects->final_tx);
/* Debug : Ouput buffer to view. */
@@ -308,25 +313,25 @@ static void eevee_draw_background(void *vedata)
if (txl->maxzbuffer) DRW_transform_to_display(txl->maxzbuffer);
break;
case 2:
- if (stl->g_data->ssr_pdf_output) DRW_transform_to_display(stl->g_data->ssr_pdf_output);
+ if (effects->ssr_pdf_output) DRW_transform_to_display(effects->ssr_pdf_output);
break;
case 3:
- if (txl->ssr_normal_input) DRW_transform_to_display(txl->ssr_normal_input);
+ if (effects->ssr_normal_input) DRW_transform_to_display(effects->ssr_normal_input);
break;
case 4:
- if (txl->ssr_specrough_input) DRW_transform_to_display(txl->ssr_specrough_input);
+ if (effects->ssr_specrough_input) DRW_transform_to_display(effects->ssr_specrough_input);
break;
case 5:
if (txl->color_double_buffer) DRW_transform_to_display(txl->color_double_buffer);
break;
case 6:
- if (stl->g_data->gtao_horizons_debug) DRW_transform_to_display(stl->g_data->gtao_horizons_debug);
+ if (effects->gtao_horizons_debug) DRW_transform_to_display(effects->gtao_horizons_debug);
break;
case 7:
- if (txl->gtao_horizons) DRW_transform_to_display(txl->gtao_horizons);
+ if (effects->gtao_horizons) DRW_transform_to_display(effects->gtao_horizons);
break;
case 8:
- if (txl->sss_data) DRW_transform_to_display(txl->sss_data);
+ if (effects->sss_data) DRW_transform_to_display(effects->sss_data);
break;
default:
break;
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index e751f2dd6b4..daab8deda7c 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -155,7 +155,6 @@ static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref)
/* XXX TODO OPTIMISATION : This is a complete waist of texture memory.
* Instead of allocating each planar probe for each viewport,
* only alloc them once using the biggest viewport resolution. */
- EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
const float *viewport_size = DRW_viewport_size_get();
@@ -182,15 +181,6 @@ static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref)
txl->planar_depth = DRW_texture_create_2D_array(1, 1, 1, DRW_TEX_DEPTH_24, 0, NULL);
}
}
-
- if (num_planar_ref > 0) {
- /* NOTE : Depth buffer is 2D but the planar_pool tex is 2D array.
- * DRW_framebuffer_init binds the whole texture making the framebuffer invalid.
- * To overcome this, we bind the planar pool ourselves later */
-
- /* XXX Do this one first so it gets it's mipmap done. */
- DRW_framebuffer_init(&fbl->planarref_fb, &draw_engine_eevee_type, 1, 1, NULL, 0);
- }
}
static void lightprobe_shaders_init(void)
@@ -349,7 +339,6 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
DRW_TEXTURE_FREE_SAFE(sldata->probe_depth_rt);
DRW_TEXTURE_FREE_SAFE(sldata->probe_rt);
DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
- DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_fb);
}
int visibility_res = BKE_collection_engine_property_value_get_int(props, "gi_visibility_resolution");
@@ -370,13 +359,12 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
sldata->probe_rt = DRW_texture_create_cube(sldata->probes->target_size, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
}
- DRWFboTexture tex_probe[2] = {{&sldata->probe_depth_rt, DRW_TEX_DEPTH_24, 0},
- {&sldata->probe_rt, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP}};
- DRW_framebuffer_init(&sldata->probe_fb, &draw_engine_eevee_type, sldata->probes->target_size, sldata->probes->target_size, tex_probe, 2);
-
- /* Minmaxz Pyramid */
- // DRWFboTexture tex_minmaxz = {&e_data.cube_face_minmaxz, DRW_TEX_RG_32, DRW_TEX_MIPMAP | DRW_TEX_TEMP};
- // DRW_framebuffer_init(&vedata->fbl->downsample_fb, &draw_engine_eevee_type, PROBE_RT_SIZE / 2, PROBE_RT_SIZE / 2, &tex_minmaxz, 1);
+ for (int i = 0; i < 6; ++i) {
+ GPU_framebuffer_ensure_config(&sldata->probe_face_fb[i], {
+ GPU_ATTACHMENT_TEXTURE_CUBEFACE(sldata->probe_depth_rt, i),
+ GPU_ATTACHMENT_TEXTURE_CUBEFACE(sldata->probe_rt, i)
+ });
+ }
/* Placeholder planar pool: used when rendering planar reflections (avoid dependency loop). */
if (!e_data.planar_pool_placeholder) {
@@ -957,7 +945,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
sldata->probe_pool = DRW_texture_create_2D_array(pinfo->cubemap_res, pinfo->cubemap_res, max_ff(1, pinfo->num_cube),
DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
if (sldata->probe_filter_fb) {
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+ GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
}
/* Tag probes to refresh */
pinfo->update_world |= PROBE_UPDATE_CUBE;
@@ -973,11 +961,6 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
}
}
- DRWFboTexture tex_filter = {&sldata->probe_pool, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
-
- DRW_framebuffer_init(&sldata->probe_filter_fb, &draw_engine_eevee_type, pinfo->cubemap_res, pinfo->cubemap_res, &tex_filter, 1);
-
-
#ifdef IRRADIANCE_SH_L2
/* we need a signed format for Spherical Harmonics */
int irradiance_format = DRW_TEX_RGBA_16;
@@ -1051,14 +1034,17 @@ static void glossy_filter_probe(
/* Max lod used from the render target probe */
pinfo->lod_rt_max = floorf(log2f(pinfo->target_size)) - 2.0f;
+ /* Start fresh */
+ GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_NONE
+ });
+
/* 2 - Let gpu create Mipmaps for Filtered Importance Sampling. */
/* Bind next framebuffer to be able to gen. mips for probe_rt. */
- DRW_framebuffer_bind(sldata->probe_filter_fb);
- EEVEE_downsample_cube_buffer(vedata, sldata->probe_filter_fb, sldata->probe_rt, (int)(pinfo->lod_rt_max));
+ EEVEE_downsample_cube_buffer(vedata, sldata->probe_rt, (int)(pinfo->lod_rt_max));
/* 3 - Render to probe array to the specified layer, do prefiltering. */
- /* Detach to rebind the right mipmap. */
- DRW_framebuffer_texture_detach(sldata->probe_pool);
float mipsize = pinfo->cubemap_res;
const int maxlevel = (int)floorf(log2f(pinfo->cubemap_res));
const int min_lod_level = 3;
@@ -1101,19 +1087,19 @@ static void glossy_filter_probe(
pinfo->invsamples_ct = 1.0f / pinfo->samples_ct;
pinfo->lodfactor = bias + 0.5f * log((float)(pinfo->target_size * pinfo->target_size) * pinfo->invsamples_ct) / log(2);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, i);
- DRW_framebuffer_viewport_size(sldata->probe_filter_fb, 0, 0, mipsize, mipsize);
+ GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE_MIP(sldata->probe_pool, i)
+ });
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
+ GPU_framebuffer_viewport_set(sldata->probe_filter_fb, 0, 0, mipsize, mipsize);
DRW_draw_pass(psl->probe_glossy_compute);
- DRW_framebuffer_texture_detach(sldata->probe_pool);
mipsize /= 2;
CLAMP_MIN(mipsize, 1);
}
/* For shading, save max level of the octahedron map */
sldata->common_data.prb_lod_cube_max = (float)(maxlevel - min_lod_level) - 1.0f;
-
- /* reattach to have a valid framebuffer. */
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
}
/* Diffuse filter probe_rt to irradiance_pool at index probe_idx */
@@ -1156,14 +1142,21 @@ static void diffuse_filter_probe(
pinfo->lod_rt_max = 2.0f; /* Improve cache reuse */
#endif
- /* 4 - Compute spherical harmonics */
- DRW_framebuffer_bind(sldata->probe_filter_fb);
- EEVEE_downsample_cube_buffer(vedata, sldata->probe_filter_fb, sldata->probe_rt, (int)(pinfo->lod_rt_max));
-
- DRW_framebuffer_texture_detach(sldata->probe_pool);
- DRW_framebuffer_texture_layer_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0, 0);
+ /* Start fresh */
+ GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_NONE
+ });
- DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, size[0], size[1]);
+ /* 4 - Compute spherical harmonics */
+ EEVEE_downsample_cube_buffer(vedata, sldata->probe_rt, (int)(pinfo->lod_rt_max));
+
+ GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE_LAYER(sldata->irradiance_rt, 0)
+ });
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
+ GPU_framebuffer_viewport_set(sldata->probe_filter_fb, x, y, size[0], size[1]);
DRW_draw_pass(psl->probe_diffuse_compute);
/* World irradiance have no visibility */
@@ -1183,18 +1176,16 @@ static void diffuse_filter_probe(
x = common_data->prb_irradiance_vis_size * (offset % cell_per_row);
y = common_data->prb_irradiance_vis_size * ((offset / cell_per_row) % cell_per_col);
int layer = 1 + ((offset / cell_per_row) / cell_per_col);
+ const int vis_size = common_data->prb_irradiance_vis_size;
- DRW_framebuffer_texture_detach(sldata->irradiance_rt);
- DRW_framebuffer_texture_layer_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, layer, 0);
-
- DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, common_data->prb_irradiance_vis_size,
- common_data->prb_irradiance_vis_size);
+ GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE_LAYER(sldata->irradiance_rt, layer)
+ });
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
+ GPU_framebuffer_viewport_set(sldata->probe_filter_fb, x, y, vis_size, vis_size);
DRW_draw_pass(psl->probe_visibility_compute);
}
-
- /* reattach to have a valid framebuffer. */
- DRW_framebuffer_texture_detach(sldata->irradiance_rt);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
}
/* Render the scene to the probe_rt texture. */
@@ -1204,7 +1195,6 @@ static void render_scene_to_probe(
{
EEVEE_TextureList *txl = vedata->txl;
EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
DRWMatrixState matstate;
@@ -1230,19 +1220,13 @@ static void render_scene_to_probe(
/* Avoid using the texture attached to framebuffer when rendering. */
/* XXX */
GPUTexture *tmp_planar_pool = txl->planar_pool;
- GPUTexture *tmp_minz = stl->g_data->minzbuffer;
GPUTexture *tmp_maxz = txl->maxzbuffer;
txl->planar_pool = e_data.planar_pool_placeholder;
- stl->g_data->minzbuffer = e_data.depth_placeholder;
txl->maxzbuffer = e_data.depth_placeholder;
/* Update common uniforms */
DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
- /* Detach to rebind the right cubeface. */
- DRW_framebuffer_bind(sldata->probe_fb);
- DRW_framebuffer_texture_detach(sldata->probe_rt);
- DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
for (int i = 0; i < 6; ++i) {
/* Setup custom matrices */
mul_m4_m4m4(viewmat, cubefacemat[i], posmat);
@@ -1256,11 +1240,8 @@ static void render_scene_to_probe(
/* Be sure that cascaded shadow maps are updated. */
EEVEE_draw_shadows(sldata, psl);
- DRW_framebuffer_cubeface_attach(sldata->probe_fb, sldata->probe_rt, 0, i, 0);
- DRW_framebuffer_cubeface_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, i, 0);
- DRW_framebuffer_viewport_size(sldata->probe_fb, 0, 0, pinfo->target_size, pinfo->target_size);
-
- DRW_framebuffer_clear(false, true, false, NULL, 1.0);
+ GPU_framebuffer_bind(sldata->probe_face_fb[i]);
+ GPU_framebuffer_clear_depth(sldata->probe_face_fb[i], 1.0);
/* Depth prepass */
DRW_draw_pass(psl->depth_pass);
@@ -1270,23 +1251,17 @@ static void render_scene_to_probe(
// EEVEE_create_minmax_buffer(vedata, sldata->probe_depth_rt);
- /* Rebind Planar FB */
- DRW_framebuffer_bind(sldata->probe_fb);
+ /* Rebind Target FB */
+ GPU_framebuffer_bind(sldata->probe_face_fb[i]);
/* Shading pass */
EEVEE_draw_default_passes(psl);
DRW_draw_pass(psl->material_pass);
DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
-
- DRW_framebuffer_texture_detach(sldata->probe_rt);
- DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
}
- DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_rt, 0, 0);
- DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, 0);
/* Restore */
txl->planar_pool = tmp_planar_pool;
- stl->g_data->minzbuffer = tmp_minz;
txl->maxzbuffer = tmp_maxz;
}
@@ -1322,12 +1297,13 @@ static void render_scene_to_planar(
DRW_uniformbuffer_update(sldata->clip_ubo, &sldata->clip_data);
DRW_state_clip_planes_count_set(1);
- /* Attach depth here since it's a DRW_TEX_TEMP */
- DRW_framebuffer_texture_layer_attach(fbl->planarref_fb, txl->planar_depth, 0, layer, 0);
- DRW_framebuffer_texture_layer_attach(fbl->planarref_fb, txl->planar_pool, 0, layer, 0);
- DRW_framebuffer_bind(fbl->planarref_fb);
+ GPU_framebuffer_ensure_config(&fbl->planarref_fb, {
+ GPU_ATTACHMENT_TEXTURE_LAYER(txl->planar_depth, layer),
+ GPU_ATTACHMENT_TEXTURE_LAYER(txl->planar_pool, layer)
+ });
- DRW_framebuffer_clear(false, true, false, NULL, 1.0);
+ GPU_framebuffer_bind(fbl->planarref_fb);
+ GPU_framebuffer_clear_depth(fbl->planarref_fb, 1.0);
/* Avoid using the texture attached to framebuffer when rendering. */
/* XXX */
@@ -1354,7 +1330,7 @@ static void render_scene_to_planar(
EEVEE_occlusion_compute(sldata, vedata, tmp_planar_depth, layer);
/* Rebind Planar FB */
- DRW_framebuffer_bind(fbl->planarref_fb);
+ GPU_framebuffer_bind(fbl->planarref_fb);
/* Shading pass */
EEVEE_draw_default_passes(psl);
@@ -1375,9 +1351,6 @@ static void render_scene_to_planar(
/* Restore */
txl->planar_pool = tmp_planar_pool;
txl->planar_depth = tmp_planar_depth;
-
- DRW_framebuffer_texture_detach(txl->planar_pool);
- DRW_framebuffer_texture_detach(txl->planar_depth);
}
static void render_world_to_probe(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
@@ -1397,10 +1370,6 @@ static void render_world_to_probe(EEVEE_ViewLayerData *sldata, EEVEE_PassList *p
perspective_m4(winmat, -0.1f, 0.1f, -0.1f, 0.1f, 0.1f, 1.0f);
invert_m4_m4(wininv, winmat);
- /* Detach to rebind the right cubeface. */
- DRW_framebuffer_bind(sldata->probe_fb);
- DRW_framebuffer_texture_detach(sldata->probe_rt);
- DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
for (int i = 0; i < 6; ++i) {
/* Setup custom matrices */
copy_m4_m4(viewmat, cubefacemat[i]);
@@ -1409,15 +1378,10 @@ static void render_world_to_probe(EEVEE_ViewLayerData *sldata, EEVEE_PassList *p
invert_m4_m4(viewinv, viewmat);
DRW_viewport_matrix_override_set_all(&matstate);
- DRW_framebuffer_cubeface_attach(sldata->probe_fb, sldata->probe_rt, 0, i, 0);
- DRW_framebuffer_viewport_size(sldata->probe_fb, 0, 0, pinfo->target_size, pinfo->target_size);
-
+ GPU_framebuffer_bind(sldata->probe_face_fb[i]);
+ GPU_framebuffer_clear_depth(sldata->probe_face_fb[i], 1.0f);
DRW_draw_pass(psl->probe_background);
-
- DRW_framebuffer_texture_detach(sldata->probe_rt);
}
- DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_rt, 0, 0);
- DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, 0);
}
static void lightprobe_cell_grid_location_get(EEVEE_LightGrid *egrid, int cell_idx, float r_local_cell[3])
@@ -1459,12 +1423,13 @@ static void lightprobes_refresh_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
}
if (pinfo->update_world & PROBE_UPDATE_GRID) {
diffuse_filter_probe(sldata, vedata, psl, 0, 0.0, 0.0, 0.0, 0.0, 1.0);
+
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
- DRW_framebuffer_texture_detach(sldata->probe_pool);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+
+ GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
DRW_draw_pass(psl->probe_grid_fill);
- DRW_framebuffer_texture_detach(sldata->irradiance_rt);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+
common_data->prb_num_render_grid = 1;
/* Reset volume history. */
stl->effects->volume_current_sample = -1;
@@ -1486,27 +1451,26 @@ static void lightprobes_refresh_initialize_grid(EEVEE_ViewLayerData *sldata, EEV
/* Grid is already initialized, nothing to do. */
return;
}
- DRW_framebuffer_texture_detach(sldata->probe_pool);
/* Flood fill with world irradiance. */
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
- DRW_framebuffer_bind(sldata->probe_filter_fb);
+ GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
DRW_draw_pass(psl->probe_grid_fill);
- DRW_framebuffer_texture_detach(sldata->irradiance_rt);
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+
+ GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
DRW_draw_pass(psl->probe_grid_fill);
- DRW_framebuffer_texture_detach(sldata->irradiance_rt);
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
- /* Reattach to have a valid framebuffer. */
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+
pinfo->grid_initialized = true;
}
void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
Object *ob;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
@@ -1547,7 +1511,12 @@ void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
if ((vedata->stl->effects->enabled_effects & EFFECT_SSR) != 0) {
const int max_lod = 9;
DRW_stats_group_start("Planar Probe Downsample");
- DRW_framebuffer_recursive_downsample(vedata->fbl->downsample_fb, txl->planar_pool, max_lod, &downsample_planar, vedata);
+
+ GPU_framebuffer_ensure_config(&fbl->planar_downsample_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->planar_pool)
+ });
+ GPU_framebuffer_recursive_downsample(fbl->planar_downsample_fb, max_lod, &downsample_planar, vedata);
/* For shading, save max level of the planar map */
common_data->prb_lod_planar_max = (float)(max_lod);
DRW_stats_group_end();
@@ -1738,12 +1707,11 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
}
/* Reset the next buffer so we can see the progress. */
/* irradiance_rt is already the next rt because of the previous SWAP */
- DRW_framebuffer_texture_detach(sldata->probe_pool);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
- DRW_framebuffer_bind(sldata->probe_filter_fb);
+ GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+ GPU_framebuffer_bind(sldata->probe_filter_fb);
DRW_draw_pass(psl->probe_grid_fill);
- DRW_framebuffer_texture_detach(sldata->irradiance_rt);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+
+ GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
/* Swap AFTER */
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
}
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index b4afb8bb555..443fdff15e3 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -505,7 +505,6 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata)
linfo->shadow_size, linfo->shadow_size, MAX_CASCADE_NUM, shadow_pool_format, DRW_TEX_FILTER, NULL);
}
- /* Initialize Textures Array first so DRW_framebuffer_init just bind them. */
if (!sldata->shadow_pool) {
/* All shadows fit in this array */
sldata->shadow_pool = DRW_texture_create_2D_array(
@@ -514,19 +513,18 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata)
}
/* Render FB */
- DRWFboTexture tex_cascade = {&sldata->shadow_cube_target, DRW_TEX_DEPTH_24, 0};
- DRW_framebuffer_init(&sldata->shadow_target_fb, &draw_engine_eevee_type,
- linfo->shadow_size, linfo->shadow_size,
- &tex_cascade, 1);
+ GPU_framebuffer_ensure_config(&sldata->shadow_cube_target_fb, {
+ GPU_ATTACHMENT_TEXTURE(sldata->shadow_cube_target)
+ });
+ GPU_framebuffer_ensure_config(&sldata->shadow_cascade_target_fb, {
+ GPU_ATTACHMENT_TEXTURE(sldata->shadow_cascade_target)
+ });
/* Storage FB */
- DRWFboTexture tex_pool = {&sldata->shadow_pool, shadow_pool_format, DRW_TEX_FILTER};
- DRW_framebuffer_init(&sldata->shadow_store_fb, &draw_engine_eevee_type,
- linfo->shadow_size, linfo->shadow_size,
- &tex_pool, 1);
-
- /* Restore */
- DRW_framebuffer_texture_detach(sldata->shadow_cube_target);
+ GPU_framebuffer_ensure_config(&sldata->shadow_store_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(sldata->shadow_pool)
+ });
/* Update Lamps UBOs. */
EEVEE_lights_update(sldata);
@@ -1033,7 +1031,6 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
EEVEE_LampsInfo *linfo = sldata->lamps;
Object *ob;
int i;
- float clear_col[4] = {FLT_MAX};
DRWMatrixState saved_mats;
@@ -1042,7 +1039,6 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
/* Cube Shadow Maps */
DRW_stats_group_start("Cube Shadow Maps");
- DRW_framebuffer_texture_attach(sldata->shadow_target_fb, sldata->shadow_cube_target, 0, 0);
/* Render each shadow to one layer of the array */
for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
@@ -1073,11 +1069,10 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
eevee_shadows_cube_culling_frustum(srd);
- DRW_framebuffer_bind(sldata->shadow_target_fb);
- DRW_framebuffer_clear(true, true, false, clear_col, 1.0f);
-
/* Render shadow cube */
linfo->shadow_instance_count = 6;
+ GPU_framebuffer_bind(sldata->shadow_cube_target_fb);
+ GPU_framebuffer_clear_depth(sldata->shadow_cube_target_fb, 1.0f);
DRW_draw_pass(psl->shadow_pass);
/* 0.001f is arbitrary, but it should be relatively small so that filter size is not too big. */
@@ -1091,10 +1086,10 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
linfo->current_shadow_face++)
{
/* Copy using a small 3x3 box filter */
- DRW_framebuffer_cubeface_attach(sldata->shadow_store_fb, sldata->shadow_cube_blur, 0, linfo->current_shadow_face, 0);
- DRW_framebuffer_bind(sldata->shadow_store_fb);
+ GPU_framebuffer_texture_cubeface_attach(sldata->shadow_store_fb, sldata->shadow_cube_blur, 0,
+ linfo->current_shadow_face, 0);
+ GPU_framebuffer_bind(sldata->shadow_store_fb);
DRW_draw_pass(psl->shadow_cube_copy_pass);
- DRW_framebuffer_texture_detach(sldata->shadow_cube_blur);
}
/* Push it to shadowmap array */
@@ -1118,22 +1113,19 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
srd->shadow_inv_samples_ct = 1.0f / (float)srd->shadow_samples_ct;
DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
- DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, evscd->layer_id, 0);
- DRW_framebuffer_bind(sldata->shadow_store_fb);
+ GPU_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, evscd->layer_id, 0);
+ GPU_framebuffer_bind(sldata->shadow_store_fb);
DRW_draw_pass(psl->shadow_cube_store_pass);
led->need_update = false;
}
linfo->update_flag &= ~LIGHT_UPDATE_SHADOW_CUBE;
-
- DRW_framebuffer_texture_detach(sldata->shadow_cube_target);
DRW_stats_group_end();
DRW_viewport_matrix_override_set_all(&saved_mats);
/* Cascaded Shadow Maps */
DRW_stats_group_start("Cascaded Shadow Maps");
- DRW_framebuffer_texture_attach(sldata->shadow_target_fb, sldata->shadow_cascade_target, 0, 0);
for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) {
EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
Lamp *la = (Lamp *)ob->data;
@@ -1150,13 +1142,12 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
}
DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
- DRW_framebuffer_bind(sldata->shadow_target_fb);
- DRW_framebuffer_clear(false, true, false, NULL, 1.0);
-
eevee_shadows_cascade_culling_frustum(evscd);
/* Render shadow cascades */
linfo->shadow_instance_count = la->cascade_count;
+ GPU_framebuffer_bind(sldata->shadow_cascade_target_fb);
+ GPU_framebuffer_clear_depth(sldata->shadow_cascade_target_fb, 1.0);
DRW_draw_pass(psl->shadow_pass);
/* TODO: OPTI: Filter all cascade in one/two draw call */
@@ -1170,11 +1161,10 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
/* Copy using a small 3x3 box filter */
linfo->filter_size = linfo->shadow_render_data.stored_texel_size * ((filter_pixel_size > 1.0f) ? 1.0f : 0.0f);
- DRW_framebuffer_texture_layer_attach(
+ GPU_framebuffer_texture_layer_attach(
sldata->shadow_store_fb, sldata->shadow_cascade_blur, 0, linfo->current_shadow_cascade, 0);
- DRW_framebuffer_bind(sldata->shadow_store_fb);
+ GPU_framebuffer_bind(sldata->shadow_store_fb);
DRW_draw_pass(psl->shadow_cascade_copy_pass);
- DRW_framebuffer_texture_detach(sldata->shadow_cascade_blur);
/* Push it to shadowmap array and blur more */
@@ -1198,13 +1188,12 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
int layer = evscd->layer_id + linfo->current_shadow_cascade;
- DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, layer, 0);
- DRW_framebuffer_bind(sldata->shadow_store_fb);
+ GPU_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, layer, 0);
+ GPU_framebuffer_bind(sldata->shadow_store_fb);
DRW_draw_pass(psl->shadow_cascade_store_pass);
}
}
- DRW_framebuffer_texture_detach(sldata->shadow_cascade_target);
DRW_stats_group_end();
DRW_viewport_matrix_override_set_all(&saved_mats);
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 6215445e113..a7cc645f738 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -138,9 +138,9 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
tex = DRW_texture_create_2D(w, h, DRW_TEX_RG_16, DRW_TEX_FILTER, (float *)texels);
DRWFboTexture tex_filter = {&tex, DRW_TEX_RG_16, DRW_TEX_FILTER};
- DRW_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+ GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
- DRW_framebuffer_bind(fb);
+ GPU_framebuffer_bind(fb);
DRW_draw_pass(pass);
float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
@@ -200,9 +200,9 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
tex = DRW_texture_create_2D(w, h, DRW_TEX_R_16, DRW_TEX_FILTER, (float *)texels);
DRWFboTexture tex_filter = {&tex, DRW_TEX_R_16, DRW_TEX_FILTER};
- DRW_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+ GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
- DRW_framebuffer_bind(fb);
+ GPU_framebuffer_bind(fb);
float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
@@ -216,7 +216,7 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
a2 = powf(roughness, 4.0f);
DRW_draw_pass(pass);
- DRW_framebuffer_read_data(0, 0, w, h, 3, 0, data);
+ GPU_framebuffer_read_data(0, 0, w, h, 3, 0, data);
#if 1
fprintf(f, "\t{\n\t\t");
@@ -374,7 +374,7 @@ static void add_standard_uniforms(
DRW_shgroup_uniform_buffer(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
if ((vedata->stl->effects->enabled_effects & EFFECT_GTAO) != 0) {
- DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->gtao_horizons);
+ DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->stl->effects->gtao_horizons);
}
else {
/* Use maxzbuffer as fallback to avoid sampling problem on certain platform, see: T52593 */
@@ -482,10 +482,8 @@ void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const d
/* Attach & detach because we don't currently support multiple FB per texture,
* and this would be the case for multiple viewport. */
- DRW_framebuffer_texture_layer_attach(fbl->update_noise_fb, e_data.util_tex, 0, 2, 0);
- DRW_framebuffer_bind(fbl->update_noise_fb);
+ GPU_framebuffer_bind(fbl->update_noise_fb);
DRW_draw_pass(psl->update_noise_pass);
- DRW_framebuffer_texture_detach(e_data.util_tex);
}
static void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4])
@@ -623,9 +621,10 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, E
{
/* Update noise Framebuffer. */
- if (fbl->update_noise_fb == NULL) {
- fbl->update_noise_fb = DRW_framebuffer_create();
- }
+ GPU_framebuffer_ensure_config(&fbl->update_noise_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE_LAYER(e_data.util_tex, 2)
+ });
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c
index e221ed865b5..eaef3121a3f 100644
--- a/source/blender/draw/engines/eevee/eevee_mist.c
+++ b/source/blender/draw/engines/eevee/eevee_mist.c
@@ -55,7 +55,6 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
EEVEE_PrivateData *g_data = stl->g_data;
Scene *scene = draw_ctx->scene;
- const float *viewport_size = DRW_viewport_size_get();
float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
if (e_data.mist_sh == NULL) {
@@ -71,13 +70,16 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
/* Create FrameBuffer. */
- DRWFboTexture tex_data = {&txl->mist_accum, DRW_TEX_R_32, 0}; /* Should be enough precision for many samples. */
- DRW_framebuffer_init(&fbl->mist_accum_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1],
- &tex_data, 1);
+ DRW_texture_ensure_fullscreen_2D(&txl->mist_accum, DRW_TEX_R_32, 0); /* Should be enough precision for many samples. */
+
+ GPU_framebuffer_ensure_config(&fbl->mist_accum_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->mist_accum)
+ });
/* Clear texture. */
- DRW_framebuffer_bind(fbl->mist_accum_fb);
- DRW_framebuffer_clear(true, false, false, clear, 0.0f);
+ GPU_framebuffer_bind(fbl->mist_accum_fb);
+ GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear);
/* Mist settings. */
if (scene && scene->world) {
@@ -123,11 +125,11 @@ void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
EEVEE_PassList *psl = vedata->psl;
if (fbl->mist_accum_fb != NULL) {
- DRW_framebuffer_bind(fbl->mist_accum_fb);
+ GPU_framebuffer_bind(fbl->mist_accum_fb);
DRW_draw_pass(psl->mist_accum_ps);
/* Restore */
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
index 53fff5de50e..3278b288d6b 100644
--- a/source/blender/draw/engines/eevee/eevee_motion_blur.c
+++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c
@@ -217,7 +217,7 @@ void EEVEE_motion_blur_draw(EEVEE_Data *vedata)
/* Motion Blur */
if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) {
- DRW_framebuffer_bind(effects->target_buffer);
+ GPU_framebuffer_bind(effects->target_buffer);
DRW_draw_pass(psl->motion_blur);
SWAP_BUFFERS();
}
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index d7d022e9b98..9c5cb09148a 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -68,9 +68,9 @@ static void eevee_create_shader_occlusion(void)
int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
- EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
- EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
@@ -80,6 +80,7 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
if (BKE_collection_engine_property_value_get_bool(props, "gtao_enable")) {
const float *viewport_size = DRW_viewport_size_get();
+ const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
/* Shaders */
if (!e_data.gtao_sh) {
@@ -100,26 +101,31 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
common_data->ao_bounce_fac = (float)BKE_collection_engine_property_value_get_bool(props, "gtao_bounce");
- DRWFboTexture tex = {&txl->gtao_horizons, DRW_TEX_RGBA_8, 0};
-
- DRW_framebuffer_init(&fbl->gtao_fb, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex, 1);
+ effects->gtao_horizons = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], DRW_TEX_RGBA_8,
+ &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->gtao_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->gtao_horizons)
+ });
if (G.debug_value == 6) {
- DRWFboTexture tex_debug = {&stl->g_data->gtao_horizons_debug, DRW_TEX_RGBA_8, DRW_TEX_TEMP};
-
- DRW_framebuffer_init(&fbl->gtao_debug_fb, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex_debug, 1);
+ effects->gtao_horizons_debug = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], DRW_TEX_RGBA_8,
+ &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->gtao_debug_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->gtao_horizons_debug)
+ });
+ }
+ else {
+ effects->gtao_horizons_debug = NULL;
}
return EFFECT_GTAO | EFFECT_NORMAL_BUFFER;
}
/* Cleanup */
- DRW_TEXTURE_FREE_SAFE(txl->gtao_horizons);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->gtao_fb);
+ effects->gtao_horizons = NULL;
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->gtao_fb);
common_data->ao_settings = 0.0f;
return 0;
@@ -129,8 +135,9 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
{
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_StorageList *stl = vedata->stl;
EEVEE_PassList *psl = vedata->psl;
- const float *viewport_size = DRW_viewport_size_get();
+ EEVEE_EffectsInfo *effects = stl->effects;
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
@@ -140,13 +147,16 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- DRWFboTexture tex_data = {&txl->ao_accum, DRW_TEX_R_32, 0};
- DRW_framebuffer_init(&fbl->ao_accum_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1],
- &tex_data, 1);
+ DRW_texture_ensure_fullscreen_2D(&txl->ao_accum, DRW_TEX_R_32, 0); /* Should be enough precision for many samples. */
+
+ GPU_framebuffer_ensure_config(&fbl->ao_accum_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->ao_accum)
+ });
/* Clear texture. */
- DRW_framebuffer_bind(fbl->ao_accum_fb);
- DRW_framebuffer_clear(true, false, false, clear, 0.0f);
+ GPU_framebuffer_bind(fbl->ao_accum_fb);
+ GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear);
/* Accumulation pass */
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE;
@@ -155,15 +165,15 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
- DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &txl->gtao_horizons);
+ DRW_shgroup_uniform_buffer(grp, "normalBuffer", &effects->ssr_normal_input);
+ DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
else {
/* Cleanup to release memory */
DRW_TEXTURE_FREE_SAFE(txl->ao_accum);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->ao_accum_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->ao_accum_fb);
}
}
@@ -212,8 +222,8 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
- DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &txl->gtao_horizons);
+ DRW_shgroup_uniform_buffer(grp, "normalBuffer", &effects->ssr_normal_input);
+ DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_call_add(grp, quad, NULL);
}
@@ -233,7 +243,7 @@ void EEVEE_occlusion_compute(
effects->ao_src_depth = depth_src;
effects->ao_depth_layer = layer;
- DRW_framebuffer_bind(fbl->gtao_fb);
+ GPU_framebuffer_bind(fbl->gtao_fb);
if (layer >= 0) {
DRW_draw_pass(psl->ao_horizon_search_layer);
@@ -243,7 +253,7 @@ void EEVEE_occlusion_compute(
}
/* Restore */
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
DRW_stats_group_end();
}
@@ -259,14 +269,11 @@ void EEVEE_occlusion_draw_debug(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
if (((effects->enabled_effects & EFFECT_GTAO) != 0) && (G.debug_value == 6)) {
DRW_stats_group_start("GTAO Debug");
- DRW_framebuffer_texture_attach(fbl->gtao_debug_fb, stl->g_data->gtao_horizons_debug, 0, 0);
- DRW_framebuffer_bind(fbl->gtao_debug_fb);
-
+ GPU_framebuffer_bind(fbl->gtao_debug_fb);
DRW_draw_pass(psl->ao_horizon_debug);
/* Restore */
- DRW_framebuffer_texture_detach(stl->g_data->gtao_horizons_debug);
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
DRW_stats_group_end();
}
@@ -284,11 +291,11 @@ void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *
EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1);
EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1);
- DRW_framebuffer_bind(fbl->ao_accum_fb);
+ GPU_framebuffer_bind(fbl->ao_accum_fb);
DRW_draw_pass(psl->ao_accum_ps);
/* Restore */
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 88fb55cfbdf..b000cad6601 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -72,22 +72,23 @@ extern struct DrawEngineType draw_engine_eevee_type;
#define SWAP_DOUBLE_BUFFERS() { \
if (effects->swap_double_buffer) { \
- SWAP(struct GPUFrameBuffer *, fbl->main, fbl->double_buffer); \
+ SWAP(struct GPUFrameBuffer *, fbl->main_fb, fbl->double_buffer_fb); \
+ SWAP(struct GPUFrameBuffer *, fbl->main_color_fb, fbl->double_buffer_color_fb); \
SWAP(GPUTexture *, txl->color, txl->color_double_buffer); \
effects->swap_double_buffer = false; \
} \
} ((void)0)
#define SWAP_BUFFERS() { \
- if (effects->target_buffer != fbl->main) { \
+ if (effects->target_buffer == fbl->effect_color_fb) { \
SWAP_DOUBLE_BUFFERS(); \
effects->source_buffer = txl->color_post; \
- effects->target_buffer = fbl->main; \
+ effects->target_buffer = fbl->main_color_fb; \
} \
else { \
SWAP_DOUBLE_BUFFERS(); \
effects->source_buffer = txl->color; \
- effects->target_buffer = fbl->effect_fb; \
+ effects->target_buffer = fbl->effect_color_fb; \
} \
} ((void)0)
@@ -217,11 +218,11 @@ typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *gtao_fb;
struct GPUFrameBuffer *gtao_debug_fb;
struct GPUFrameBuffer *downsample_fb;
- struct GPUFrameBuffer *effect_fb;
struct GPUFrameBuffer *bloom_blit_fb;
struct GPUFrameBuffer *bloom_down_fb[MAX_BLOOM_STEP];
struct GPUFrameBuffer *bloom_accum_fb[MAX_BLOOM_STEP - 1];
struct GPUFrameBuffer *sss_blur_fb;
+ struct GPUFrameBuffer *sss_resolve_fb;
struct GPUFrameBuffer *sss_clear_fb;
struct GPUFrameBuffer *sss_accum_fb;
struct GPUFrameBuffer *dof_down_fb;
@@ -238,30 +239,24 @@ typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *update_noise_fb;
struct GPUFrameBuffer *planarref_fb;
+ struct GPUFrameBuffer *planar_downsample_fb;
- struct GPUFrameBuffer *main;
- struct GPUFrameBuffer *double_buffer;
- struct GPUFrameBuffer *depth_double_buffer_fb;
+ struct GPUFrameBuffer *main_fb;
+ struct GPUFrameBuffer *main_color_fb;
+ struct GPUFrameBuffer *effect_fb;
+ struct GPUFrameBuffer *effect_color_fb;
+ struct GPUFrameBuffer *double_buffer_fb;
+ struct GPUFrameBuffer *double_buffer_color_fb;
+ struct GPUFrameBuffer *double_buffer_depth_fb;
} EEVEE_FramebufferList;
typedef struct EEVEE_TextureList {
/* Effects */
struct GPUTexture *color_post; /* R16_G16_B16 */
- struct GPUTexture *dof_down_near; /* R16_G16_B16_A16 */
- struct GPUTexture *dof_down_far; /* R16_G16_B16_A16 */
- struct GPUTexture *dof_coc; /* R16_G16 */
- struct GPUTexture *dof_near_blur; /* R16_G16_B16_A16 */
- struct GPUTexture *dof_far_blur; /* R16_G16_B16_A16 */
- struct GPUTexture *bloom_blit; /* R16_G16_B16 */
- struct GPUTexture *bloom_downsample[MAX_BLOOM_STEP]; /* R16_G16_B16 */
- struct GPUTexture *bloom_upsample[MAX_BLOOM_STEP - 1]; /* R16_G16_B16 */
struct GPUTexture *mist_accum;
struct GPUTexture *ao_accum;
struct GPUTexture *sss_dir_accum;
struct GPUTexture *sss_col_accum;
- struct GPUTexture *ssr_normal_input;
- struct GPUTexture *ssr_specrough_input;
- struct GPUTexture *ssr_hit_output;
struct GPUTexture *refract_color;
struct GPUTexture *volume_prop_scattering;
@@ -276,13 +271,6 @@ typedef struct EEVEE_TextureList {
struct GPUTexture *planar_pool;
struct GPUTexture *planar_depth;
- struct GPUTexture *gtao_horizons;
-
- struct GPUTexture *sss_data;
- struct GPUTexture *sss_albedo;
- struct GPUTexture *sss_blur;
- struct GPUTexture *sss_stencil;
-
struct GPUTexture *maxzbuffer;
struct GPUTexture *color; /* R16_G16_B16 */
@@ -486,12 +474,20 @@ typedef struct EEVEE_EffectsInfo {
/* SSSS */
int sss_sample_count;
bool sss_separate_albedo;
+ struct GPUTexture *sss_data; /* Textures from pool */
+ struct GPUTexture *sss_albedo;
+ struct GPUTexture *sss_blur;
+ struct GPUTexture *sss_stencil;
/* Volumetrics */
int volume_current_sample;
/* SSR */
bool reflection_trace_full;
int ssr_neighbor_ofs;
int ssr_halfres_ofs[2];
+ struct GPUTexture *ssr_normal_input; /* Textures from pool */
+ struct GPUTexture *ssr_specrough_input;
+ struct GPUTexture *ssr_hit_output;
+ struct GPUTexture *ssr_pdf_output;
/* Temporal Anti Aliasing */
int taa_current_sample;
int taa_render_sample;
@@ -506,6 +502,8 @@ typedef struct EEVEE_EffectsInfo {
/* Ambient Occlusion */
int ao_depth_layer;
struct GPUTexture *ao_src_depth; /* pointer copy */
+ struct GPUTexture *gtao_horizons; /* Textures from pool */
+ struct GPUTexture *gtao_horizons_debug;
/* Motion Blur */
float current_ndc_to_world[4][4];
float past_world_to_ndc[4][4];
@@ -516,6 +514,11 @@ typedef struct EEVEE_EffectsInfo {
float dof_bokeh[4];
float dof_layer_select[2];
int dof_target_size[2];
+ struct GPUTexture *dof_down_near; /* Textures from pool */
+ struct GPUTexture *dof_down_far;
+ struct GPUTexture *dof_coc;
+ struct GPUTexture *dof_near_blur;
+ struct GPUTexture *dof_far_blur;
/* Other */
float prev_persmat[4][4];
/* Bloom */
@@ -528,6 +531,9 @@ typedef struct EEVEE_EffectsInfo {
float bloom_sample_scale;
float bloom_curve_threshold[4];
float unf_source_texel_size[2];
+ struct GPUTexture *bloom_blit; /* Textures from pool */
+ struct GPUTexture *bloom_downsample[MAX_BLOOM_STEP];
+ struct GPUTexture *bloom_upsample[MAX_BLOOM_STEP - 1];
struct GPUTexture *unf_source_buffer; /* pointer copy */
struct GPUTexture *unf_base_buffer; /* pointer copy */
/* Not alloced, just a copy of a *GPUtexture in EEVEE_TextureList. */
@@ -620,7 +626,8 @@ typedef struct EEVEE_ViewLayerData {
struct GPUUniformBuffer *shadow_render_ubo;
struct GPUUniformBuffer *shadow_samples_ubo;
- struct GPUFrameBuffer *shadow_target_fb;
+ struct GPUFrameBuffer *shadow_cube_target_fb;
+ struct GPUFrameBuffer *shadow_cascade_target_fb;
struct GPUFrameBuffer *shadow_store_fb;
struct GPUTexture *shadow_cube_target;
@@ -638,8 +645,8 @@ typedef struct EEVEE_ViewLayerData {
struct GPUUniformBuffer *grid_ubo;
struct GPUUniformBuffer *planar_ubo;
- struct GPUFrameBuffer *probe_fb;
struct GPUFrameBuffer *probe_filter_fb;
+ struct GPUFrameBuffer *probe_face_fb[6];
struct GPUTexture *probe_rt;
struct GPUTexture *probe_depth_rt;
@@ -746,9 +753,6 @@ typedef struct EEVEE_PrivateData {
struct DRWShadingGroup *planar_display_shgrp;
struct GHash *material_hash;
struct GHash *hair_material_hash;
- struct GPUTexture *minzbuffer;
- struct GPUTexture *ssr_pdf_output;
- struct GPUTexture *gtao_horizons_debug;
float background_alpha; /* TODO find a better place for this. */
/* For planar probes */
float planar_texel_size[2];
@@ -890,8 +894,8 @@ void EEVEE_volumes_free(void);
void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera);
void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer);
-void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level);
-void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level);
+void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level);
+void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level);
void EEVEE_effects_do_gtao(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_effects_free(void);
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index 52d45e2ef04..130999adb39 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -53,7 +53,6 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
Scene *scene = DEG_get_evaluated_scene(depsgraph);
- const float *viewport_size = DRW_viewport_size_get();
/* Init default FB and render targets:
* In render mode the default framebuffer is not generated
@@ -62,16 +61,22 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- /* NOTE : use 32 bit format for precision in render mode. */
- DRWFboTexture dtex = {&dtxl->depth, DRW_TEX_DEPTH_24_STENCIL_8, 0};
- DRW_framebuffer_init(&dfbl->default_fb, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &dtex, 1);
-
- DRWFboTexture tex = {&txl->color, DRW_TEX_RGBA_32, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
- DRW_framebuffer_init(&fbl->main, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex, 1);
+ /* TODO 32 bit depth */
+ DRW_texture_ensure_fullscreen_2D(&dtxl->depth, DRW_TEX_DEPTH_24_STENCIL_8, 0);
+ DRW_texture_ensure_fullscreen_2D(&txl->color, DRW_TEX_RGBA_32, DRW_TEX_FILTER | DRW_TEX_MIPMAP);
+
+ GPU_framebuffer_ensure_config(&dfbl->default_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(txl->color)
+ });
+ GPU_framebuffer_ensure_config(&fbl->main_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(txl->color)
+ });
+ GPU_framebuffer_ensure_config(&fbl->main_color_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->color)
+ });
/* Alloc transient data. */
if (!stl->g_data) {
@@ -166,8 +171,11 @@ static void eevee_render_result_combined(
{
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname);
- DRW_framebuffer_bind(vedata->stl->effects->final_fb);
- DRW_framebuffer_read_data(rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), 4, 0, rp->rect);
+ GPU_framebuffer_bind(vedata->stl->effects->final_fb);
+ GPU_framebuffer_read_color(vedata->stl->effects->final_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ 4, 0, rp->rect);
}
static void eevee_render_result_subsurface(
@@ -185,8 +193,11 @@ static void eevee_render_result_subsurface(
if ((view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) != 0) {
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_COLOR, viewname);
- DRW_framebuffer_bind(vedata->fbl->sss_accum_fb);
- DRW_framebuffer_read_data(rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), 3, 1, rp->rect);
+ GPU_framebuffer_bind(vedata->fbl->sss_accum_fb);
+ GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ 3, 1, rp->rect);
/* This is the accumulated color. Divide by the number of samples. */
for (int i = 0; i < rp->rectx * rp->recty * 3; i++) {
@@ -197,8 +208,11 @@ static void eevee_render_result_subsurface(
if ((view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT) != 0) {
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_DIRECT, viewname);
- DRW_framebuffer_bind(vedata->fbl->sss_accum_fb);
- DRW_framebuffer_read_data(rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), 3, 0, rp->rect);
+ GPU_framebuffer_bind(vedata->fbl->sss_accum_fb);
+ GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ 3, 0, rp->rect);
/* This is the accumulated color. Divide by the number of samples. */
for (int i = 0; i < rp->rectx * rp->recty * 3; i++) {
@@ -228,7 +242,11 @@ static void eevee_render_result_normal(
if ((view_layer->passflag & SCE_PASS_NORMAL) != 0) {
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_NORMAL, viewname);
- DRW_framebuffer_read_data(rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), 3, 1, rp->rect);
+ GPU_framebuffer_bind(vedata->fbl->main_fb);
+ GPU_framebuffer_read_color(vedata->fbl->main_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ 3, 1, rp->rect);
/* Convert Eevee encoded normals to Blender normals. */
for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) {
@@ -270,7 +288,10 @@ static void eevee_render_result_z(
if ((view_layer->passflag & SCE_PASS_Z) != 0) {
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname);
- DRW_framebuffer_read_depth(rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), rp->rect);
+ GPU_framebuffer_read_depth(vedata->fbl->main_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ rp->rect);
bool is_persp = DRW_viewport_is_persp_get();
@@ -302,8 +323,11 @@ static void eevee_render_result_mist(
if ((view_layer->passflag & SCE_PASS_MIST) != 0) {
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_MIST, viewname);
- DRW_framebuffer_bind(vedata->fbl->mist_accum_fb);
- DRW_framebuffer_read_data(rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), 1, 0, rp->rect);
+ GPU_framebuffer_bind(vedata->fbl->mist_accum_fb);
+ GPU_framebuffer_read_color(vedata->fbl->mist_accum_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ 1, 0, rp->rect);
/* This is the accumulated color. Divide by the number of samples. */
for (int i = 0; i < rp->rectx * rp->recty; i++) {
@@ -327,8 +351,11 @@ static void eevee_render_result_occlusion(
if ((view_layer->passflag & SCE_PASS_AO) != 0) {
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_AO, viewname);
- DRW_framebuffer_bind(vedata->fbl->ao_accum_fb);
- DRW_framebuffer_read_data(rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), 3, 0, rp->rect);
+ GPU_framebuffer_bind(vedata->fbl->ao_accum_fb);
+ GPU_framebuffer_read_color(vedata->fbl->ao_accum_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ 3, 0, rp->rect);
/* This is the accumulated color. Divide by the number of samples. */
for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) {
@@ -339,30 +366,34 @@ static void eevee_render_result_occlusion(
static void eevee_render_draw_background(EEVEE_Data *vedata)
{
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
EEVEE_PassList *psl = vedata->psl;
/* Prevent background to write to data buffers.
* NOTE : This also make sure the textures are bound
* to the right double buffer. */
- if (txl->ssr_normal_input != NULL) {
- DRW_framebuffer_texture_detach(txl->ssr_normal_input);
- }
- if (txl->ssr_specrough_input != NULL) {
- DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
- }
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_ensure_config(&fbl->main_fb, {
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_NONE
+ });
+ GPU_framebuffer_bind(fbl->main_fb);
DRW_draw_pass(psl->background_pass);
- if (txl->ssr_normal_input != NULL) {
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0);
- }
- if (txl->ssr_specrough_input != NULL) {
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
- }
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_ensure_config(&fbl->main_fb, {
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_TEXTURE(stl->effects->ssr_normal_input),
+ GPU_ATTACHMENT_TEXTURE(stl->effects->ssr_specrough_input),
+ GPU_ATTACHMENT_TEXTURE(stl->effects->sss_data),
+ GPU_ATTACHMENT_TEXTURE(stl->effects->sss_albedo)
+ });
+ GPU_framebuffer_bind(fbl->main_fb);
}
void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl, const rcti *rect)
@@ -413,6 +444,8 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
while (render_samples < tot_sample && !RE_engine_test_break(engine)) {
float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float clear_depth = 1.0f;
+ unsigned int clear_stencil = 0xFF;
unsigned int primes[3] = {2, 3, 7};
double offset[3] = {0.0, 0.0, 0.0};
double r[3];
@@ -455,10 +488,8 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
/* Refresh Shadows */
EEVEE_draw_shadows(sldata, psl);
- DRW_framebuffer_texture_detach(dtxl->depth);
- DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
- DRW_framebuffer_bind(fbl->main);
- DRW_framebuffer_clear(true, true, true, clear_col, 1.0f);
+ GPU_framebuffer_bind(fbl->main_fb);
+ GPU_framebuffer_clear_color_depth_stencil(fbl->main_fb, clear_col, clear_depth, clear_stencil);
/* Depth prepass */
DRW_draw_pass(psl->depth_pass);
DRW_draw_pass(psl->depth_pass_cull);
@@ -468,7 +499,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
EEVEE_volumes_compute(sldata, vedata);
/* Shading pass */
eevee_render_draw_background(vedata);
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
EEVEE_draw_default_passes(psl);
DRW_draw_pass(psl->material_pass);
EEVEE_subsurface_data_render(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index 96d560688f3..7a856870eb3 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -124,14 +124,15 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
const bool use_refraction = BKE_collection_engine_property_value_get_bool(props, "ssr_refraction");
if (use_refraction) {
- DRWFboTexture tex = {&txl->refract_color, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
+ /* TODO: Opti: Could be shared. */
+ DRW_texture_ensure_fullscreen_2D(&txl->refract_color, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP);
- DRW_framebuffer_init(&fbl->refract_fb, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex, 1);
+ GPU_framebuffer_ensure_config(&fbl->refract_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->refract_color)
+ });
}
- bool prev_trace_full = effects->reflection_trace_full;
effects->reflection_trace_full = !BKE_collection_engine_property_value_get_bool(props, "ssr_halfres");
common_data->ssr_thickness = BKE_collection_engine_property_value_get_float(props, "ssr_thickness");
common_data->ssr_border_fac = BKE_collection_engine_property_value_get_float(props, "ssr_border_fade");
@@ -144,47 +145,39 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
common_data->ssr_firefly_fac = FLT_MAX;
}
- if (prev_trace_full != effects->reflection_trace_full) {
- DRW_TEXTURE_FREE_SAFE(txl->ssr_hit_output);
- }
-
const int divisor = (effects->reflection_trace_full) ? 1 : 2;
int tracing_res[2] = {(int)viewport_size[0] / divisor, (int)viewport_size[1] / divisor};
+ int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]};
const bool high_qual_input = true; /* TODO dither low quality input */
+ const DRWTextureFormat format = (high_qual_input) ? DRW_TEX_RGBA_16 : DRW_TEX_RGBA_8;
/* MRT for the shading pass in order to output needed data for the SSR pass. */
- /* TODO create one texture layer per lobe */
- if (txl->ssr_specrough_input == NULL) {
- DRWTextureFormat specrough_format = (high_qual_input) ? DRW_TEX_RGBA_16 : DRW_TEX_RGBA_8;
- txl->ssr_specrough_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1],
- specrough_format, 0, NULL);
- }
+ effects->ssr_specrough_input = DRW_texture_pool_query_2D(size_fs[0], size_fs[1], format,
+ &draw_engine_eevee_type);
- /* Reattach textures to the right buffer (because we are alternating between buffers) */
- /* TODO multiple FBO per texture!!!! */
- DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
+ GPU_framebuffer_texture_attach(fbl->main_fb, effects->ssr_specrough_input, 2, 0);
/* Raytracing output */
- /* (AMD or Intel) For some reason DRW_TEX_TEMP with DRW_TEX_RG_16I
- * creates problems when toggling ssr_halfres. Texture is not read correctly (black output).
- * So using a persistent buffer instead. */
- DRWFboTexture tex_output[2] = {{&txl->ssr_hit_output, DRW_TEX_RG_16I, 0},
- {&stl->g_data->ssr_pdf_output, DRW_TEX_R_16, DRW_TEX_TEMP}};
+ effects->ssr_hit_output = DRW_texture_pool_query_2D(tracing_res[0], tracing_res[1], DRW_TEX_RG_16I,
+ &draw_engine_eevee_type);
+ effects->ssr_pdf_output = DRW_texture_pool_query_2D(tracing_res[0], tracing_res[1], DRW_TEX_R_16,
+ &draw_engine_eevee_type);
- DRW_framebuffer_init(&fbl->screen_tracing_fb, &draw_engine_eevee_type,
- tracing_res[0], tracing_res[1],
- tex_output, 2);
+ GPU_framebuffer_ensure_config(&fbl->screen_tracing_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->ssr_hit_output),
+ GPU_ATTACHMENT_TEXTURE(effects->ssr_pdf_output)
+ });
/* Enable double buffering to be able to read previous frame color */
return EFFECT_SSR | EFFECT_NORMAL_BUFFER | EFFECT_DOUBLE_BUFFER | ((use_refraction) ? EFFECT_REFRACT : 0);
}
/* Cleanup to release memory */
- DRW_TEXTURE_FREE_SAFE(txl->ssr_specrough_input);
- DRW_TEXTURE_FREE_SAFE(txl->ssr_hit_output);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->screen_tracing_fb);
- stl->g_data->ssr_pdf_output = NULL;
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->screen_tracing_fb);
+ effects->ssr_specrough_input = NULL;
+ effects->ssr_hit_output = NULL;
+ effects->ssr_pdf_output = NULL;
return 0;
}
@@ -221,8 +214,8 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
psl->ssr_raytrace = DRW_pass_create("SSR Raytrace", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(trace_shader, psl->ssr_raytrace);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
- DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
- DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input);
+ DRW_shgroup_uniform_buffer(grp, "normalBuffer", &effects->ssr_normal_input);
+ DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &effects->ssr_specrough_input);
DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_buffer(grp, "planarDepth", &vedata->txl->planar_depth);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
@@ -236,13 +229,13 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
psl->ssr_resolve = DRW_pass_create("SSR Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
grp = DRW_shgroup_create(resolve_shader, psl->ssr_resolve);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
- DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
- DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input);
+ DRW_shgroup_uniform_buffer(grp, "normalBuffer", &effects->ssr_normal_input);
+ DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &effects->ssr_specrough_input);
DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool);
DRW_shgroup_uniform_buffer(grp, "probePlanars", &vedata->txl->planar_pool);
DRW_shgroup_uniform_buffer(grp, "planarDepth", &vedata->txl->planar_depth);
- DRW_shgroup_uniform_buffer(grp, "hitBuffer", &vedata->txl->ssr_hit_output);
- DRW_shgroup_uniform_buffer(grp, "pdfBuffer", &stl->g_data->ssr_pdf_output);
+ DRW_shgroup_uniform_buffer(grp, "hitBuffer", &effects->ssr_hit_output);
+ DRW_shgroup_uniform_buffer(grp, "pdfBuffer", &effects->ssr_pdf_output);
DRW_shgroup_uniform_buffer(grp, "prevColorBuffer", &txl->color_double_buffer);
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
@@ -250,7 +243,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_int(grp, "neighborOffset", &effects->ssr_neighbor_ofs, 1);
if ((effects->enabled_effects & EFFECT_GTAO) != 0) {
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &vedata->txl->gtao_horizons);
+ DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &effects->gtao_horizons);
}
DRW_shgroup_call_add(grp, quad, NULL);
@@ -265,12 +258,11 @@ void EEVEE_refraction_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
EEVEE_EffectsInfo *effects = stl->effects;
if ((effects->enabled_effects & EFFECT_REFRACT) != 0) {
- DRW_framebuffer_texture_attach(fbl->refract_fb, txl->refract_color, 0, 0);
- DRW_framebuffer_blit(fbl->main, fbl->refract_fb, false, false);
- EEVEE_downsample_buffer(vedata, fbl->downsample_fb, txl->refract_color, 9);
+ GPU_framebuffer_blit(fbl->main_fb, 0, fbl->refract_fb, 0, GPU_COLOR_BIT);
+ EEVEE_downsample_buffer(vedata, txl->refract_color, 9);
/* Restore */
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
}
}
@@ -287,15 +279,12 @@ void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
e_data.depth_src = dtxl->depth;
DRW_stats_group_start("SSR");
- DRW_framebuffer_texture_attach(fbl->screen_tracing_fb, stl->g_data->ssr_pdf_output, 1, 0);
- DRW_framebuffer_bind(fbl->screen_tracing_fb);
/* Raytrace. */
+ GPU_framebuffer_bind(fbl->screen_tracing_fb);
DRW_draw_pass(psl->ssr_raytrace);
- DRW_framebuffer_texture_detach(stl->g_data->ssr_pdf_output);
-
- EEVEE_downsample_buffer(vedata, fbl->downsample_fb, txl->color_double_buffer, 9);
+ EEVEE_downsample_buffer(vedata, txl->color_double_buffer, 9);
/* Resolve at fullres */
int sample = (DRW_state_is_image_render()) ? effects->taa_render_sample : effects->taa_current_sample;
@@ -320,18 +309,11 @@ void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
effects->ssr_halfres_ofs[1] = 1;
break;
}
- DRW_framebuffer_texture_detach(dtxl->depth);
- DRW_framebuffer_texture_detach(txl->ssr_normal_input);
- DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_color_fb);
DRW_draw_pass(psl->ssr_resolve);
/* Restore */
- DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0);
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
- DRW_framebuffer_bind(fbl->main);
-
+ GPU_framebuffer_bind(fbl->main_fb);
DRW_stats_group_end();
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 12a70cc2fe7..510f1e8fdb6 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -66,6 +66,7 @@ int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
const float *viewport_size = DRW_viewport_size_get();
+ const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
@@ -90,36 +91,45 @@ int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
* as the depth buffer we are sampling from. This could be avoided if the stencil is
* a separate texture but that needs OpenGL 4.4 or ARB_texture_stencil8.
* OR OpenGL 4.3 / ARB_ES3_compatibility if using a renderbuffer instead */
- DRWFboTexture texs[2] = {{&txl->sss_stencil, DRW_TEX_DEPTH_24_STENCIL_8, 0},
- {&txl->sss_blur, DRW_TEX_RGBA_16, DRW_TEX_FILTER}};
-
- DRW_framebuffer_init(&fbl->sss_blur_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1],
- texs, 2);
-
- DRWFboTexture tex_data = {&txl->sss_data, DRW_TEX_RGBA_16, DRW_TEX_FILTER};
- DRW_framebuffer_init(&fbl->sss_clear_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1],
- &tex_data, 1);
+ effects->sss_stencil = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], DRW_TEX_DEPTH_24_STENCIL_8,
+ &draw_engine_eevee_type);
+ effects->sss_blur = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], DRW_TEX_RGBA_16,
+ &draw_engine_eevee_type);
+ effects->sss_data = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], DRW_TEX_RGBA_16,
+ &draw_engine_eevee_type);
+
+ GPU_framebuffer_ensure_config(&fbl->sss_blur_fb, {
+ GPU_ATTACHMENT_TEXTURE(effects->sss_stencil),
+ GPU_ATTACHMENT_TEXTURE(effects->sss_blur)
+ });
+
+ GPU_framebuffer_ensure_config(&fbl->sss_resolve_fb, {
+ GPU_ATTACHMENT_TEXTURE(effects->sss_stencil),
+ GPU_ATTACHMENT_TEXTURE(txl->color)
+ });
+
+ GPU_framebuffer_ensure_config(&fbl->sss_clear_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->sss_data)
+ });
if (effects->sss_separate_albedo) {
- if (txl->sss_albedo == NULL) {
- txl->sss_albedo = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1],
- DRW_TEX_RGB_11_11_10, 0, NULL);
- }
+ effects->sss_albedo = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], DRW_TEX_RGB_11_11_10,
+ &draw_engine_eevee_type);
}
else {
- /* Cleanup to release memory */
- DRW_TEXTURE_FREE_SAFE(txl->sss_albedo);
+ effects->sss_albedo = NULL;
}
return EFFECT_SSS;
}
/* Cleanup to release memory */
- DRW_TEXTURE_FREE_SAFE(txl->sss_albedo);
- DRW_TEXTURE_FREE_SAFE(txl->sss_data);
- DRW_TEXTURE_FREE_SAFE(txl->sss_blur);
- DRW_TEXTURE_FREE_SAFE(txl->sss_stencil);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->sss_blur_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_blur_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_resolve_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb);
+ effects->sss_stencil = NULL;
+ effects->sss_blur = NULL;
+ effects->sss_data = NULL;
return 0;
}
@@ -133,23 +143,27 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
{
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
- const float *viewport_size = DRW_viewport_size_get();
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
if (BKE_collection_engine_property_value_get_bool(props, "sss_enable")) {
- float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ DRW_texture_ensure_fullscreen_2D(&txl->sss_dir_accum, DRW_TEX_RGBA_16, 0);
+ DRW_texture_ensure_fullscreen_2D(&txl->sss_col_accum, DRW_TEX_RGBA_16, 0);
- DRWFboTexture tex_data[2] = {{&txl->sss_dir_accum, DRW_TEX_RGBA_16, 0},
- {&txl->sss_col_accum, DRW_TEX_RGBA_16, 0}};
- DRW_framebuffer_init(&fbl->sss_accum_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1],
- tex_data, 2);
+ GPU_framebuffer_ensure_config(&fbl->sss_accum_fb, {
+ GPU_ATTACHMENT_TEXTURE(effects->sss_stencil),
+ GPU_ATTACHMENT_TEXTURE(txl->sss_dir_accum),
+ GPU_ATTACHMENT_TEXTURE(txl->sss_col_accum)
+ });
/* Clear texture. */
- DRW_framebuffer_bind(fbl->sss_accum_fb);
- DRW_framebuffer_clear(true, false, false, clear, 0.0f);
+ float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ GPU_framebuffer_bind(fbl->sss_accum_fb);
+ GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear);
/* Make the opaque refraction pass mask the sss. */
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
@@ -161,7 +175,7 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
/* Cleanup to release memory */
DRW_TEXTURE_FREE_SAFE(txl->sss_dir_accum);
DRW_TEXTURE_FREE_SAFE(txl->sss_col_accum);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb);
}
}
@@ -187,7 +201,6 @@ void EEVEE_subsurface_add_pass(
EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile)
{
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
@@ -196,7 +209,7 @@ void EEVEE_subsurface_add_pass(
DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_data);
+ DRW_shgroup_uniform_buffer(grp, "sssData", &effects->sss_data);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
@@ -206,22 +219,22 @@ void EEVEE_subsurface_add_pass(
grp = DRW_shgroup_create(sh, psl->sss_resolve_ps);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_blur);
+ DRW_shgroup_uniform_buffer(grp, "sssData", &effects->sss_blur);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
DRW_shgroup_call_add(grp, quad, NULL);
if (effects->sss_separate_albedo) {
- DRW_shgroup_uniform_buffer(grp, "sssAlbedo", &txl->sss_albedo);
+ DRW_shgroup_uniform_buffer(grp, "sssAlbedo", &effects->sss_albedo);
}
if (DRW_state_is_image_render()) {
grp = DRW_shgroup_create(e_data.sss_sh[3], psl->sss_accum_ps);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_blur);
- DRW_shgroup_uniform_buffer(grp, "sssAlbedo", &txl->sss_albedo);
+ DRW_shgroup_uniform_buffer(grp, "sssData", &effects->sss_blur);
+ DRW_shgroup_uniform_buffer(grp, "sssAlbedo", &effects->sss_albedo);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
@@ -232,7 +245,6 @@ void EEVEE_subsurface_add_pass(
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
@@ -240,103 +252,60 @@ void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
if ((effects->enabled_effects & EFFECT_SSS) != 0) {
float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
/* Clear sss_data texture only... can this be done in a more clever way? */
- DRW_framebuffer_bind(fbl->sss_clear_fb);
- DRW_framebuffer_clear(true, false, false, clear, 0.0f);
-
-
- DRW_framebuffer_texture_detach(txl->sss_data);
- if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
- DRW_framebuffer_texture_detach(txl->ssr_normal_input);
- }
- if ((effects->enabled_effects & EFFECT_SSR) != 0) {
- DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
- }
-
- /* Start at slot 1 because slot 0 is txl->color */
- int tex_slot = 1;
- DRW_framebuffer_texture_attach(fbl->main, txl->sss_data, tex_slot++, 0);
- if (effects->sss_separate_albedo) {
- DRW_framebuffer_texture_attach(fbl->main, txl->sss_albedo, tex_slot++, 0);
- }
- if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, tex_slot++, 0);
- }
- if ((effects->enabled_effects & EFFECT_SSR) != 0) {
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, tex_slot++, 0);
- }
- DRW_framebuffer_bind(fbl->main);
-
+ GPU_framebuffer_bind(fbl->sss_clear_fb);
+ GPU_framebuffer_clear_color(fbl->sss_clear_fb, clear);
+
+ GPU_framebuffer_ensure_config(&fbl->main_fb, {
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_TEXTURE(effects->sss_data),
+ GPU_ATTACHMENT_TEXTURE(effects->sss_albedo)
+ });
+
+ GPU_framebuffer_bind(fbl->main_fb);
DRW_draw_pass(psl->sss_pass);
/* Restore */
- DRW_framebuffer_texture_detach(txl->sss_data);
- if (effects->sss_separate_albedo) {
- DRW_framebuffer_texture_detach(txl->sss_albedo);
- }
- if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
- DRW_framebuffer_texture_detach(txl->ssr_normal_input);
- }
- if ((effects->enabled_effects & EFFECT_SSR) != 0) {
- DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
- }
-
- DRW_framebuffer_texture_attach(fbl->sss_clear_fb, txl->sss_data, 0, 0);
- if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0);
- }
- if ((effects->enabled_effects & EFFECT_SSR) != 0) {
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
- }
+ GPU_framebuffer_ensure_config(&fbl->main_fb, {
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_LEAVE,
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_NONE
+ });
}
}
void EEVEE_subsurface_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
- EEVEE_FramebufferList *fbl = vedata->fbl;
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_EffectsInfo *effects = stl->effects;
if ((effects->enabled_effects & EFFECT_SSS) != 0) {
float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
DRW_stats_group_start("SSS");
/* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
- DRW_framebuffer_blit(fbl->main, fbl->sss_blur_fb, false, true);
-
- DRW_framebuffer_texture_detach(dtxl->depth);
+ GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blur_fb, 0, GPU_STENCIL_BIT);
/* 1. horizontal pass */
- DRW_framebuffer_bind(fbl->sss_blur_fb);
- DRW_framebuffer_clear(true, false, false, clear, 0.0f);
+ GPU_framebuffer_bind(fbl->sss_blur_fb);
+ GPU_framebuffer_clear_color(fbl->sss_blur_fb, clear);
DRW_draw_pass(psl->sss_blur_ps);
/* 2. vertical pass + Resolve */
- DRW_framebuffer_texture_detach(txl->sss_stencil);
- if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
- DRW_framebuffer_texture_detach(txl->ssr_normal_input);
- }
- if ((effects->enabled_effects & EFFECT_SSR) != 0) {
- DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
- }
- DRW_framebuffer_texture_attach(fbl->main, txl->sss_stencil, 0, 0);
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_texture_attach(fbl->sss_resolve_fb, txl->color, 0, 0);
+ GPU_framebuffer_bind(fbl->sss_resolve_fb);
DRW_draw_pass(psl->sss_resolve_ps);
- /* Restore */
- DRW_framebuffer_texture_detach(txl->sss_stencil);
- DRW_framebuffer_texture_attach(fbl->sss_blur_fb, txl->sss_stencil, 0, 0);
- DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
- if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0);
- }
- if ((effects->enabled_effects & EFFECT_SSR) != 0) {
- DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
- }
-
+ GPU_framebuffer_bind(fbl->main_fb);
DRW_stats_group_end();
}
}
@@ -345,24 +314,19 @@ void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEV
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_FramebufferList *fbl = vedata->fbl;
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
if (((effects->enabled_effects & EFFECT_SSS) != 0) && (fbl->sss_accum_fb != NULL)) {
/* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
- DRW_framebuffer_blit(fbl->main, fbl->sss_blur_fb, false, true);
+ GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blur_fb, 0, GPU_STENCIL_BIT);
/* Only do vertical pass + Resolve */
- DRW_framebuffer_texture_detach(txl->sss_stencil);
- DRW_framebuffer_texture_attach(fbl->sss_accum_fb, txl->sss_stencil, 0, 0);
- DRW_framebuffer_bind(fbl->sss_accum_fb);
+ GPU_framebuffer_bind(fbl->sss_accum_fb);
DRW_draw_pass(psl->sss_accum_ps);
/* Restore */
- DRW_framebuffer_texture_detach(txl->sss_stencil);
- DRW_framebuffer_texture_attach(fbl->sss_blur_fb, txl->sss_stencil, 0, 0);
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index a417a9bdf56..25dbf4d4802 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -179,7 +179,6 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
(effects->enabled_effects & EFFECT_MOTION_BLUR) == 0) ||
DRW_state_is_image_render())
{
- const float *viewport_size = DRW_viewport_size_get();
float persmat[4][4], viewmat[4][4];
if (!e_data.taa_resolve_sh) {
@@ -239,11 +238,11 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
effects->taa_current_sample = 1;
}
- DRWFboTexture tex_double_buffer = {&txl->depth_double_buffer, DRW_TEX_DEPTH_24_STENCIL_8, 0};
+ DRW_texture_ensure_fullscreen_2D(&txl->depth_double_buffer, DRW_TEX_DEPTH_24_STENCIL_8, 0);
- DRW_framebuffer_init(&fbl->depth_double_buffer_fb, &draw_engine_eevee_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &tex_double_buffer, 1);
+ GPU_framebuffer_ensure_config(&fbl->double_buffer_depth_fb, {
+ GPU_ATTACHMENT_TEXTURE(txl->depth_double_buffer)
+ });
return EFFECT_TAA | EFFECT_DOUBLE_BUFFER | EFFECT_POST_BUFFER;
}
@@ -252,7 +251,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
/* Cleanup to release memory */
DRW_TEXTURE_FREE_SAFE(txl->depth_double_buffer);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->depth_double_buffer_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer_depth_fb);
return 0;
}
@@ -293,27 +292,28 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
effects->taa_alpha = 1.0f / (float)(effects->taa_current_sample);
}
- DRW_framebuffer_bind(fbl->effect_fb);
+ GPU_framebuffer_bind(fbl->effect_color_fb);
DRW_draw_pass(psl->taa_resolve);
/* Restore the depth from sample 1. */
if (!DRW_state_is_image_render()) {
- DRW_framebuffer_blit(fbl->depth_double_buffer_fb, fbl->main, true, false);
+ GPU_framebuffer_blit(fbl->double_buffer_depth_fb, 0, fbl->main_fb, 0, GPU_DEPTH_BIT);
}
/* Special Swap */
- SWAP(struct GPUFrameBuffer *, fbl->effect_fb, fbl->double_buffer);
+ SWAP(struct GPUFrameBuffer *, fbl->effect_fb, fbl->double_buffer_fb);
+ SWAP(struct GPUFrameBuffer *, fbl->effect_color_fb, fbl->double_buffer_color_fb);
SWAP(GPUTexture *, txl->color_post, txl->color_double_buffer);
effects->swap_double_buffer = false;
effects->source_buffer = txl->color_double_buffer;
- effects->target_buffer = fbl->main;
+ effects->target_buffer = fbl->main_fb;
}
else {
/* Save the depth buffer for the next frame.
* This saves us from doing anything special
* in the other mode engines. */
if (!DRW_state_is_image_render()) {
- DRW_framebuffer_blit(fbl->main, fbl->depth_double_buffer_fb, true, false);
+ GPU_framebuffer_blit(fbl->main_fb, 0, fbl->double_buffer_depth_fb, 0, GPU_DEPTH_BIT);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 85b168d1075..11ad4cae398 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -195,9 +195,9 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
common_data->vol_tex_size[0] = tex_size[0];
common_data->vol_tex_size[1] = tex_size[1];
common_data->vol_tex_size[2] = tex_size[2];
@@ -268,28 +268,23 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
EEVEE_volumes_set_jitter(sldata, current_sample);
/* Framebuffer setup */
- DRWFboTexture tex_vol[4] = {{&txl->volume_prop_scattering, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
- {&txl->volume_prop_extinction, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
- {&txl->volume_prop_emission, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
- {&txl->volume_prop_phase, DRW_TEX_RG_16, DRW_TEX_FILTER}};
-
- DRW_framebuffer_init(&fbl->volumetric_fb, &draw_engine_eevee_type,
- (int)tex_size[0], (int)tex_size[1],
- tex_vol, 4);
-
- DRWFboTexture tex_vol_scat[2] = {{&txl->volume_scatter, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
- {&txl->volume_transmittance, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}};
-
- DRW_framebuffer_init(&fbl->volumetric_scat_fb, &draw_engine_eevee_type,
- (int)tex_size[0], (int)tex_size[1],
- tex_vol_scat, 2);
-
- DRWFboTexture tex_vol_integ[2] = {{&txl->volume_scatter_history, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
- {&txl->volume_transmittance_history, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}};
-
- DRW_framebuffer_init(&fbl->volumetric_integ_fb, &draw_engine_eevee_type,
- (int)tex_size[0], (int)tex_size[1],
- tex_vol_integ, 2);
+ GPU_framebuffer_ensure_config(&fbl->volumetric_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->volume_prop_scattering),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_prop_extinction),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_prop_emission),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_prop_phase)
+ });
+ GPU_framebuffer_ensure_config(&fbl->volumetric_scat_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->volume_scatter),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance)
+ });
+ GPU_framebuffer_ensure_config(&fbl->volumetric_integ_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_history),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance_history)
+ });
float integration_start = BKE_collection_engine_property_value_get_float(props, "volumetric_start");
float integration_end = BKE_collection_engine_property_value_get_float(props, "volumetric_end");
@@ -345,9 +340,9 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
- DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
return 0;
}
@@ -530,16 +525,16 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
DRW_stats_group_start("Volumetrics");
/* Step 1: Participating Media Properties */
- DRW_framebuffer_bind(fbl->volumetric_fb);
+ GPU_framebuffer_bind(fbl->volumetric_fb);
DRW_draw_pass(psl->volumetric_world_ps);
DRW_draw_pass(psl->volumetric_objects_ps);
/* Step 2: Scatter Light */
- DRW_framebuffer_bind(fbl->volumetric_scat_fb);
+ GPU_framebuffer_bind(fbl->volumetric_scat_fb);
DRW_draw_pass(psl->volumetric_scatter_ps);
/* Step 3: Integration */
- DRW_framebuffer_bind(fbl->volumetric_integ_fb);
+ GPU_framebuffer_bind(fbl->volumetric_integ_fb);
DRW_draw_pass(psl->volumetric_integration_ps);
/* Swap volume history buffers */
@@ -548,7 +543,7 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
SWAP(GPUTexture *, txl->volume_transmittance, txl->volume_transmittance_history);
/* Restore */
- DRW_framebuffer_bind(fbl->main);
+ GPU_framebuffer_bind(fbl->main_fb);
DRW_stats_group_end();
}
@@ -569,14 +564,14 @@ void EEVEE_volumes_resolve(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
e_data.depth_src = dtxl->depth;
/* Step 4: Apply for opaque */
- DRW_framebuffer_bind(fbl->effect_fb);
+ GPU_framebuffer_bind(fbl->effect_color_fb);
DRW_draw_pass(psl->volumetric_resolve_ps);
/* Swap the buffers and rebind depth to the current buffer */
- DRW_framebuffer_texture_detach(dtxl->depth);
- SWAP(struct GPUFrameBuffer *, fbl->main, fbl->effect_fb);
+ SWAP(GPUFrameBuffer *, fbl->main_fb, fbl->effect_fb);
+ SWAP(GPUFrameBuffer *, fbl->main_color_fb, fbl->effect_color_fb);
SWAP(GPUTexture *, txl->color, txl->color_post);
- DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
+ GPU_framebuffer_texture_attach(fbl->main_fb, dtxl->depth, 0, 0);
}
}
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index 23487e66a17..1fba69ffa51 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -760,20 +760,13 @@ Closure closure_add(Closure cl1, Closure cl2)
# if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER) && !defined(USE_MULTIPLY)
layout(location = 0) out vec4 fragColor;
+layout(location = 1) out vec4 ssrNormals;
+layout(location = 2) out vec4 ssrData;
# ifdef USE_SSS
+layout(location = 3) out vec4 sssData;
# ifdef USE_SSS_ALBEDO
-layout(location = 1) out vec4 sssData;
-layout(location = 2) out vec4 sssAlbedo;
-layout(location = 3) out vec4 ssrNormals;
-layout(location = 4) out vec4 ssrData;
-# else
-layout(location = 1) out vec4 sssData;
-layout(location = 2) out vec4 ssrNormals;
-layout(location = 3) out vec4 ssrData;
+layout(location = 4) out vec4 sssAlbedo;
# endif /* USE_SSS_ALBEDO */
-# else
-layout(location = 1) out vec4 ssrNormals;
-layout(location = 2) out vec4 ssrData;
# endif /* USE_SSS */
Closure nodetree_exec(void); /* Prototype */
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 3334579a7cd..e60ce6c391b 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -45,6 +45,8 @@
#include "DNA_material_types.h"
#include "DNA_scene_types.h"
+#include "GPU_framebuffer.h"
+
#include "draw_common.h"
#include "draw_cache.h"
#include "draw_view.h"
@@ -100,9 +102,8 @@ typedef char DRWViewportEmptyList;
#define MULTISAMPLE_SYNC_ENABLE(dfbl) { \
if (dfbl->multisample_fb != NULL) { \
DRW_stats_query_start("Multisample Blit"); \
- DRW_framebuffer_blit(dfbl->default_fb, dfbl->multisample_fb, false, false); \
- DRW_framebuffer_blit(dfbl->default_fb, dfbl->multisample_fb, true, false); \
- DRW_framebuffer_bind(dfbl->multisample_fb); \
+ GPU_framebuffer_blit(dfbl->default_fb, 0, dfbl->multisample_fb, 0, GPU_COLOR_BIT | GPU_DEPTH_BIT); \
+ GPU_framebuffer_bind(dfbl->multisample_fb); \
DRW_stats_query_end(); \
} \
}
@@ -110,9 +111,8 @@ typedef char DRWViewportEmptyList;
#define MULTISAMPLE_SYNC_DISABLE(dfbl) { \
if (dfbl->multisample_fb != NULL) { \
DRW_stats_query_start("Multisample Resolve"); \
- DRW_framebuffer_blit(dfbl->multisample_fb, dfbl->default_fb, false, false); \
- DRW_framebuffer_blit(dfbl->multisample_fb, dfbl->default_fb, true, false); \
- DRW_framebuffer_bind(dfbl->default_fb); \
+ GPU_framebuffer_blit(dfbl->multisample_fb, 0, dfbl->default_fb, 0, GPU_COLOR_BIT | GPU_DEPTH_BIT); \
+ GPU_framebuffer_bind(dfbl->default_fb); \
DRW_stats_query_end(); \
} \
}
@@ -153,6 +153,8 @@ typedef struct DrawEngineType {
/* Buffer and textures used by the viewport by default */
typedef struct DefaultFramebufferList {
struct GPUFrameBuffer *default_fb;
+ struct GPUFrameBuffer *color_only_fb;
+ struct GPUFrameBuffer *depth_only_fb;
struct GPUFrameBuffer *multisample_fb;
} DefaultFramebufferList;
@@ -195,9 +197,13 @@ typedef enum {
DRW_TEX_WRAP = (1 << 1),
DRW_TEX_COMPARE = (1 << 2),
DRW_TEX_MIPMAP = (1 << 3),
- DRW_TEX_TEMP = (1 << 4),
} DRWTextureFlag;
+/* Textures from DRW_texture_pool_query_* have the options
+ * DRW_TEX_FILTER for color float textures, and no options
+ * for depth textures and integer textures. */
+struct GPUTexture *DRW_texture_pool_query_2D(int w, int h, DRWTextureFormat format, DrawEngineType *engine_type);
+
struct GPUTexture *DRW_texture_create_1D(
int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
struct GPUTexture *DRW_texture_create_2D(
@@ -208,6 +214,12 @@ struct GPUTexture *DRW_texture_create_3D(
int w, int h, int d, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
struct GPUTexture *DRW_texture_create_cube(
int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
+
+void DRW_texture_ensure_fullscreen_2D(
+ struct GPUTexture **tex, DRWTextureFormat format, DRWTextureFlag flags);
+void DRW_texture_ensure_2D(
+ struct GPUTexture **tex, int w, int h, DRWTextureFormat format, DRWTextureFlag flags);
+
void DRW_texture_generate_mipmaps(struct GPUTexture *tex);
void DRW_texture_free(struct GPUTexture *tex);
#define DRW_TEXTURE_FREE_SAFE(tex) do { \
@@ -228,40 +240,6 @@ void DRW_uniformbuffer_free(struct GPUUniformBuffer *ubo);
} \
} while (0)
-/* Buffers */
-#define MAX_FBO_TEX 5
-
-typedef struct DRWFboTexture {
- struct GPUTexture **tex;
- int format;
- DRWTextureFlag flag;
-} DRWFboTexture;
-
-struct GPUFrameBuffer *DRW_framebuffer_create(void);
-void DRW_framebuffer_init(
- struct GPUFrameBuffer **fb, void *engine_type, int width, int height,
- DRWFboTexture textures[MAX_FBO_TEX], int textures_len);
-void DRW_framebuffer_bind(struct GPUFrameBuffer *fb);
-void DRW_framebuffer_clear(bool color, bool depth, bool stencil, float clear_col[4], float clear_depth);
-void DRW_framebuffer_read_data(int x, int y, int w, int h, int channels, int slot, float *data);
-void DRW_framebuffer_read_depth(int x, int y, int w, int h, float *data);
-void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip);
-void DRW_framebuffer_texture_layer_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip);
-void DRW_framebuffer_cubeface_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip);
-void DRW_framebuffer_texture_detach(struct GPUTexture *tex);
-void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth, bool stencil);
-void DRW_framebuffer_recursive_downsample(
- struct GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
- void (*callback)(void *userData, int level), void *userData);
-void DRW_framebuffer_viewport_size(struct GPUFrameBuffer *fb_read, int x, int y, int w, int h);
-void DRW_framebuffer_free(struct GPUFrameBuffer *fb);
-#define DRW_FRAMEBUFFER_FREE_SAFE(fb) do { \
- if (fb != NULL) { \
- DRW_framebuffer_free(fb); \
- fb = NULL; \
- } \
-} while (0)
-
void DRW_transform_to_display(struct GPUTexture *tex);
/* Shaders */
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 8377d212788..2b64eabe332 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -744,6 +744,10 @@ static void drw_engines_draw_scene(void)
if (engine->draw_scene) {
DRW_stats_group_start(engine->idname);
engine->draw_scene(data);
+ /* Restore for next engine */
+ if (DRW_state_is_fbo()) {
+ GPU_framebuffer_bind(DST.default_framebuffer);
+ }
DRW_stats_group_end();
}
@@ -1126,6 +1130,9 @@ void DRW_draw_render_loop_ex(
/* Update ubos */
DRW_globals_update();
+ /* No framebuffer allowed before drawing. */
+ BLI_assert(GPU_framebuffer_current_get() == 0);
+
/* Init engines */
drw_engines_init();
@@ -1152,6 +1159,8 @@ void DRW_draw_render_loop_ex(
DRW_stats_begin();
+ GPU_framebuffer_bind(DST.default_framebuffer);
+
/* Start Drawing */
DRW_state_reset();
@@ -1217,6 +1226,8 @@ void DRW_draw_render_loop_ex(
glEnable(GL_DEPTH_TEST);
}
+ GPU_framebuffer_restore();
+
DRW_state_reset();
drw_engines_disable();
@@ -1262,6 +1273,8 @@ void DRW_draw_render_loop_offscreen(
}
}
+ GPU_framebuffer_restore();
+
/* Reset before using it. */
memset(&DST, 0x0, offsetof(DRWManager, ogl_context));
DST.options.is_image_render = true;
@@ -1461,11 +1474,6 @@ void DRW_draw_select_loop(
DST.viewport = viewport;
v3d->zbuf = true;
- /* Setup framebuffer */
- draw_select_framebuffer_setup(rect);
- GPU_framebuffer_bind(g_select_buffer.framebuffer);
- DRW_framebuffer_clear(false, true, false, NULL, 1.0f);
-
DST.options.is_select = true;
/* Get list of enabled engines */
@@ -1519,6 +1527,11 @@ void DRW_draw_select_loop(
DRW_render_instance_buffer_finish();
}
+ /* Setup framebuffer */
+ draw_select_framebuffer_setup(rect);
+ GPU_framebuffer_bind(g_select_buffer.framebuffer);
+ GPU_framebuffer_clear_depth(g_select_buffer.framebuffer, 1.0f);
+
/* Start Drawing */
DRW_state_reset();
DRW_draw_callbacks_pre_scene();
@@ -1628,7 +1641,7 @@ void DRW_draw_depth_loop(
/* Setup framebuffer */
draw_select_framebuffer_setup(&ar->winrct);
GPU_framebuffer_bind(g_select_buffer.framebuffer);
- DRW_framebuffer_clear(false, true, false, NULL, 1.0f);
+ GPU_framebuffer_clear_depth(g_select_buffer.framebuffer, 1.0f);
bool cache_is_dirty;
DST.viewport = viewport;
@@ -1918,7 +1931,7 @@ void DRW_engines_free(void)
DRW_opengl_context_enable();
DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth);
- DRW_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer);
+ GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer);
DRW_shape_cache_free();
DRW_stats_free();
diff --git a/source/blender/draw/intern/draw_manager_framebuffer.c b/source/blender/draw/intern/draw_manager_framebuffer.c
deleted file mode 100644
index a76b1c42a53..00000000000
--- a/source/blender/draw/intern/draw_manager_framebuffer.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2016, Blender Foundation.
- *
- * 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.
- *
- * Contributor(s): Blender Institute
- *
- */
-
-/** \file blender/draw/intern/draw_manager_framebuffer.c
- * \ingroup draw
- */
-
-#include "draw_manager.h"
-
-GPUFrameBuffer *DRW_framebuffer_create(void)
-{
- return GPU_framebuffer_create();
-}
-
-void DRW_framebuffer_init(
- GPUFrameBuffer **fb, void *engine_type, int width, int height,
- DRWFboTexture textures[MAX_FBO_TEX], int textures_len)
-{
- BLI_assert(textures_len <= MAX_FBO_TEX);
- BLI_assert(width > 0 && height > 0);
-
- bool create_fb = false;
- int color_attachment = -1;
-
- if (!*fb) {
- *fb = GPU_framebuffer_create();
- create_fb = true;
- }
-
- for (int i = 0; i < textures_len; ++i) {
- int channels;
- bool is_depth;
- bool create_tex = false;
- GPUTextureFormat gpu_format;
-
- DRWFboTexture fbotex = textures[i];
- bool is_temp = (fbotex.flag & DRW_TEX_TEMP) != 0;
-
- drw_texture_get_format(fbotex.format, true, &gpu_format, &channels, &is_depth);
-
- if (!*fbotex.tex || is_temp) {
- /* Temp textures need to be queried each frame, others not. */
- if (is_temp) {
- *fbotex.tex = GPU_viewport_texture_pool_query(
- DST.viewport, engine_type, width, height, channels, gpu_format);
- }
- else {
- *fbotex.tex = GPU_texture_create_2D_custom(
- width, height, channels, gpu_format, NULL, NULL);
- create_tex = true;
- }
- }
-
- if (!is_depth) {
- ++color_attachment;
- }
-
- if (create_fb || create_tex) {
- drw_texture_set_parameters(*fbotex.tex, fbotex.flag);
- GPU_framebuffer_texture_attach(*fb, *fbotex.tex, color_attachment, 0);
- }
- }
-
- if (create_fb && (textures_len > 0)) {
- if (!GPU_framebuffer_check_valid(*fb, NULL)) {
- printf("Error invalid framebuffer\n");
- }
-
- /* Detach temp textures */
- for (int i = 0; i < textures_len; ++i) {
- DRWFboTexture fbotex = textures[i];
-
- if ((fbotex.flag & DRW_TEX_TEMP) != 0) {
- GPU_framebuffer_texture_detach(*fbotex.tex);
- }
- }
-
- if (DST.default_framebuffer != NULL) {
- GPU_framebuffer_bind(DST.default_framebuffer);
- }
- }
-}
-
-void DRW_framebuffer_free(GPUFrameBuffer *fb)
-{
- GPU_framebuffer_free(fb);
-}
-
-void DRW_framebuffer_bind(GPUFrameBuffer *fb)
-{
- GPU_framebuffer_bind(fb);
-}
-
-void DRW_framebuffer_clear(bool color, bool depth, bool stencil, float clear_col[4], float clear_depth)
-{
- if (color) {
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]);
- }
- if (depth) {
- glDepthMask(GL_TRUE);
- glClearDepth(clear_depth);
- }
- if (stencil) {
- glStencilMask(0xFF);
- }
- glClear(((color) ? GL_COLOR_BUFFER_BIT : 0) |
- ((depth) ? GL_DEPTH_BUFFER_BIT : 0) |
- ((stencil) ? GL_STENCIL_BUFFER_BIT : 0));
-}
-
-void DRW_framebuffer_read_data(int x, int y, int w, int h, int channels, int slot, float *data)
-{
- GLenum type;
- switch (channels) {
- case 1: type = GL_RED; break;
- case 2: type = GL_RG; break;
- case 3: type = GL_RGB; break;
- case 4: type = GL_RGBA; break;
- default:
- BLI_assert(false && "wrong number of read channels");
- return;
- }
- glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
- glReadPixels(x, y, w, h, type, GL_FLOAT, data);
-}
-
-void DRW_framebuffer_read_depth(int x, int y, int w, int h, float *data)
-{
- GLenum type = GL_DEPTH_COMPONENT;
-
- glReadBuffer(GL_COLOR_ATTACHMENT0); /* This is OK! */
- glReadPixels(x, y, w, h, type, GL_FLOAT, data);
-}
-
-void DRW_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
-{
- GPU_framebuffer_texture_attach(fb, tex, slot, mip);
-}
-
-void DRW_framebuffer_texture_layer_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
-{
- GPU_framebuffer_texture_layer_attach(fb, tex, slot, layer, mip);
-}
-
-void DRW_framebuffer_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip)
-{
- GPU_framebuffer_texture_cubeface_attach(fb, tex, slot, face, mip);
-}
-
-void DRW_framebuffer_texture_detach(GPUTexture *tex)
-{
- GPU_framebuffer_texture_detach(tex);
-}
-
-void DRW_framebuffer_blit(GPUFrameBuffer *fb_read, GPUFrameBuffer *fb_write, bool depth, bool stencil)
-{
- GPU_framebuffer_blit(fb_read, 0, fb_write, 0, depth, stencil);
-}
-
-void DRW_framebuffer_recursive_downsample(
- GPUFrameBuffer *fb, GPUTexture *tex, int num_iter,
- void (*callback)(void *userData, int level), void *userData)
-{
- GPU_framebuffer_recursive_downsample(fb, tex, num_iter, callback, userData);
-}
-
-void DRW_framebuffer_viewport_size(GPUFrameBuffer *UNUSED(fb_read), int x, int y, int w, int h)
-{
- glViewport(x, y, w, h);
-}
diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c
index 3a258954dbd..65856a6bf5c 100644
--- a/source/blender/draw/intern/draw_manager_texture.c
+++ b/source/blender/draw/intern/draw_manager_texture.c
@@ -197,6 +197,33 @@ GPUTexture *DRW_texture_create_cube(int w, DRWTextureFormat format, DRWTextureFl
return tex;
}
+GPUTexture *DRW_texture_pool_query_2D(int w, int h, DRWTextureFormat format, DrawEngineType *engine_type)
+{
+ GPUTexture *tex;
+ GPUTextureFormat data_type;
+ int channels;
+
+ drw_texture_get_format(format, true, &data_type, &channels, NULL);
+ tex = GPU_viewport_texture_pool_query(DST.viewport, engine_type, w, h, channels, data_type);
+
+ return tex;
+}
+
+void DRW_texture_ensure_fullscreen_2D(GPUTexture **tex, DRWTextureFormat format, DRWTextureFlag flags)
+{
+ if (*(tex) == NULL) {
+ const float *size = DRW_viewport_size_get();
+ *(tex) = DRW_texture_create_2D((int)size[0], (int)size[1], format, flags, NULL);
+ }
+}
+
+void DRW_texture_ensure_2D(GPUTexture **tex, int w, int h, DRWTextureFormat format, DRWTextureFlag flags)
+{
+ if (*(tex) == NULL) {
+ *(tex) = DRW_texture_create_2D(w, h, format, flags, NULL);
+ }
+}
+
void DRW_texture_generate_mipmaps(GPUTexture *tex)
{
GPU_texture_bind(tex, 0);
diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c
index cc1373dc29f..51b8eca9148 100644
--- a/source/blender/draw/modes/edit_mesh_mode.c
+++ b/source/blender/draw/modes/edit_mesh_mode.c
@@ -137,15 +137,17 @@ static void EDIT_MESH_engine_init(void *vedata)
EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl;
const float *viewport_size = DRW_viewport_size_get();
+ const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
- DRWFboTexture tex[2] = {{
- &e_data.occlude_wire_depth_tx, DRW_TEX_DEPTH_24, DRW_TEX_TEMP},
- {&e_data.occlude_wire_color_tx, DRW_TEX_RGBA_8, DRW_TEX_FILTER | DRW_TEX_TEMP}
- };
- DRW_framebuffer_init(
- &fbl->occlude_wire_fb, &draw_engine_edit_mesh_type,
- (int)viewport_size[0], (int)viewport_size[1],
- tex, ARRAY_SIZE(tex));
+ e_data.occlude_wire_depth_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_DEPTH_24,
+ &draw_engine_edit_mesh_type);
+ e_data.occlude_wire_color_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_RGBA_8,
+ &draw_engine_edit_mesh_type);
+
+ GPU_framebuffer_ensure_config(&fbl->occlude_wire_fb, {
+ GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_depth_tx),
+ GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_color_tx)
+ });
if (!e_data.vcolor_face_shader) {
e_data.vcolor_face_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA);
@@ -523,7 +525,6 @@ static void EDIT_MESH_draw_scene(void *vedata)
EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl;
EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
DRW_draw_pass(psl->vcolor_faces);
@@ -534,29 +535,15 @@ static void EDIT_MESH_draw_scene(void *vedata)
/* render facefill */
DRW_draw_pass(psl->facefill_occlude);
- /* attach temp textures */
- DRW_framebuffer_texture_attach(fbl->occlude_wire_fb, e_data.occlude_wire_depth_tx, 0, 0);
- DRW_framebuffer_texture_attach(fbl->occlude_wire_fb, e_data.occlude_wire_color_tx, 0, 0);
-
/* Render wires on a separate framebuffer */
- DRW_framebuffer_bind(fbl->occlude_wire_fb);
- DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
+ GPU_framebuffer_bind(fbl->occlude_wire_fb);
+ GPU_framebuffer_clear_color_depth(fbl->occlude_wire_fb, clearcol, 1.0f);
DRW_draw_pass(psl->normals);
DRW_draw_pass(psl->edit_face_occluded);
- /* detach textures */
- DRW_framebuffer_texture_detach(dtxl->depth);
-
/* Combine with scene buffer */
- DRW_framebuffer_bind(dfbl->default_fb);
+ GPU_framebuffer_bind(dfbl->color_only_fb);
DRW_draw_pass(psl->mix_occlude);
-
- /* detach temp textures */
- DRW_framebuffer_texture_detach(e_data.occlude_wire_depth_tx);
- DRW_framebuffer_texture_detach(e_data.occlude_wire_color_tx);
-
- /* reattach */
- DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
}
else {
DRW_draw_pass(psl->normals);
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index b5127ca634d..2947c64d91b 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -106,8 +106,9 @@ typedef struct OBJECT_PassList {
} OBJECT_PassList;
typedef struct OBJECT_FramebufferList {
- struct GPUFrameBuffer *outlines;
- struct GPUFrameBuffer *blur;
+ struct GPUFrameBuffer *outlines_fb;
+ struct GPUFrameBuffer *blur_fb;
+ struct GPUFrameBuffer *expand_fb;
} OBJECT_FramebufferList;
typedef struct OBJECT_StorageList {
@@ -282,23 +283,31 @@ static void OBJECT_engine_init(void *vedata)
OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl;
const float *viewport_size = DRW_viewport_size_get();
+ const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
if (DRW_state_is_fbo()) {
- DRWFboTexture tex[2] = {
- {&e_data.outlines_depth_tx, DRW_TEX_DEPTH_24, DRW_TEX_TEMP},
- {&e_data.outlines_color_tx, DRW_TEX_RGBA_8, DRW_TEX_FILTER | DRW_TEX_TEMP},
- };
+ e_data.outlines_depth_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_DEPTH_24,
+ &draw_engine_object_type);
+ e_data.outlines_color_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_RGBA_8,
+ &draw_engine_object_type);
- DRW_framebuffer_init(
- &fbl->outlines, &draw_engine_object_type,
- (int)viewport_size[0], (int)viewport_size[1],
- tex, 2);
+ GPU_framebuffer_ensure_config(&fbl->outlines_fb, {
+ GPU_ATTACHMENT_TEXTURE(e_data.outlines_depth_tx),
+ GPU_ATTACHMENT_TEXTURE(e_data.outlines_color_tx)
+ });
- DRWFboTexture blur_tex = {&e_data.outlines_blur_tx, DRW_TEX_RGBA_8, DRW_TEX_FILTER | DRW_TEX_TEMP};
- DRW_framebuffer_init(
- &fbl->blur, &draw_engine_object_type,
- (int)viewport_size[0], (int)viewport_size[1],
- &blur_tex, 1);
+ GPU_framebuffer_ensure_config(&fbl->expand_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(e_data.outlines_color_tx)
+ });
+
+ e_data.outlines_blur_tx = DRW_texture_pool_query_2D(size[0], size[1], DRW_TEX_RGBA_8,
+ &draw_engine_object_type);
+
+ GPU_framebuffer_ensure_config(&fbl->blur_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(e_data.outlines_blur_tx)
+ });
}
if (!e_data.outline_resolve_sh) {
@@ -2036,38 +2045,27 @@ static void OBJECT_draw_scene(void *vedata)
if (DRW_state_is_fbo()) {
DRW_stats_group_start("Outlines");
- /* attach temp textures */
- DRW_framebuffer_texture_attach(fbl->outlines, e_data.outlines_depth_tx, 0, 0);
- DRW_framebuffer_texture_attach(fbl->outlines, e_data.outlines_color_tx, 0, 0);
- DRW_framebuffer_texture_attach(fbl->blur, e_data.outlines_blur_tx, 0, 0);
/* Render filled polygon on a separate framebuffer */
- DRW_framebuffer_bind(fbl->outlines);
- DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
+ GPU_framebuffer_bind(fbl->outlines_fb);
+ GPU_framebuffer_clear_color_depth(fbl->outlines_fb, clearcol, 1.0f);
DRW_draw_pass(psl->outlines);
DRW_draw_pass(psl->lightprobes);
- /* detach textures */
- DRW_framebuffer_texture_detach(e_data.outlines_depth_tx);
-
/* Search outline pixels */
- DRW_framebuffer_bind(fbl->blur);
+ GPU_framebuffer_bind(fbl->blur_fb);
DRW_draw_pass(psl->outlines_search);
/* Expand outline to form a 3px wide line */
- DRW_framebuffer_bind(fbl->outlines);
+ GPU_framebuffer_bind(fbl->expand_fb);
DRW_draw_pass(psl->outlines_expand);
/* Bleed color so the AA can do it's stuff */
- DRW_framebuffer_bind(fbl->blur);
+ GPU_framebuffer_bind(fbl->blur_fb);
DRW_draw_pass(psl->outlines_bleed);
- /* detach temp textures */
- DRW_framebuffer_texture_detach(e_data.outlines_color_tx);
- DRW_framebuffer_texture_detach(e_data.outlines_blur_tx);
-
/* restore main framebuffer */
- DRW_framebuffer_bind(dfbl->default_fb);
+ GPU_framebuffer_bind(dfbl->default_fb);
DRW_stats_group_end();
}
else if (DRW_state_is_select()) {
@@ -2091,9 +2089,9 @@ static void OBJECT_draw_scene(void *vedata)
if (DRW_state_is_fbo()) {
if (e_data.draw_grid) {
- DRW_framebuffer_texture_detach(dtxl->depth);
+ GPU_framebuffer_bind(dfbl->color_only_fb);
DRW_draw_pass(psl->grid);
- DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
+ GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
}
/* Combine with scene buffer last */
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
index 93f16b342d1..0ab15a4ea47 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -36,6 +36,13 @@
extern "C" {
#endif
+struct GPUTexture;
+
+typedef struct GPUAttachment {
+ struct GPUTexture *tex;
+ int mip, layer;
+} GPUAttachment;
+
typedef enum GPUFrameBufferBits{
GPU_COLOR_BIT = (1 << 0),
GPU_DEPTH_BIT = (1 << 1),
@@ -44,40 +51,95 @@ typedef enum GPUFrameBufferBits{
typedef struct GPUFrameBuffer GPUFrameBuffer;
typedef struct GPUOffScreen GPUOffScreen;
-struct GPUTexture;
/* GPU Framebuffer
* - this is a wrapper for an OpenGL framebuffer object (FBO). in practice
* multiple FBO's may be created, to get around limitations on the number
* of attached textures and the dimension requirements.
- * - after any of the GPU_framebuffer_* functions, GPU_framebuffer_restore must
- * be called before rendering to the window framebuffer again */
-
-void GPU_texture_bind_as_framebuffer(struct GPUTexture *tex);
+ * - actual FBO creation & config is deferred until GPU_framebuffer_bind or
+ * GPU_framebuffer_check_valid to allow creation & config while another
+ * opengl context is bound (since FBOs are not shared between ogl contexts).
+ */
GPUFrameBuffer *GPU_framebuffer_create(void);
-bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip);
-bool GPU_framebuffer_texture_layer_attach(
- GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip);
-bool GPU_framebuffer_texture_cubeface_attach(
- GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip);
-void GPU_framebuffer_texture_detach(struct GPUTexture *tex);
-void GPU_framebuffer_bind(GPUFrameBuffer *fb);
-void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
-void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, struct GPUTexture *tex);
void GPU_framebuffer_free(GPUFrameBuffer *fb);
+void GPU_framebuffer_bind(GPUFrameBuffer *fb);
+void GPU_framebuffer_restore(void);
+
+bool GPU_framebuffer_bound(GPUFrameBuffer *fb);
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
/* internal use only */
unsigned int GPU_framebuffer_current_get(void);
-void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot);
-bool GPU_framebuffer_bound(GPUFrameBuffer *fb);
+#define GPU_FRAMEBUFFER_FREE_SAFE(fb) do { \
+ if (fb != NULL) { \
+ GPU_framebuffer_free(fb); \
+ fb = NULL; \
+ } \
+} while (0)
+
+/* Framebuffer setup : You need to call GPU_framebuffer_bind for theses
+ * to be effective. */
+
+void GPU_framebuffer_texture_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip);
+void GPU_framebuffer_texture_layer_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip);
+void GPU_framebuffer_texture_cubeface_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip);
+void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, struct GPUTexture *tex);
+void GPU_framebuffer_texture_detach_slot(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int type);
+
+/**
+ * How to use GPU_framebuffer_ensure_config().
+ *
+ * Example :
+ * GPU_framebuffer_ensure_config(&fb, {
+ * GPU_ATTACHMENT_TEXTURE(depth), // must be depth buffer
+ * GPU_ATTACHMENT_TEXTURE(tex1),
+ * GPU_ATTACHMENT_TEXTURE_CUBEFACE(tex2, 0),
+ * GPU_ATTACHMENT_TEXTURE_LAYER_MIP(tex2, 0, 0)
+ * })
+ *
+ * Note : Unspecified attachements (i.e: those beyond the last
+ * GPU_ATTACHMENT_* in GPU_framebuffer_ensure_config list)
+ * are left unchanged.
+ * Note : Make sure that the dimensions of your textures matches
+ * otherwise you will have an invalid framebuffer error.
+ **/
+#define GPU_framebuffer_ensure_config(_fb, ...) do { \
+ if (*(_fb) == NULL) { \
+ *(_fb) = GPU_framebuffer_create(); \
+ } \
+ GPUAttachment config[] = __VA_ARGS__; \
+ GPU_framebuffer_config_array(*(_fb), config, (sizeof(config) / sizeof(GPUAttachment))); \
+} while (0)
+
+void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_ct);
+
+#define GPU_ATTACHMENT_NONE \
+ {.tex = NULL, .layer = -1, .mip = 0}
+#define GPU_ATTACHMENT_LEAVE \
+ {.tex = NULL, .layer = -1, .mip = -1}
+#define GPU_ATTACHMENT_TEXTURE(_tex) \
+ {.tex = _tex, .layer = -1, .mip = 0}
+#define GPU_ATTACHMENT_TEXTURE_MIP(_tex, _mip) \
+ {.tex = _tex, .layer = -1, .mip = _mip}
+#define GPU_ATTACHMENT_TEXTURE_LAYER(_tex, _layer) \
+ {.tex = _tex, .layer = _layer, .mip = 0}
+#define GPU_ATTACHMENT_TEXTURE_LAYER_MIP(_tex, _layer, _mip) \
+ {.tex = _tex, .layer = _layer, .mip = _mip}
+#define GPU_ATTACHMENT_TEXTURE_CUBEFACE(_tex, _face) \
+ {.tex = _tex, .layer = _face, .mip = 0}
+#define GPU_ATTACHMENT_TEXTURE_CUBEFACE_MIP(_tex, _face, _mip) \
+ {.tex = _tex, .layer = _face, .mip = _mip}
+
/* Framebuffer operations */
void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int w, int h);
-void GPU_framebuffer_restore(void);
void GPU_framebuffer_clear(
GPUFrameBuffer *fb, GPUFrameBufferBits buffers,
const float clear_col[4], float clear_depth, unsigned int clear_stencil);
@@ -100,18 +162,22 @@ void GPU_framebuffer_clear(
#define GPU_framebuffer_clear_color_depth_stencil(fb, col, depth, stencil) \
GPU_framebuffer_clear(fb, GPU_COLOR_BIT | GPU_DEPTH_BIT | GPU_STENCIL_BIT, col, depth, stencil)
+void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data);
+void GPU_framebuffer_read_color(
+ GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data);
void GPU_framebuffer_blit(
GPUFrameBuffer *fb_read, int read_slot,
- GPUFrameBuffer *fb_write, int write_slot, bool use_depth, bool use_stencil);
+ GPUFrameBuffer *fb_write, int write_slot,
+ GPUFrameBufferBits blit_buffers);
void GPU_framebuffer_recursive_downsample(
- GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
+ GPUFrameBuffer *fb, int max_lvl,
void (*callback)(void *userData, int level), void *userData);
/* GPU OffScreen
* - wrapper around framebuffer and texture for simple offscreen drawing
- * - changes size if graphics card can't support it */
+ */
GPUOffScreen *GPU_offscreen_create(int width, int height, int samples,
bool depth, bool high_bitdepth, char err_out[256]);
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 72e3859a5a8..57185d2f39e 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -189,9 +189,8 @@ void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter);
void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter);
void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat);
-struct GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
-int GPU_texture_framebuffer_attachment(GPUTexture *tex);
-void GPU_texture_framebuffer_set(GPUTexture *tex, struct GPUFrameBuffer *fb, int attachment);
+void GPU_texture_attach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb, int attachment);
+int GPU_texture_detach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb);
int GPU_texture_target(const GPUTexture *tex);
int GPU_texture_width(const GPUTexture *tex);
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index dbcf0dc4568..0e27e3e0f8f 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -30,6 +30,7 @@
#include "BLI_blenlib.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLI_math_base.h"
#include "BKE_global.h"
@@ -43,16 +44,67 @@
static ThreadLocal(GLuint) g_currentfb;
-/* Number of maximum output slots.
- * We support 5 outputs for now (usually we wouldn't need more to preserve fill rate) */
-#define GPU_FB_MAX_SLOTS 5
+typedef enum {
+ GPU_FB_DEPTH_ATTACHMENT = 0,
+ GPU_FB_DEPTH_STENCIL_ATTACHMENT,
+ GPU_FB_COLOR_ATTACHMENT0,
+ GPU_FB_COLOR_ATTACHMENT1,
+ GPU_FB_COLOR_ATTACHMENT2,
+ GPU_FB_COLOR_ATTACHMENT3,
+ GPU_FB_COLOR_ATTACHMENT4,
+ /* Number of maximum output slots.
+ * We support 5 outputs for now (usually we wouldn't need more to preserve fill rate). */
+ /* Keep in mind that GL max is GL_MAX_DRAW_BUFFERS and is at least 8, corresponding to
+ * the maximum number of COLOR attachments specified by glDrawBuffers. */
+ GPU_FB_MAX_ATTACHEMENT
+} GPUAttachmentType;
+
+#define GPU_FB_MAX_COLOR_ATTACHMENT (GPU_FB_MAX_ATTACHEMENT - GPU_FB_COLOR_ATTACHMENT0)
+
+#define GPU_FB_DIRTY_DRAWBUFFER (1 << 15)
+
+#define GPU_FB_ATTACHEMENT_IS_DIRTY(flag, type) ((flag & (1 << type)) != 0)
+#define GPU_FB_ATTACHEMENT_SET_DIRTY(flag, type) (flag |= (1 << type))
struct GPUFrameBuffer {
GLuint object;
- GPUTexture *colortex[GPU_FB_MAX_SLOTS];
- GPUTexture *depthtex;
+ GPUAttachment attachments[GPU_FB_MAX_ATTACHEMENT];
+ uint16_t dirty_flag;
+ int width, height;
+ bool multisample;
+ /* TODO Check that we always use the right context when binding
+ * (FBOs are not shared accross ogl contexts). */
+ // void *ctx;
};
+static GLenum convert_attachment_type_to_gl(GPUAttachmentType type)
+{
+ static const GLenum table[] = {
+ [GPU_FB_DEPTH_ATTACHMENT] = GL_DEPTH_ATTACHMENT,
+ [GPU_FB_DEPTH_STENCIL_ATTACHMENT] = GL_DEPTH_STENCIL_ATTACHMENT,
+ [GPU_FB_COLOR_ATTACHMENT0] = GL_COLOR_ATTACHMENT0,
+ [GPU_FB_COLOR_ATTACHMENT1] = GL_COLOR_ATTACHMENT1,
+ [GPU_FB_COLOR_ATTACHMENT2] = GL_COLOR_ATTACHMENT2,
+ [GPU_FB_COLOR_ATTACHMENT3] = GL_COLOR_ATTACHMENT3,
+ [GPU_FB_COLOR_ATTACHMENT4] = GL_COLOR_ATTACHMENT4
+ };
+ return table[type];
+}
+
+static GPUAttachmentType attachment_type_from_tex(GPUTexture *tex, int slot)
+{
+ switch (GPU_texture_format(tex)) {
+ case GPU_DEPTH_COMPONENT32F:
+ case GPU_DEPTH_COMPONENT24:
+ case GPU_DEPTH_COMPONENT16:
+ return GPU_FB_DEPTH_ATTACHMENT;
+ case GPU_DEPTH24_STENCIL8:
+ return GPU_FB_DEPTH_STENCIL_ATTACHMENT;
+ default:
+ return GPU_FB_COLOR_ATTACHMENT0 + slot;
+ }
+}
+
static GLenum convert_buffer_bits_to_gl(GPUFrameBufferBits bits)
{
GLbitfield mask = 0;
@@ -62,6 +114,19 @@ static GLenum convert_buffer_bits_to_gl(GPUFrameBufferBits bits)
return mask;
}
+static GPUTexture *framebuffer_get_depth_tex(GPUFrameBuffer *fb)
+{
+ if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex)
+ return fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex;
+ else
+ return fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex;;
+}
+
+static GPUTexture *framebuffer_get_color_tex(GPUFrameBuffer *fb, int slot)
+{
+ return fb->attachments[GPU_FB_COLOR_ATTACHMENT0 + slot].tex;
+}
+
static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
{
const char *format = "GPUFrameBuffer: framebuffer status %s\n";
@@ -102,303 +167,268 @@ static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
GPUFrameBuffer *GPU_framebuffer_create(void)
{
- GPUFrameBuffer *fb;
+ /* We generate the FB object later at first use in order to
+ * create the framebuffer in the right opengl context. */
+ return MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");;
+}
- fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
+static void gpu_framebuffer_init(GPUFrameBuffer *fb)
+{
glGenFramebuffers(1, &fb->object);
-
- if (!fb->object) {
- fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed.\n");
- GPU_framebuffer_free(fb);
- return NULL;
- }
-
- /* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- glReadBuffer(GL_NONE);
- glDrawBuffer(GL_NONE);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- return fb;
}
-bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
+void GPU_framebuffer_free(GPUFrameBuffer *fb)
{
- GLenum attachment;
-
- if (slot >= GPU_FB_MAX_SLOTS) {
- fprintf(stderr,
- "Attaching to index %d framebuffer slot unsupported. "
- "Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
- return false;
- }
-
- if ((G.debug & G_DEBUG)) {
- if (GPU_texture_bound_number(tex) != -1) {
- fprintf(stderr,
- "Feedback loop warning!: "
- "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n");
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; type++) {
+ if (fb->attachments[type].tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, fb->attachments[type].tex);
}
}
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- g_currentfb = fb->object;
-
- if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- else if (GPU_texture_depth(tex))
- attachment = GL_DEPTH_ATTACHMENT;
- else
- attachment = GL_COLOR_ATTACHMENT0 + slot;
-
- glFramebufferTexture(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), mip);
-
- if (GPU_texture_depth(tex))
- fb->depthtex = tex;
- else
- fb->colortex[slot] = tex;
+ /* This restores the framebuffer if it was bound */
+ glDeleteFramebuffers(1, &fb->object);
- GPU_texture_framebuffer_set(tex, fb, slot);
+ if (g_currentfb == fb->object) {
+ g_currentfb = 0;
+ }
- return true;
+ MEM_freeN(fb);
}
-static bool gpu_framebuffer_texture_layer_attach_ex(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip, bool cubemap)
-{
- GLenum attachment;
- GLenum facetarget;
+/* ---------- Attach ----------- */
- if (slot >= GPU_FB_MAX_SLOTS) {
+static void gpu_framebuffer_texture_attach_ex(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
+{
+ if (slot >= GPU_FB_MAX_COLOR_ATTACHMENT) {
fprintf(stderr,
"Attaching to index %d framebuffer slot unsupported. "
- "Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
- return false;
- }
-
- if ((G.debug & G_DEBUG)) {
- if (GPU_texture_bound_number(tex) != -1) {
- fprintf(stderr,
- "Feedback loop warning!: "
- "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n");
- }
+ "Use at most %d\n", slot, GPU_FB_MAX_COLOR_ATTACHMENT);
+ return;
}
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- g_currentfb = fb->object;
-
- if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- else if (GPU_texture_depth(tex))
- attachment = GL_DEPTH_ATTACHMENT;
- else
- attachment = GL_COLOR_ATTACHMENT0 + slot;
+ GPUAttachmentType type = attachment_type_from_tex(tex, slot);
+ GPUAttachment *attachment = &fb->attachments[type];
- if (cubemap) {
- facetarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
- glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, facetarget, GPU_texture_opengl_bindcode(tex), mip);
+ if ((attachment->tex == tex) &&
+ (attachment->mip == mip) &&
+ (attachment->layer == layer))
+ {
+ return; /* Exact same texture already bound here. */
}
- else {
- glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), mip, layer);
+ else if (attachment->tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, attachment->tex);
}
- if (GPU_texture_depth(tex))
- fb->depthtex = tex;
- else
- fb->colortex[slot] = tex;
-
- GPU_texture_framebuffer_set(tex, fb, slot);
+ if (attachment->tex == NULL) {
+ GPU_texture_attach_framebuffer(tex, fb, type);
+ }
- return true;
+ attachment->tex = tex;
+ attachment->mip = mip;
+ attachment->layer = layer;
+ GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
}
-bool GPU_framebuffer_texture_layer_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
+void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
{
- return gpu_framebuffer_texture_layer_attach_ex(fb, tex, slot, layer, mip, false);
+ return gpu_framebuffer_texture_attach_ex(fb, tex, slot, -1, mip);
}
-bool GPU_framebuffer_texture_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip)
+void GPU_framebuffer_texture_layer_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
{
- BLI_assert(GPU_texture_target(tex) == GL_TEXTURE_CUBE_MAP);
- return gpu_framebuffer_texture_layer_attach_ex(fb, tex, slot, face, mip, true);
+ /* NOTE: We could support 1D ARRAY texture. */
+ BLI_assert(GPU_texture_target(tex) == GL_TEXTURE_2D_ARRAY);
+ return gpu_framebuffer_texture_attach_ex(fb, tex, slot, layer, mip);
}
-void GPU_framebuffer_texture_detach(GPUTexture *tex)
+void GPU_framebuffer_texture_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip)
{
- GLenum attachment;
- GPUFrameBuffer *fb = GPU_texture_framebuffer(tex);
- int fb_attachment = GPU_texture_framebuffer_attachment(tex);
+ BLI_assert(GPU_texture_cube(tex));
+ return gpu_framebuffer_texture_attach_ex(fb, tex, slot, face, mip);
+}
- if (!fb)
- return;
+/* ---------- Detach ----------- */
- if (g_currentfb != fb->object) {
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- g_currentfb = fb->object;
- }
+void GPU_framebuffer_texture_detach_slot(GPUFrameBuffer *fb, GPUTexture *tex, int type)
+{
+ GPUAttachment *attachment = &fb->attachments[type];
- if (GPU_texture_stencil(tex) && GPU_texture_depth(tex)) {
- fb->depthtex = NULL;
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- }
- else if (GPU_texture_depth(tex)) {
- fb->depthtex = NULL;
- attachment = GL_DEPTH_ATTACHMENT;
- }
- else {
- BLI_assert(fb->colortex[fb_attachment] == tex);
- fb->colortex[fb_attachment] = NULL;
- attachment = GL_COLOR_ATTACHMENT0 + fb_attachment;
+ if (attachment->tex != tex) {
+ fprintf(stderr,
+ "Warning, attempting to detach Texture %p from framebuffer %p "
+ "but texture is not attached.\n", tex, fb);
+ return;
}
- glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0);
+ attachment->tex = NULL;
+ GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
+}
- GPU_texture_framebuffer_set(tex, NULL, -1);
+void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
+{
+ GPUAttachmentType type = GPU_texture_detach_framebuffer(tex, fb);
+ GPU_framebuffer_texture_detach_slot(fb, tex, type);
}
-void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
+/* ---------- Config (Attach & Detach) ----------- */
+
+/**
+ * First GPUAttachment in *config is always the depth/depth_stencil buffer.
+ * Following GPUAttachments are color buffers.
+ * Setting GPUAttachment.mip to -1 will leave the texture in this slot.
+ * Setting GPUAttachment.tex to NULL will detach the texture in this slot.
+ **/
+void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_ct)
{
- GPUFrameBuffer *fb = GPU_texture_framebuffer(tex);
- int fb_attachment = GPU_texture_framebuffer_attachment(tex);
+ if (config[0].tex) {
+ BLI_assert(GPU_texture_depth(config[0].tex));
+ gpu_framebuffer_texture_attach_ex(fb, config[0].tex, 0, config[0].layer, config[0].mip);
+ }
+ else if (config[0].mip == -1) {
+ /* Leave texture attached */
+ }
+ else if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex);
+ }
+ else if (fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex);
+ }
- if (!fb) {
- fprintf(stderr, "Error, texture not bound to framebuffer!\n");
- return;
+ int slot = 0;
+ for (int i = 1; i < config_ct; ++i, ++slot) {
+ if (config[i].tex != NULL) {
+ BLI_assert(GPU_texture_depth(config[i].tex) == false);
+ gpu_framebuffer_texture_attach_ex(fb, config[i].tex, slot, config[i].layer, config[i].mip);
+ }
+ else if (config[i].mip != -1) {
+ GPUTexture *tex = framebuffer_get_color_tex(fb, slot);
+ if (tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, tex);
+ }
+ }
}
+}
- /* push attributes */
- gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
- glDisable(GL_SCISSOR_TEST);
+/* ---------- Bind / Restore ----------- */
- /* bind framebuffer */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+static void gpu_framebuffer_attachment_attach(GPUAttachment *attach, GPUAttachmentType attach_type)
+{
+ int tex_bind = GPU_texture_opengl_bindcode(attach->tex);
+ GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
- if (GPU_texture_depth(tex)) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
+ if (attach->layer > -1) {
+ if (GPU_texture_cube(attach->tex)) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X + attach->layer,
+ tex_bind, attach->mip);
+ }
+ else {
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip, attach->layer);
+ }
}
else {
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0 + fb_attachment);
- glReadBuffer(GL_COLOR_ATTACHMENT0 + fb_attachment);
- }
-
- if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) {
- glEnable(GL_MULTISAMPLE);
+ glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip);
}
+}
- /* set default viewport */
- glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
- g_currentfb = fb->object;
+static void gpu_framebuffer_attachment_detach(GPUAttachment *UNUSED(attachment), GPUAttachmentType attach_type)
+{
+ GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
+ glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, 0, 0);
}
-void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
+static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb)
{
- int numslots = 0, i;
- GLenum attachments[GPU_FB_MAX_SLOTS];
-
- if (!fb->colortex[slot]) {
- fprintf(stderr, "Error, framebuffer slot empty!\n");
- return;
- }
-
- for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
- if (fb->colortex[i]) {
- attachments[numslots] = GL_COLOR_ATTACHMENT0 + i;
+ GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT];
+ int numslots = 0;
+
+ BLI_assert(g_currentfb == fb->object);
+
+ /* Update attachments */
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+
+ if (type >= GPU_FB_COLOR_ATTACHMENT0) {
+ if (fb->attachments[type].tex) {
+ gl_attachments[numslots] = convert_attachment_type_to_gl(type);
+ }
+ else {
+ gl_attachments[numslots] = GL_NONE;
+ }
numslots++;
}
- }
-
- /* push attributes */
- gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
- glDisable(GL_SCISSOR_TEST);
- /* bind framebuffer */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type) == false) {
+ continue;
+ }
+ else if (fb->attachments[type].tex != NULL) {
+ gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffers(numslots, attachments);
- glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
+ fb->multisample = (GPU_texture_samples(fb->attachments[type].tex) > 0);
+ fb->width = GPU_texture_width(fb->attachments[type].tex);
+ fb->height = GPU_texture_height(fb->attachments[type].tex);
+ }
+ else {
+ gpu_framebuffer_attachment_detach(&fb->attachments[type], type);
+ }
+ }
+ fb->dirty_flag = 0;
- /* set default viewport */
- glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
- g_currentfb = fb->object;
+ /* Update draw buffers (color targets)
+ * This state is saved in the FBO */
+ if (numslots)
+ glDrawBuffers(numslots, gl_attachments);
+ else
+ glDrawBuffer(GL_NONE);
}
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
{
- int numslots = 0, i;
- GLenum attachments[GPU_FB_MAX_SLOTS];
- GLenum readattachement = 0;
- GPUTexture *tex;
+ if (fb->object == 0)
+ gpu_framebuffer_init(fb);
- for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
- if (fb->colortex[i]) {
- attachments[numslots] = GL_COLOR_ATTACHMENT0 + i;
- tex = fb->colortex[i];
-
- if (!readattachement)
- readattachement = GL_COLOR_ATTACHMENT0 + i;
+ if (g_currentfb != fb->object)
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- numslots++;
- }
- }
+ g_currentfb = fb->object;
- /* bind framebuffer */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ if (fb->dirty_flag != 0)
+ gpu_framebuffer_update_attachments(fb);
- if (numslots == 0) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- tex = fb->depthtex;
- }
- else {
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffers(numslots, attachments);
- glReadBuffer(readattachement);
+ /* TODO manually check for errors? */
+#if 0
+ char err_out[256];
+ if (!GPU_framebuffer_check_valid(fb, err_out)) {
+ printf("Invalid %s\n", err_out);
}
+#endif
- if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) {
+ if (fb->multisample)
glEnable(GL_MULTISAMPLE);
- }
- glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
- g_currentfb = fb->object;
+ glViewport(0, 0, fb->width, fb->height);
}
-void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
+void GPU_framebuffer_restore(void)
{
- /* Restore attributes. */
- gpuPopAttrib();
+ if (g_currentfb != 0) {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ g_currentfb = 0;
+ }
}
-void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
+bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
{
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0 + slot);
- glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
-
- /* push matrices and set default viewport and matrix */
- glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
- g_currentfb = fb->object;
+ return (fb->object == g_currentfb) && (fb->object != 0);
}
-bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
+unsigned int GPU_framebuffer_current_get(void)
{
- return fb->object == g_currentfb;
+ return g_currentfb;
}
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
{
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- g_currentfb = fb->object;
-
- /* On macOS glDrawBuffer must be set when checking completeness,
- * otherwise it will return GL_FRAMEBUFFER_UNSUPPORTED when only a
- * color buffer without depth is used. */
- if (fb->colortex[0]) {
- glDrawBuffer(GL_COLOR_ATTACHMENT0);
- }
+ if (g_currentfb != fb->object)
+ GPU_framebuffer_bind(fb);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -411,42 +441,7 @@ bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
return true;
}
-void GPU_framebuffer_free(GPUFrameBuffer *fb)
-{
- int i;
- if (fb->depthtex)
- GPU_framebuffer_texture_detach(fb->depthtex);
-
- for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
- if (fb->colortex[i]) {
- GPU_framebuffer_texture_detach(fb->colortex[i]);
- }
- }
-
- if (fb->object) {
- glDeleteFramebuffers(1, &fb->object);
-
- if (g_currentfb == fb->object) {
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- g_currentfb = 0;
- }
- }
-
- MEM_freeN(fb);
-}
-
-unsigned int GPU_framebuffer_current_get(void)
-{
- return g_currentfb;
-}
-
-void GPU_framebuffer_restore(void)
-{
- if (g_currentfb != 0) {
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- g_currentfb = 0;
- }
-}
+/* ---------- Framebuffer Operations ----------- */
#define CHECK_FRAMEBUFFER_IS_BOUND(_fb) \
BLI_assert(GPU_framebuffer_bound(_fb)); \
@@ -482,61 +477,104 @@ void GPU_framebuffer_clear(
glClear(mask);
}
+void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data)
+{
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
+
+ GLenum type = GL_DEPTH_COMPONENT;
+ glReadBuffer(GL_COLOR_ATTACHMENT0); /* This is OK! */
+ glReadPixels(x, y, w, h, type, GL_FLOAT, data);
+}
+
+void GPU_framebuffer_read_color(
+ GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data)
+{
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
+
+ GLenum type;
+ switch (channels) {
+ case 1: type = GL_RED; break;
+ case 2: type = GL_RG; break;
+ case 3: type = GL_RGB; break;
+ case 4: type = GL_RGBA; break;
+ default:
+ BLI_assert(false && "wrong number of read channels");
+ return;
+ }
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
+ glReadPixels(x, y, w, h, type, GL_FLOAT, data);
+}
+
+/* read_slot and write_slot are only used for color buffers. */
void GPU_framebuffer_blit(
- GPUFrameBuffer *fb_read, int read_slot, GPUFrameBuffer *fb_write,
- int write_slot, bool use_depth, bool use_stencil)
-{
- GPUTexture *read_tex = (use_depth || use_stencil) ? fb_read->depthtex : fb_read->colortex[read_slot];
- GPUTexture *write_tex = (use_depth || use_stencil) ? fb_write->depthtex : fb_write->colortex[write_slot];
- int read_attach = (use_depth) ? GL_DEPTH_ATTACHMENT :
- (use_stencil) ? GL_DEPTH_STENCIL_ATTACHMENT :
- GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(read_tex);
- int write_attach = (use_depth) ? GL_DEPTH_ATTACHMENT :
- (use_stencil) ? GL_DEPTH_STENCIL_ATTACHMENT :
- GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(write_tex);
- int read_bind = GPU_texture_opengl_bindcode(read_tex);
- int write_bind = GPU_texture_opengl_bindcode(write_tex);
- const int read_w = GPU_texture_width(read_tex);
- const int read_h = GPU_texture_height(read_tex);
- const int write_w = GPU_texture_width(write_tex);
- const int write_h = GPU_texture_height(write_tex);
-
-
- /* Never both! */
- BLI_assert(!(use_depth && use_stencil));
-
- if (use_depth) {
+ GPUFrameBuffer *fb_read, int read_slot,
+ GPUFrameBuffer *fb_write, int write_slot,
+ GPUFrameBufferBits blit_buffers)
+{
+ BLI_assert(blit_buffers != 0);
+
+ GLuint prev_fb = g_currentfb;
+
+ /* Framebuffers must be up to date. This simplify this function. */
+ if (fb_read->dirty_flag != 0 || fb_read->object == 0) {
+ GPU_framebuffer_bind(fb_read);
+ }
+ if (fb_write->dirty_flag != 0 || fb_write->object == 0) {
+ GPU_framebuffer_bind(fb_write);
+ }
+
+ const bool do_color = (blit_buffers & GPU_COLOR_BIT);
+ const bool do_depth = (blit_buffers & GPU_DEPTH_BIT);
+ const bool do_stencil = (blit_buffers & GPU_STENCIL_BIT);
+
+ GPUTexture *read_tex = (do_depth || do_stencil)
+ ? framebuffer_get_depth_tex(fb_read)
+ : framebuffer_get_color_tex(fb_read, read_slot);
+ GPUTexture *write_tex = (do_depth || do_stencil)
+ ? framebuffer_get_depth_tex(fb_write)
+ : framebuffer_get_color_tex(fb_write, read_slot);
+
+ if (do_depth) {
BLI_assert(GPU_texture_depth(read_tex) && GPU_texture_depth(write_tex));
BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
}
- else if (use_stencil) {
+ if (do_stencil) {
BLI_assert(GPU_texture_stencil(read_tex) && GPU_texture_stencil(write_tex));
BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
}
+ if (GPU_texture_samples(write_tex) != 0 ||
+ GPU_texture_samples(read_tex) != 0)
+ {
+ /* Can only blit multisample textures to another texture of the same size. */
+ BLI_assert((fb_read->width == fb_write->width) &&
+ (fb_read->height == fb_write->height));
+ }
- /* read from multi-sample buffer */
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object);
- glFramebufferTexture2D(
- GL_READ_FRAMEBUFFER, read_attach,
- GPU_texture_target(read_tex), read_bind, 0);
- BLI_assert(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
-
- /* write into new single-sample buffer */
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object);
- glFramebufferTexture2D(
- GL_DRAW_FRAMEBUFFER, write_attach,
- GPU_texture_target(write_tex), write_bind, 0);
- BLI_assert(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
- glDrawBuffer((use_depth || use_stencil) ? GL_COLOR_ATTACHMENT0 : read_attach);
- glBlitFramebuffer(0, 0, read_w, read_h, 0, 0, write_w, write_h,
- (use_depth) ? GL_DEPTH_BUFFER_BIT :
- (use_stencil) ? GL_STENCIL_BUFFER_BIT :
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ if (do_color) {
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + read_slot);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0 + write_slot);
+ /* XXX we messed with the glDrawBuffer, this will reset the
+ * glDrawBuffers the next time we bind fb_write. */
+ fb_write->dirty_flag = GPU_FB_DIRTY_DRAWBUFFER;
+ }
+
+ GLbitfield mask = convert_buffer_bits_to_gl(blit_buffers);
+
+ glBlitFramebuffer(0, 0, fb_read->width, fb_read->height,
+ 0, 0, fb_write->width, fb_write->height,
+ mask, GL_NEAREST);
/* Restore previous framebuffer */
- glBindFramebuffer(GL_FRAMEBUFFER, g_currentfb);
- glDrawBuffer(GL_COLOR_ATTACHMENT0);
+ if (fb_write->object == prev_fb) {
+ GPU_framebuffer_bind(fb_write); /* To update drawbuffers */
+ }
+ else {
+ glBindFramebuffer(GL_FRAMEBUFFER, prev_fb);
+ g_currentfb = prev_fb;
+ }
}
/**
@@ -544,68 +582,63 @@ void GPU_framebuffer_blit(
* This function only takes care of the correct texture handling. It execute the callback for each texture level.
**/
void GPU_framebuffer_recursive_downsample(
- GPUFrameBuffer *fb, GPUTexture *tex, int num_iter, void (*callback)(void *userData, int level), void *userData)
+ GPUFrameBuffer *fb, int max_lvl,
+ void (*callback)(void *userData, int level), void *userData)
{
- int i;
- int current_dim[2] = {GPU_texture_width(tex), GPU_texture_height(tex)};
- GLenum attachment;
-
- /* Manually setup framebuffer to not use GPU_texture_framebuffer_set() */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- g_currentfb = fb->object;
-
- if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- else if (GPU_texture_depth(tex))
- attachment = GL_DEPTH_ATTACHMENT;
- else
- attachment = GL_COLOR_ATTACHMENT0;
-
- /* last bound prevails here, better allow explicit control here too */
- if (GPU_texture_depth(tex)) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- }
- else {
- glDrawBuffer(GL_COLOR_ATTACHMENT0);
- glReadBuffer(GL_COLOR_ATTACHMENT0);
+ /* Framebuffer must be up to date and bound. This simplify this function. */
+ if (g_currentfb != fb->object || fb->dirty_flag != 0 || fb->object == 0) {
+ GPU_framebuffer_bind(fb);
}
+ /* HACK: We make the framebuffer appear not bound in order to
+ * not trigger any error in GPU_texture_bind(). */
+ GLuint prev_fb = g_currentfb;
+ g_currentfb = 0;
- for (i = 1; i < num_iter + 1; i++) {
-
+ int i;
+ int current_dim[2] = {fb->width, fb->height};
+ for (i = 1; i < max_lvl + 1; i++) {
/* calculate next viewport size */
- current_dim[0] /= 2;
- current_dim[1] /= 2;
-
- if (current_dim[0] <= 2 && current_dim[1] <= 2) {
- /* Cannot reduce further. */
- break;
+ current_dim[0] = max_ii(current_dim[0] / 2, 1);
+ current_dim[1] = max_ii(current_dim[1] / 2, 1);
+
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+ if (fb->attachments[type].tex != NULL) {
+ /* bind next level for rendering but first restrict fetches only to previous level */
+ GPUTexture *tex = fb->attachments[type].tex;
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
+ GPU_texture_unbind(tex);
+ /* copy attachment and replace miplevel. */
+ GPUAttachment attachment = fb->attachments[type];
+ attachment.mip = i;
+ gpu_framebuffer_attachment_attach(&attachment, type);
+ }
}
- /* ensure that the viewport size is always at least 1x1 */
- CLAMP_MIN(current_dim[0], 1);
- CLAMP_MIN(current_dim[1], 1);
-
glViewport(0, 0, current_dim[0], current_dim[1]);
-
- /* bind next level for rendering but first restrict fetches only to previous level */
- GPU_texture_bind(tex, 0);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
- GPU_texture_unbind(tex);
-
- glFramebufferTexture(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), i);
-
callback(userData, i);
+
+ if (current_dim[0] == 1 && current_dim[1] == 1)
+ break;
}
- glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0);
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+ if (fb->attachments[type].tex != NULL) {
+ /* reset mipmap level range */
+ GPUTexture *tex = fb->attachments[type].tex;
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
+ GPU_texture_unbind(tex);
+ /* Reattach original level */
+ /* NOTE: This is not necessary but this makes the FBO config
+ * remain in sync with the GPUFrameBuffer config. */
+ gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
+ }
+ }
- /* reset mipmap level range for the depth image */
- GPU_texture_bind(tex, 0);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
- GPU_texture_unbind(tex);
+ g_currentfb = prev_fb;
}
/* GPUOffScreen */
@@ -622,51 +655,23 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool dept
ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
- ofs->fb = GPU_framebuffer_create();
- if (!ofs->fb) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
-
- if (samples) {
- if (!GLEW_ARB_texture_multisample ||
- /* This is required when blitting from a multi-sampled buffers,
- * even though we're not scaling. */
- !GLEW_EXT_framebuffer_multisample_blit_scaled)
- {
- samples = 0;
- }
- }
+ ofs->color = GPU_texture_create_2D_custom_multisample(width, height, 4,
+ (high_bitdepth) ? GPU_RGBA16F : GPU_RGBA8, NULL, samples, err_out);
if (depth) {
ofs->depth = GPU_texture_create_depth_with_stencil_multisample(width, height, samples, err_out);
- if (!ofs->depth) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
-
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, 0)) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
- }
-
- if (high_bitdepth) {
- ofs->color = GPU_texture_create_2D_custom_multisample(width, height, 4, GPU_RGBA16F, NULL, samples, err_out);
- }
- else {
- ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, samples, err_out);
- }
- if (!ofs->color) {
- GPU_offscreen_free(ofs);
- return NULL;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, 0)) {
+ if (!ofs->depth || !ofs->color) {
GPU_offscreen_free(ofs);
return NULL;
}
+ GPU_framebuffer_ensure_config(&ofs->fb, {
+ GPU_ATTACHMENT_TEXTURE(ofs->depth),
+ GPU_ATTACHMENT_TEXTURE(ofs->color)
+ });
+
/* check validity at the very end! */
if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
GPU_offscreen_free(ofs);
@@ -692,68 +697,48 @@ void GPU_offscreen_free(GPUOffScreen *ofs)
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
{
- glDisable(GL_SCISSOR_TEST);
- if (save)
- GPU_texture_bind_as_framebuffer(ofs->color);
- else {
- GPU_framebuffer_bind_no_save(ofs->fb, 0);
+ if (save) {
+ gpuPushAttrib(GPU_SCISSOR_BIT | GPU_VIEWPORT_BIT);
}
+ glDisable(GL_SCISSOR_TEST);
+ GPU_framebuffer_bind(ofs->fb);
}
-void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
+void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore)
{
- if (restore)
- GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
GPU_framebuffer_restore();
- glEnable(GL_SCISSOR_TEST);
+ if (restore) {
+ gpuPopAttrib();
+ }
}
-
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
{
const int w = GPU_texture_width(ofs->color);
const int h = GPU_texture_height(ofs->color);
+ BLI_assert(type == GL_UNSIGNED_BYTE || type == GL_FLOAT);
+
if (GPU_texture_target(ofs->color) == GL_TEXTURE_2D_MULTISAMPLE) {
/* For a multi-sample texture,
* we need to create an intermediate buffer to blit to,
* before its copied using 'glReadPixels' */
-
- /* not needed since 'ofs' needs to be bound to the framebuffer already */
-// #define USE_FBO_CTX_SWITCH
-
GLuint fbo_blit = 0;
GLuint tex_blit = 0;
- GLenum status;
/* create texture for new 'fbo_blit' */
glGenTextures(1, &tex_blit);
- if (!tex_blit) {
- goto finally;
- }
-
glBindTexture(GL_TEXTURE_2D, tex_blit);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, type, 0);
-
-#ifdef USE_FBO_CTX_SWITCH
- /* read from multi-sample buffer */
- glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->color->fb->object);
- glFramebufferTexture2D(
- GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + ofs->color->fb_attachment,
- GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
- status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- goto finally;
- }
-#endif
+ glTexImage2D(GL_TEXTURE_2D, 0, (type == GL_FLOAT) ? GL_RGBA16F : GL_RGBA8,
+ w, h, 0, GL_RGBA, type, 0);
/* write into new single-sample buffer */
glGenFramebuffers(1, &fbo_blit);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
- glFramebufferTexture2D(
- GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, tex_blit, 0);
- status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, tex_blit, 0);
+
+ GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
goto finally;
}
@@ -765,21 +750,13 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_blit);
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
-#ifdef USE_FBO_CTX_SWITCH
/* restore the original frame-bufer */
- glBindFramebuffer(GL_FRAMEBUFFER, ofs->color->fb->object);
-#undef USE_FBO_CTX_SWITCH
-#endif
-
+ glBindFramebuffer(GL_FRAMEBUFFER, ofs->fb->object);
finally:
/* cleanup */
- if (tex_blit) {
- glDeleteTextures(1, &tex_blit);
- }
- if (fbo_blit) {
- glDeleteFramebuffers(1, &fbo_blit);
- }
+ glDeleteTextures(1, &tex_blit);
+ glDeleteFramebuffers(1, &fbo_blit);
}
else {
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
diff --git a/source/blender/gpu/intern/gpu_lamp.c b/source/blender/gpu/intern/gpu_lamp.c
index ffdb433bacf..8968521060d 100644
--- a/source/blender/gpu/intern/gpu_lamp.c
+++ b/source/blender/gpu/intern/gpu_lamp.c
@@ -267,89 +267,35 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) ||
(la->type == LA_SUN && (la->mode & LA_SHAD_RAY)))
{
- /* opengl */
- lamp->fb = GPU_framebuffer_create();
- if (!lamp->fb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- /* Shadow depth map */
lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->depthtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- GPU_texture_bind(lamp->depthtex, 0);
- GPU_texture_compare_mode(lamp->depthtex, true);
- GPU_texture_unbind(lamp->depthtex);
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* Shadow color map */
lamp->tex = gpu_lamp_create_vsm_shadow_map(lamp->size);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* FBO and texture for blurring */
- lamp->blurfb = GPU_framebuffer_create();
- if (!lamp->blurfb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
lamp->blurtex = gpu_lamp_create_vsm_shadow_map(lamp->size * 0.5);
- if (!lamp->blurtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
- if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
+ lamp->fb = GPU_framebuffer_create();
+ GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, 0);
+ GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0);
- /* we need to properly bind to test for completeness */
- GPU_texture_bind_as_framebuffer(lamp->blurtex);
+ lamp->blurfb = GPU_framebuffer_create();
+ GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, 0);
- if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
+ if (!GPU_framebuffer_check_valid(lamp->fb, NULL) ||
+ !GPU_framebuffer_check_valid(lamp->blurfb, NULL))
+ {
gpu_lamp_shadow_free(lamp);
return lamp;
}
-
}
else {
lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
GPU_texture_bind(lamp->tex, 0);
GPU_texture_compare_mode(lamp->tex, true);
+ GPU_texture_filter_mode(lamp->tex, true);
GPU_texture_unbind(lamp->tex);
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
+ lamp->fb = GPU_framebuffer_create();
+ GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0);
if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
gpu_lamp_shadow_free(lamp);
@@ -437,7 +383,7 @@ void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsiz
/* opengl */
glDisable(GL_SCISSOR_TEST);
- GPU_texture_bind_as_framebuffer(lamp->tex);
+ GPU_framebuffer_bind(lamp->fb);
if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
@@ -486,7 +432,6 @@ void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
gpu_lamp_shadow_blur(lamp);
}
- GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
GPU_framebuffer_restore();
glEnable(GL_SCISSOR_TEST);
}
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index b8368343a88..2ccc9ce7ca7 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -48,6 +48,9 @@ static struct GPUTextureGlobal {
GPUTexture *invalid_tex_3D;
} GG = {NULL, NULL, NULL};
+/* Maximum number of FBOs a texture can be attached to. */
+#define GPU_TEX_MAX_FBO_ATTACHED 8
+
typedef enum GPUTextureFormatFlag{
GPU_FORMAT_DEPTH = (1 << 0),
GPU_FORMAT_STENCIL = (1 << 1),
@@ -72,14 +75,15 @@ struct GPUTexture {
GLuint bindcode; /* opengl identifier for texture */
int fromblender; /* we got the texture from Blender */
+ GPUTextureFormat format;
GPUTextureFormatFlag format_flag;
- GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
- int fb_attachment; /* slot the texture is attached to */
unsigned int bytesize; /* number of byte for one pixel */
- GPUTextureFormat format;
int components; /* number of color/alpha channels */
int samples; /* number of samples for multisamples textures. 0 if not multisample target */
+
+ int fb_attachment[GPU_TEX_MAX_FBO_ATTACHED];
+ GPUFrameBuffer *fb[GPU_TEX_MAX_FBO_ATTACHED];
};
/* ------ Memory Management ------- */
@@ -355,7 +359,6 @@ static GPUTexture *GPU_texture_create_nD(
tex->samples = samples;
tex->number = -1;
tex->refcount = 1;
- tex->fb_attachment = -1;
tex->format = data_type;
tex->components = components;
tex->format_flag = 0;
@@ -506,7 +509,6 @@ static GPUTexture *GPU_texture_cube_create(
tex->samples = 0;
tex->number = -1;
tex->refcount = 1;
- tex->fb_attachment = -1;
tex->format = data_type;
tex->components = components;
tex->format_flag = GPU_FORMAT_CUBE;
@@ -847,8 +849,13 @@ void GPU_texture_bind(GPUTexture *tex, int number)
}
if ((G.debug & G_DEBUG)) {
- if (tex->fb && GPU_framebuffer_bound(tex->fb)) {
- fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] && GPU_framebuffer_bound(tex->fb[i])) {
+ fprintf(stderr, "Feedback loop warning!: Attempting to bind "
+ "texture attached to current framebuffer!\n");
+ BLI_assert(0); /* Should never happen! */
+ break;
+ }
}
}
@@ -961,8 +968,12 @@ void GPU_texture_free(GPUTexture *tex)
fprintf(stderr, "GPUTexture: negative refcount\n");
if (tex->refcount == 0) {
- if (tex->fb)
- GPU_framebuffer_texture_detach(tex);
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] != NULL) {
+ GPU_framebuffer_texture_detach_slot(tex->fb[i], tex, tex->fb_attachment[i]);
+ }
+ }
+
if (tex->bindcode && !tex->fromblender)
glDeleteTextures(1, &tex->bindcode);
@@ -1027,19 +1038,28 @@ int GPU_texture_opengl_bindcode(const GPUTexture *tex)
return tex->bindcode;
}
-GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
+void GPU_texture_attach_framebuffer(GPUTexture *tex, GPUFrameBuffer *fb, int attachment)
{
- return tex->fb;
-}
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] == NULL) {
+ tex->fb[i] = fb;
+ tex->fb_attachment[i] = attachment;
+ return;
+ }
+ }
-int GPU_texture_framebuffer_attachment(GPUTexture *tex)
-{
- return tex->fb_attachment;
+ BLI_assert(!"Error: Texture: Not enough Framebuffer slots");
}
-void GPU_texture_framebuffer_set(GPUTexture *tex, GPUFrameBuffer *fb, int attachment)
+/* Return previous attachment point */
+int GPU_texture_detach_framebuffer(GPUTexture *tex, GPUFrameBuffer *fb)
{
- tex->fb = fb;
- tex->fb_attachment = attachment;
-}
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] == fb) {
+ tex->fb[i] = NULL;
+ return tex->fb_attachment[i];
+ }
+ }
+ BLI_assert(!"Error: Texture: Framebuffer is not attached");
+}
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index 0f061f1c791..e635174eca2 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -48,6 +48,7 @@
#include "GPU_immediate.h"
#include "GPU_texture.h"
#include "GPU_viewport.h"
+#include "GPU_draw.h"
#include "DRW_engine.h"
@@ -69,7 +70,6 @@ typedef struct ViewportTempTexture {
struct GPUViewport {
int size[2];
-
int samples;
int flag;
@@ -137,12 +137,19 @@ GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs)
viewport->txl->multisample_depth = depth;
viewport->fbl->multisample_fb = fb;
gpu_viewport_default_fb_create(viewport);
- GPU_framebuffer_slots_bind(viewport->fbl->default_fb, 0);
}
else {
viewport->fbl->default_fb = fb;
viewport->txl->color = color;
viewport->txl->depth = depth;
+ GPU_framebuffer_ensure_config(&viewport->fbl->color_only_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(viewport->txl->color)
+ });
+ GPU_framebuffer_ensure_config(&viewport->fbl->depth_only_fb, {
+ GPU_ATTACHMENT_TEXTURE(viewport->txl->depth),
+ GPU_ATTACHMENT_NONE
+ });
}
return viewport;
@@ -158,8 +165,7 @@ void GPU_viewport_clear_from_offscreen(GPUViewport *viewport)
if (dfbl->multisample_fb) {
/* GPUViewport expect the final result to be in default_fb but
* GPUOffscreen wants it in its multisample_fb, so we sync it back. */
- GPU_framebuffer_blit(dfbl->default_fb, 0, dfbl->multisample_fb, 0, false, false);
- GPU_framebuffer_blit(dfbl->default_fb, 0, dfbl->multisample_fb, 0, true, false);
+ GPU_framebuffer_blit(dfbl->default_fb, 0, dfbl->multisample_fb, 0, GPU_COLOR_BIT | GPU_DEPTH_BIT);
dfbl->multisample_fb = NULL;
dtxl->multisample_color = NULL;
dtxl->multisample_depth = NULL;
@@ -288,9 +294,9 @@ GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine,
GPUTexture *tex;
for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) {
- if ((GPU_texture_width(tmp_tex->texture) == width) &&
- (GPU_texture_height(tmp_tex->texture) == height) &&
- (GPU_texture_format(tmp_tex->texture) == format))
+ 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) {
@@ -307,11 +313,16 @@ GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine,
}
tex = GPU_texture_create_2D_custom(width, height, channels, format, NULL, NULL);
+ GPU_texture_bind(tex, 0);
+ /* 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);
+ GPU_texture_unbind(tex);
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;
@@ -378,48 +389,66 @@ static void gpu_viewport_default_fb_create(GPUViewport *viewport)
int *size = viewport->size;
bool ok = true;
- dfbl->default_fb = GPU_framebuffer_create();
- if (!dfbl->default_fb) {
- ok = false;
- goto cleanup;
- }
-
- /* Color */
dtxl->color = GPU_texture_create_2D(size[0], size[1], NULL, NULL);
- if (!dtxl->color) {
- ok = false;
- goto cleanup;
- }
+ dtxl->depth = GPU_texture_create_depth_with_stencil(size[0], size[1], NULL);
- if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->color, 0, 0)) {
+ if (!(dtxl->depth && dtxl->color)) {
ok = false;
goto cleanup;
}
- /* Depth */
- dtxl->depth = GPU_texture_create_depth_with_stencil(size[0], size[1], NULL);
+ GPU_framebuffer_ensure_config(&dfbl->default_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(dtxl->color)
+ });
- if (dtxl->depth) {
- /* Define texture parameters */
- GPU_texture_bind(dtxl->depth, 0);
- GPU_texture_compare_mode(dtxl->depth, false);
- GPU_texture_filter_mode(dtxl->depth, false);
- GPU_texture_unbind(dtxl->depth);
- }
- else {
- ok = false;
- goto cleanup;
- }
+ GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_NONE
+ });
- if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0)) {
- ok = false;
- goto cleanup;
+ GPU_framebuffer_ensure_config(&dfbl->color_only_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(dtxl->color)
+ });
+
+ ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL);
+ ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL);
+ ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL);
+
+cleanup:
+ if (!ok) {
+ GPU_viewport_free(viewport);
+ DRW_opengl_context_disable();
+ return;
}
- else if (!GPU_framebuffer_check_valid(dfbl->default_fb, NULL)) {
+
+ GPU_framebuffer_restore();
+}
+
+static void gpu_viewport_default_multisample_fb_create(GPUViewport *viewport)
+{
+ DefaultFramebufferList *dfbl = viewport->fbl;
+ DefaultTextureList *dtxl = viewport->txl;
+ int *size = viewport->size;
+ int samples = viewport->samples;
+ bool ok = true;
+
+ dtxl->multisample_color = GPU_texture_create_2D_multisample(size[0], size[1], NULL, samples, NULL);
+ dtxl->multisample_depth = GPU_texture_create_depth_with_stencil_multisample(size[0], size[1], samples, NULL);
+
+ if (!(dtxl->multisample_depth && dtxl->multisample_color)) {
ok = false;
goto cleanup;
}
+ GPU_framebuffer_ensure_config(&dfbl->multisample_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->multisample_depth),
+ GPU_ATTACHMENT_TEXTURE(dtxl->multisample_color)
+ });
+
+ ok = ok && GPU_framebuffer_check_valid(dfbl->multisample_fb, NULL);
+
cleanup:
if (!ok) {
GPU_viewport_free(viewport);
@@ -433,7 +462,6 @@ cleanup:
void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
{
DefaultFramebufferList *dfbl = viewport->fbl;
- DefaultTextureList *dtxl = viewport->txl;
int fbl_len, txl_len;
/* add one pixel because of scissor test */
@@ -460,64 +488,20 @@ void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
viewport->size[0] = rect_w;
viewport->size[1] = rect_h;
+ viewport->samples = U.ogl_multisamples;
gpu_viewport_texture_pool_clear_users(viewport);
/* Multisample Buffer */
- if (U.ogl_multisamples > 0) {
+ if (viewport->samples > 0) {
if (!dfbl->default_fb) {
- bool ok = true;
- viewport->samples = U.ogl_multisamples;
-
- dfbl->multisample_fb = GPU_framebuffer_create();
- if (!dfbl->multisample_fb) {
- ok = false;
- goto cleanup_multisample;
- }
-
- /* Color */
- dtxl->multisample_color = GPU_texture_create_2D_multisample(rect_w, rect_h, NULL, U.ogl_multisamples, NULL);
- if (!dtxl->multisample_color) {
- ok = false;
- goto cleanup_multisample;
- }
-
- if (!GPU_framebuffer_texture_attach(dfbl->multisample_fb, dtxl->multisample_color, 0, 0)) {
- ok = false;
- goto cleanup_multisample;
- }
-
- /* Depth */
- dtxl->multisample_depth = GPU_texture_create_depth_with_stencil_multisample(rect_w, rect_h,
- U.ogl_multisamples, NULL);
-
- if (!dtxl->multisample_depth) {
- ok = false;
- goto cleanup_multisample;
- }
-
- if (!GPU_framebuffer_texture_attach(dfbl->multisample_fb, dtxl->multisample_depth, 0, 0)) {
- ok = false;
- goto cleanup_multisample;
- }
- else if (!GPU_framebuffer_check_valid(dfbl->multisample_fb, NULL)) {
- ok = false;
- goto cleanup_multisample;
- }
-
-cleanup_multisample:
- if (!ok) {
- GPU_viewport_free(viewport);
- return;
- }
+ gpu_viewport_default_multisample_fb_create(viewport);
}
}
if (!dfbl->default_fb) {
gpu_viewport_default_fb_create(viewport);
}
-
- GPU_framebuffer_slots_bind(dfbl->default_fb, 0);
}
void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 4c3a89f76fa..84a4c3786e6 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -82,6 +82,7 @@
#include "GPU_batch.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
+#include "GPU_framebuffer.h"
#include "GPU_init_exit.h"
#include "GPU_immediate.h"
#include "BLF_api.h"
@@ -1157,6 +1158,8 @@ static int query_qual(modifierKeyType qual)
void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
{
+ BLI_assert(GPU_framebuffer_current_get() == 0);
+
if (win != wm->windrawable && win->ghostwin) {
// win->lmbut = 0; /* keeps hanging when mousepressed while other window opened */
@@ -1180,6 +1183,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
void wm_window_reset_drawable(void)
{
BLI_assert(BLI_thread_is_main());
+ BLI_assert(GPU_framebuffer_current_get() == 0);
wmWindowManager *wm = G.main->wm.first;
if (wm == NULL)
@@ -2211,20 +2215,24 @@ void *WM_opengl_context_create(void)
* So we should call this function only on the main thread.
*/
BLI_assert(BLI_thread_is_main());
+ BLI_assert(GPU_framebuffer_current_get() == 0);
return GHOST_CreateOpenGLContext(g_system);
}
void WM_opengl_context_dispose(void *context)
{
+ BLI_assert(GPU_framebuffer_current_get() == 0);
GHOST_DisposeOpenGLContext(g_system, (GHOST_ContextHandle)context);
}
void WM_opengl_context_activate(void *context)
{
+ BLI_assert(GPU_framebuffer_current_get() == 0);
GHOST_ActivateOpenGLContext((GHOST_ContextHandle)context);
}
void WM_opengl_context_release(void *context)
{
+ BLI_assert(GPU_framebuffer_current_get() == 0);
GHOST_ReleaseOpenGLContext((GHOST_ContextHandle)context);
}