EEVEE: Metal: Enable attachmentless FB support for VSM update FB

Utilise attachmentless framebuffer for atomic shadow update
Path.

Authored by Apple: Michael Parkin-White.

Pull Request: https://projects.blender.org/blender/blender/pulls/116396
This commit is contained in:
Jason Fielder
2023-12-24 12:19:18 +01:00
committed by Clément Foucault
parent 258ba00a03
commit 6692390501
4 changed files with 26 additions and 17 deletions

View File

@@ -1287,19 +1287,10 @@ void ShadowModule::set_view(View &view, GPUTexture *depth_tx)
int fb_layers = SHADOW_VIEW_MAX;
if (shadow_technique == ShadowTechnique::ATOMIC_RASTER) {
if (GPU_backend_get_type() == GPU_BACKEND_METAL) {
/* Metal requires a memoryless attachment to create an empty framebuffer.
* Might as well make use of it. */
shadow_depth_fb_tx_.ensure_2d_array(GPU_DEPTH_COMPONENT32F, fb_size, fb_layers, usage);
shadow_depth_accum_tx_.free();
render_fb_.ensure(GPU_ATTACHMENT_TEXTURE(shadow_depth_fb_tx_));
}
else {
/* Create attachment-less framebuffer. */
shadow_depth_fb_tx_.free();
shadow_depth_accum_tx_.free();
render_fb_.ensure(fb_size);
}
/* Create attachment-less framebuffer. */
shadow_depth_fb_tx_.free();
shadow_depth_accum_tx_.free();
render_fb_.ensure(fb_size);
}
else if (shadow_technique == ShadowTechnique::TILE_COPY) {
/* Create memoryless depth attachment for on-tile surface depth accumulation.*/

View File

@@ -152,10 +152,14 @@ void init_interface()
#if defined(GPU_VERTEX_SHADER) && defined(MAT_SHADOW)
void shadow_viewport_layer_set(int view_id, int lod)
{
# ifdef SHADOW_UPDATE_ATOMIC_RASTER
shadow_iface.shadow_view_id = view_id;
# else
/* We still render to a layered frame-buffer in the case of Metal + Tile Based Renderer.
* Since it needs correct depth buffering, each view needs to not overlap each others.
* It doesn't matter much for other platform, so we use that as a way to pass the view id. */
gpu_Layer = view_id;
# endif
gpu_ViewportIndex = lod;
}
#endif
@@ -163,6 +167,10 @@ void shadow_viewport_layer_set(int view_id, int lod)
#if defined(GPU_FRAGMENT_SHADER) && defined(MAT_SHADOW)
int shadow_view_id_get()
{
# ifdef SHADOW_UPDATE_ATOMIC_RASTER
return shadow_iface.shadow_view_id;
# else
return gpu_Layer;
# endif
}
#endif

View File

@@ -226,10 +226,13 @@ GPU_SHADER_CREATE_INFO(eevee_surf_world)
// "eevee_cryptomatte_out",
"eevee_utility_texture");
GPU_SHADER_INTERFACE_INFO(eevee_surf_shadow_atomic_iface, "shadow_iface")
.flat(Type::INT, "shadow_view_id");
GPU_SHADER_CREATE_INFO(eevee_surf_shadow)
.define("DRW_VIEW_LEN", STRINGIFY(SHADOW_VIEW_MAX))
.define("MAT_SHADOW")
.builtins(BuiltinBits::VIEWPORT_INDEX | BuiltinBits::LAYER)
.builtins(BuiltinBits::VIEWPORT_INDEX)
.storage_buf(SHADOW_VIEWPORT_INDEX_BUF_SLOT,
Qualifier::READ,
"uint",
@@ -244,6 +247,7 @@ GPU_SHADER_CREATE_INFO(eevee_surf_shadow_atomic)
/* Early fragment test for speeding up platforms that requires a depth buffer. */
/* NOTE: This removes the possibility of using gl_FragDepth. */
.early_fragment_test(true)
.vertex_out(eevee_surf_shadow_atomic_iface)
.storage_buf(SHADOW_RENDER_MAP_BUF_SLOT,
Qualifier::READ,
"uint",
@@ -257,6 +261,7 @@ GPU_SHADER_CREATE_INFO(eevee_surf_shadow_atomic)
GPU_SHADER_CREATE_INFO(eevee_surf_shadow_tbdr)
.additional_info("eevee_surf_shadow")
.define("SHADOW_UPDATE_TBDR")
.builtins(BuiltinBits::LAYER)
/* F32 color attachment for on-tile depth accumulation without atomics. */
.fragment_out(0, Type::FLOAT, "out_depth", DualBlend::NONE, SHADOW_ROG_ID);

View File

@@ -1084,11 +1084,16 @@ bool MTLContext::ensure_render_pipeline_state(MTLPrimitiveType mtl_prim_type)
}
else {
/* Scissor is disabled, reset to default size as scissor state may have been previously
* assigned on this encoder. */
* assigned on this encoder.
* NOTE: If an attachment-less framebuffer is used, fetch specified width/height rather
* than active attachment width/height as provided by get_default_w/h().*/
uint default_w = render_fb->get_default_width();
uint default_h = render_fb->get_default_height();
bool is_attachmentless = (default_w == 0) && (default_h == 0);
scissor.x = 0;
scissor.y = 0;
scissor.width = render_fb->get_default_width();
scissor.height = render_fb->get_default_height();
scissor.width = (is_attachmentless) ? render_fb->get_width() : default_w;
scissor.height = (is_attachmentless) ? render_fb->get_height() : default_h;
}
/* Scissor state can still be flagged as changed if it is toggled on and off, without