GPUFramebuffer: Refactor (Part 2)

This refactor modernise the use of framebuffers.
It also touches a lot of files so breaking down changes we have:
 - GPUTexture: Allow textures to be attached to more than one GPUFrameBuffer.
   This allows to create and configure more FBO without the need to attach
   and detach texture at drawing time.
 - GPUFrameBuffer: The wrapper starts to mimic opengl a bit closer. This
   allows to configure the framebuffer inside a context other than the one
   that will be rendering the framebuffer. We do the actual configuration
   when binding the FBO. We also Keep track of config validity and save
   drawbuffers state in the FBO. We remove the different bind/unbind
   functions. These make little sense now that we have separate contexts.
 - DRWFrameBuffer: We replace DRW_framebuffer functions by GPU_framebuffer
   ones to avoid another layer of abstraction. We move the DRW convenience
   functions to GPUFramebuffer instead and even add new ones. The MACRO
   GPU_framebuffer_ensure_config is pretty much all you need to create and
   config a GPUFramebuffer.
 - DRWTexture: Due to the removal of DRWFrameBuffer, we needed to create
   functions to create textures for thoses framebuffers. Pool textures are
   now using default texture parameters for the texture type asked.
 - DRWManager: Make sure no framebuffer object is bound when doing cache
   filling.
 - GPUViewport: Add new color_only_fb and depth_only_fb along with FB API
   usage update. This let draw engines render to color/depth only target
   and without the need to attach/detach textures.
 - WM_window: Assert when a framebuffer is bound when changing context.
   This balance the fact we are not track ogl context inside GPUFramebuffer.
 - Eevee, Clay, Mode engines: Update to new API. This comes with a lot of
   code simplification.

This also come with some cleanups in some engine codes.
This commit is contained in:
Clément Foucault 2018-03-25 17:46:48 +02:00
parent f937123116
commit bc15ec0896
35 changed files with 1415 additions and 1694 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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);

View File

@ -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;
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);
if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
dof_down_near = &txl->bloom_downsample[0];
}
else {
dof_down_near = &txl->dof_down_near;
}
/* 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();
}

View File

@ -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]};
/* 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);
effects->ssr_normal_input = DRW_texture_pool_query_2D(size_fs[0], size_fs[1], DRW_TEX_RG_16,
&draw_engine_eevee_type);
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();

View File

@ -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);
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_fb, {
GPU_ATTACHMENT_TEXTURE(dtxl->depth),
GPU_ATTACHMENT_TEXTURE(txl->color),
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_LEAVE
});
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;

View File

@ -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
/* Start fresh */
GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, {
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_NONE
});
/* 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));
EEVEE_downsample_cube_buffer(vedata, 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);
DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, size[0], size[1]);
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);
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);
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);
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
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);
}

View File

@ -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);

View File

@ -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)
});
}
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);
/* 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);
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);
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);

View File

@ -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();
}
}

View File

@ -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}};
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);
DRW_framebuffer_init(&fbl->sss_blur_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1],
texs, 2);
GPU_framebuffer_ensure_config(&fbl->sss_blur_fb, {
GPU_ATTACHMENT_TEXTURE(effects->sss_stencil),
GPU_ATTACHMENT_TEXTURE(effects->sss_blur)
});
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);
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);
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)
});
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->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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
# ifdef USE_SSS
# 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;
# endif /* USE_SSS_ALBEDO */
# else
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 = 4) out vec4 sssAlbedo;
# endif /* USE_SSS_ALBEDO */
# endif /* USE_SSS */
Closure nodetree_exec(void); /* Prototype */

View File

@ -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 */

View File

@ -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();

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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]);

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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) {
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);
lamp->blurfb = GPU_framebuffer_create();
GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, 0);
if (!GPU_framebuffer_check_valid(lamp->fb, NULL) ||
!GPU_framebuffer_check_valid(lamp->blurfb, NULL))
{
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;
}
/* we need to properly bind to test for completeness */
GPU_texture_bind_as_framebuffer(lamp->blurtex);
if (!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);
}

View File

@ -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;
}
}
BLI_assert(!"Error: Texture: Not enough Framebuffer slots");
}
int GPU_texture_framebuffer_attachment(GPUTexture *tex)
/* Return previous attachment point */
int GPU_texture_detach_framebuffer(GPUTexture *tex, GPUFrameBuffer *fb)
{
return tex->fb_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];
}
}
void GPU_texture_framebuffer_set(GPUTexture *tex, GPUFrameBuffer *fb, int attachment)
{
tex->fb = fb;
tex->fb_attachment = attachment;
BLI_assert(!"Error: Texture: Framebuffer is not attached");
}

View File

@ -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;
}
if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->color, 0, 0)) {
ok = false;
goto cleanup;
}
/* Depth */
dtxl->depth = GPU_texture_create_depth_with_stencil(size[0], size[1], NULL);
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 {
if (!(dtxl->depth && dtxl->color)) {
ok = false;
goto cleanup;
}
if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0)) {
ok = false;
goto cleanup;
}
else if (!GPU_framebuffer_check_valid(dfbl->default_fb, NULL)) {
GPU_framebuffer_ensure_config(&dfbl->default_fb, {
GPU_ATTACHMENT_TEXTURE(dtxl->depth),
GPU_ATTACHMENT_TEXTURE(dtxl->color)
});
GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, {
GPU_ATTACHMENT_TEXTURE(dtxl->depth),
GPU_ATTACHMENT_NONE
});
GPU_framebuffer_ensure_config(&dfbl->color_only_fb, {
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE(dtxl->color)
});
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;
}
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)

View File

@ -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);
}