summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorCrossVR <jules.blok@gmail.com>2025-07-21 05:48:04 +0900
committerCrossVR <jules.blok@gmail.com>2025-07-21 14:07:26 +0900
commit0ace5f5d3db86e3f98e421c0ed3495ffe39a02fc (patch)
tree14581223c7ae0fe9d0f0554d3aa6647fb06cfe45 /Source/Core
parentdccd8709d8c8df70493def8813dd8039dfe5ba16 (diff)
Vulkan: Add support for unrestricted depth range.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/VideoBackends/Vulkan/VKPipeline.cpp9
-rw-r--r--Source/Core/VideoBackends/Vulkan/VulkanContext.cpp11
-rw-r--r--Source/Core/VideoCommon/BPFunctions.cpp13
-rw-r--r--Source/Core/VideoCommon/VertexShaderManager.cpp5
-rw-r--r--Source/Core/VideoCommon/VideoCommon.h6
-rw-r--r--Source/Core/VideoCommon/VideoConfig.h1
6 files changed, 35 insertions, 10 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/VKPipeline.cpp b/Source/Core/VideoBackends/Vulkan/VKPipeline.cpp
index be3aae1390..1b8dd0eb9a 100644
--- a/Source/Core/VideoBackends/Vulkan/VKPipeline.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VKPipeline.cpp
@@ -368,12 +368,19 @@ std::unique_ptr<VKPipeline> VKPipeline::Create(const AbstractPipelineConfig& con
GetVulkanColorBlendState(config.blending_state, blend_attachment_states.data(),
static_cast<uint32_t>(blend_attachment_states.size()));
+ static const VkDepthClampRangeEXT clamp_range = {0.0f, MAX_EFB_DEPTH};
+ static const VkPipelineViewportDepthClampControlCreateInfoEXT depth_clamp_state = {
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLAMP_CONTROL_CREATE_INFO_EXT, nullptr,
+ VK_DEPTH_CLAMP_MODE_USER_DEFINED_RANGE_EXT, // VkDepthClampModeEXT depthClampMode
+ &clamp_range // const VkDepthClampRangeEXT* pDepthClampRange
+ };
+
// This viewport isn't used, but needs to be specified anyway.
static const VkViewport viewport = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
static const VkRect2D scissor = {{0, 0}, {1, 1}};
static const VkPipelineViewportStateCreateInfo viewport_state = {
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
- nullptr,
+ &depth_clamp_state,
0, // VkPipelineViewportStateCreateFlags flags;
1, // uint32_t viewportCount
&viewport, // const VkViewport* pViewports
diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
index c6ff5e148d..60580aff40 100644
--- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
@@ -459,6 +459,7 @@ void VulkanContext::PopulateBackendInfo(BackendInfo* backend_info)
backend_info->bSupportsDynamicVertexLoader = true; // Assumed support.
backend_info->bSupportsVSLinePointExpand = true; // Assumed support.
backend_info->bSupportsHDROutput = true; // Assumed support.
+ backend_info->bSupportsUnrestrictedDepthRange = false; // Dependent on features.
}
void VulkanContext::PopulateBackendInfoAdapters(BackendInfo* backend_info, const GPUList& gpu_list)
@@ -663,6 +664,16 @@ bool VulkanContext::SelectDeviceExtensions(bool enable_surface)
AddExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, false);
AddExtension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, false);
+ if (!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_D32F_CLEAR))
+ {
+ // Unrestricted depth range is one of the few extensions that changes the behavior
+ // of Vulkan just by being enabled, so we rely on lazy evaluation to ensure it is
+ // not enabled unless depth clamp control is supported.
+ g_backend_info.bSupportsUnrestrictedDepthRange =
+ AddExtension(VK_EXT_DEPTH_CLAMP_CONTROL_EXTENSION_NAME, false) &&
+ AddExtension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME, false);
+ }
+
return true;
}
diff --git a/Source/Core/VideoCommon/BPFunctions.cpp b/Source/Core/VideoCommon/BPFunctions.cpp
index 0b20bcfd8a..444b1dbc4f 100644
--- a/Source/Core/VideoCommon/BPFunctions.cpp
+++ b/Source/Core/VideoCommon/BPFunctions.cpp
@@ -216,17 +216,12 @@ void SetScissorAndViewport()
height *= -1;
}
- // The maximum depth that is written to the depth buffer should never exceed this value.
- // This is necessary because we use a 2^24 divisor for all our depth values to prevent
- // floating-point round-trip errors. However the console GPU doesn't ever write a value
- // to the depth buffer that exceeds 2^24 - 1.
- constexpr float GX_MAX_DEPTH = 16777215.0f / 16777216.0f;
if (!g_backend_info.bSupportsDepthClamp)
{
// There's no way to support oversized depth ranges in this situation. Let's just clamp the
// range to the maximum value supported by the console GPU and hope for the best.
- min_depth = std::clamp(min_depth, 0.0f, GX_MAX_DEPTH);
- max_depth = std::clamp(max_depth, 0.0f, GX_MAX_DEPTH);
+ min_depth = std::clamp(min_depth, 0.0f, MAX_EFB_DEPTH);
+ max_depth = std::clamp(max_depth, 0.0f, MAX_EFB_DEPTH);
}
if (VertexShaderManager::UseVertexDepthRange())
@@ -235,13 +230,13 @@ void SetScissorAndViewport()
// Taking into account whether the depth range is inverted or not.
if (xfmem.viewport.zRange < 0.0f && g_backend_info.bSupportsReversedDepthRange)
{
- min_depth = GX_MAX_DEPTH;
+ min_depth = MAX_EFB_DEPTH;
max_depth = 0.0f;
}
else
{
min_depth = 0.0f;
- max_depth = GX_MAX_DEPTH;
+ max_depth = MAX_EFB_DEPTH;
}
}
diff --git a/Source/Core/VideoCommon/VertexShaderManager.cpp b/Source/Core/VideoCommon/VertexShaderManager.cpp
index 976cff00f6..4dba5432bc 100644
--- a/Source/Core/VideoCommon/VertexShaderManager.cpp
+++ b/Source/Core/VideoCommon/VertexShaderManager.cpp
@@ -131,6 +131,11 @@ void VertexShaderManager::SetProjectionMatrix(XFStateManager& xf_state_manager)
bool VertexShaderManager::UseVertexDepthRange()
{
+ // Backend has full support for unrestricted depth ranges including the ability to clamp the
+ // final depth value to MAX_EFB_DEPTH.
+ if (g_backend_info.bSupportsUnrestrictedDepthRange)
+ return false;
+
// We can't compute the depth range in the vertex shader if we don't support depth clamp.
if (!g_backend_info.bSupportsDepthClamp)
return false;
diff --git a/Source/Core/VideoCommon/VideoCommon.h b/Source/Core/VideoCommon/VideoCommon.h
index 517e8b3e9b..abc79a847d 100644
--- a/Source/Core/VideoCommon/VideoCommon.h
+++ b/Source/Core/VideoCommon/VideoCommon.h
@@ -15,6 +15,12 @@
constexpr u32 EFB_WIDTH = 640u;
constexpr u32 EFB_HEIGHT = 528u;
+// The maximum depth that is written to the depth buffer should never exceed this value.
+// This is necessary because we use a 2^24 divisor for all our depth values to prevent
+// floating-point round-trip errors. However the console GPU doesn't ever write a value
+// to the depth buffer that exceeds 2^24 - 1.
+constexpr float MAX_EFB_DEPTH = 16777215.0f / 16777216.0f;
+
// Max XFB width is 720. You can only copy out 640 wide areas of efb to XFB
// so you need multiple copies to do the full width.
// The VI can do horizontal scaling (TODO: emulate).
diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h
index a268278eca..a0baaa666c 100644
--- a/Source/Core/VideoCommon/VideoConfig.h
+++ b/Source/Core/VideoCommon/VideoConfig.h
@@ -180,6 +180,7 @@ struct BackendInfo
bool bSupportsVSLinePointExpand = false;
bool bSupportsGLLayerInFS = true;
bool bSupportsHDROutput = false;
+ bool bSupportsUnrestrictedDepthRange = false;
};
extern BackendInfo g_backend_info;