[GPU] Allow depth clamping instead of clipping

For now, this adds a depth clamp override to both backends that's kept disabled by default.

494707EE needs this for its setup draws that feed its lighting passes. It could be that guest clipping / host near and flare Z planes aren't cleanly interchangeable at the edge of the clip volume.
This commit is contained in:
goldislead
2026-08-03 00:13:05 -07:00
committed by Radosław Gliński
parent 6ff2a56f6a
commit 25597a5465
4 changed files with 33 additions and 2 deletions

View File

@@ -1449,7 +1449,15 @@ bool PipelineCache::GetCurrentStateDescription(
if (tessellated && cvars::d3d12_tessellation_wireframe) {
description_out.fill_mode_wireframe = 1;
}
description_out.depth_clip = !regs.Get<reg::PA_CL_CLIP_CNTL>().clip_disable;
// With force_depth_clamp, use the host viewport clamp instead of near and far
// Z plane clipping. X/Y/W clipping is unchanged. Both 494707EE and 41560881
// have passes that rely on alpha inputs that currently gets dropped by
// near-plane clipping.
// TODO(boma): Investigate whether the difference is in shader arithmetic or
// the clipper itself.
description_out.depth_clip = !regs.Get<reg::PA_CL_CLIP_CNTL>().clip_disable &&
!cvars::force_depth_clamp;
bool depth_stencil_bound_and_used = false;
if (!edram_rov_used) {
// Depth/stencil. No stencil, always passing depth test and no depth writing

View File

@@ -125,3 +125,10 @@ DEFINE_bool(
"This fixes(hide) issues with black ground in AC6. Use only in AC6. "
"Might cause issues in other titles.",
"HACKS");
DEFINE_bool(
force_depth_clamp, false,
"Use host depth clamping instead of near and far plane clipping when "
"guest clipping is enabled. X/Y/W clipping is unaffected. On Vulkan, "
"this requires depthClamp support.",
"GPU");

View File

@@ -48,6 +48,8 @@ DECLARE_bool(gpu_3d_to_2d_texture);
DECLARE_bool(ac6_ground_fix);
DECLARE_bool(force_depth_clamp);
#define XE_GPU_FINE_GRAINED_DRAW_SCOPES 1
#endif // XENIA_GPU_GPU_FLAGS_H_

View File

@@ -196,6 +196,13 @@ bool VulkanPipelineCache::Initialize() {
}
}
if (cvars::force_depth_clamp && !vulkan_device->properties().depthClamp) {
XELOGW(
"force_depth_clamp is enabled, but the device doesn't support depth "
"clamping - guest draws with clipping enabled will still be clipped "
"to the host planes");
}
// Create placeholder pixel shader for pipeline hot-swap (stutter reduction).
placeholder_pixel_shader_ = ui::vulkan::util::CreateShaderModule(
vulkan_device, shaders::placeholder_ps, sizeof(shaders::placeholder_ps));
@@ -1267,9 +1274,16 @@ bool VulkanPipelineCache::GetCurrentStateDescription(
description_out.primitive_restart =
primitive_processing_result.host_primitive_reset_enabled;
// With force_depth_clamp, use the host viewport clamp instead of near and far
// Z plane clipping. X/Y/W clipping is unchanged. Both 494707EE and 41560881
// have passes that rely on alpha inputs that currently gets dropped by
// near-plane clipping.
// TODO(boma): Investigate whether the difference is in shader arithmetic or
// the clipper itself.
description_out.depth_clamp_enable =
device_properties.depthClamp &&
regs.Get<reg::PA_CL_CLIP_CNTL>().clip_disable;
(regs.Get<reg::PA_CL_CLIP_CNTL>().clip_disable ||
cvars::force_depth_clamp);
// TODO(Triang3l): Tessellation.
bool primitive_polygonal = draw_util::IsPrimitivePolygonal(regs);