diff --git a/src/Ryujinx.Graphics.GAL/Capabilities.cs b/src/Ryujinx.Graphics.GAL/Capabilities.cs
index a93d384667..48b37d35d4 100644
--- a/src/Ryujinx.Graphics.GAL/Capabilities.cs
+++ b/src/Ryujinx.Graphics.GAL/Capabilities.cs
@@ -39,6 +39,7 @@ namespace Ryujinx.Graphics.GAL
public readonly bool SupportsViewportMask;
public readonly bool SupportsViewportSwizzle;
public readonly bool SupportsIndirectParameters;
+ public readonly bool SupportsDepthClipControl;
public readonly uint MaximumUniformBuffersPerStage;
public readonly uint MaximumStorageBuffersPerStage;
@@ -85,6 +86,7 @@ namespace Ryujinx.Graphics.GAL
bool supportsViewportMask,
bool supportsViewportSwizzle,
bool supportsIndirectParameters,
+ bool supportsDepthClipControl,
uint maximumUniformBuffersPerStage,
uint maximumStorageBuffersPerStage,
uint maximumTexturesPerStage,
@@ -127,6 +129,7 @@ namespace Ryujinx.Graphics.GAL
SupportsViewportMask = supportsViewportMask;
SupportsViewportSwizzle = supportsViewportSwizzle;
SupportsIndirectParameters = supportsIndirectParameters;
+ SupportsDepthClipControl = supportsDepthClipControl;
MaximumUniformBuffersPerStage = maximumUniformBuffersPerStage;
MaximumStorageBuffersPerStage = maximumStorageBuffersPerStage;
MaximumTexturesPerStage = maximumTexturesPerStage;
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
index e2346bd0b8..7f83f58800 100644
--- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
+++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
- private const uint CodeGenVersion = 5110;
+ private const uint CodeGenVersion = 5027;
private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data";
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs
index e4e1e0d611..d206aad0b8 100644
--- a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs
+++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs
@@ -165,6 +165,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
public bool QueryHostSupportsViewportMask() => _context.Capabilities.SupportsViewportMask;
+ public bool QueryHostSupportsDepthClipControl() => _context.Capabilities.SupportsDepthClipControl;
+
///
/// Converts a packed Maxwell texture format to the shader translator texture format.
///
diff --git a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs
index 7d5fe8931b..161191b854 100644
--- a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs
+++ b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs
@@ -163,6 +163,7 @@ namespace Ryujinx.Graphics.OpenGL
supportsViewportMask: HwCapabilities.SupportsViewportArray2,
supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle,
supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters,
+ supportsDepthClipControl: true,
maximumUniformBuffersPerStage: 13, // TODO: Avoid hardcoding those limits here and get from driver?
maximumStorageBuffersPerStage: 16,
maximumTexturesPerStage: 32,
diff --git a/src/Ryujinx.Graphics.Shader/IGpuAccessor.cs b/src/Ryujinx.Graphics.Shader/IGpuAccessor.cs
index 2207156cdb..3be5088e45 100644
--- a/src/Ryujinx.Graphics.Shader/IGpuAccessor.cs
+++ b/src/Ryujinx.Graphics.Shader/IGpuAccessor.cs
@@ -367,6 +367,15 @@ namespace Ryujinx.Graphics.Shader
return true;
}
+ ///
+ /// Queries whether the host supports depth clip control.
+ ///
+ /// True if the GPU and driver supports depth clip control, false otherwise
+ bool QueryHostSupportsDepthClipControl()
+ {
+ return true;
+ }
+
///
/// Queries the point size from the GPU state, used when it is not explicitly set on the shader.
///
diff --git a/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
index 2786caaa0a..6ca74a379a 100644
--- a/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
+++ b/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
@@ -246,7 +246,7 @@ namespace Ryujinx.Graphics.Shader.Translation
this.Store(StorageKind.Output, IoVariable.Position, null, Const(1), this.FPFusedMultiplyAdd(y, yScale, negativeOne));
}
- if (Config.Options.TargetApi == TargetApi.Vulkan && Config.GpuAccessor.QueryTransformDepthMinusOneToOne())
+ if (Config.GpuAccessor.QueryTransformDepthMinusOneToOne() && !Config.GpuAccessor.QueryHostSupportsDepthClipControl())
{
Operand z = this.Load(StorageKind.Output, IoVariable.Position, null, Const(2));
Operand w = this.Load(StorageKind.Output, IoVariable.Position, null, Const(3));
@@ -283,7 +283,7 @@ namespace Ryujinx.Graphics.Shader.Translation
oldYLocal = null;
}
- if (Config.Options.TargetApi == TargetApi.Vulkan && Config.GpuAccessor.QueryTransformDepthMinusOneToOne())
+ if (Config.GpuAccessor.QueryTransformDepthMinusOneToOne() && !Config.GpuAccessor.QueryHostSupportsDepthClipControl())
{
oldZLocal = Local();
this.Copy(oldZLocal, this.Load(StorageKind.Output, IoVariable.Position, null, Const(2)));
diff --git a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs
index 4b9ace3aa3..f600d93f00 100644
--- a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs
+++ b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs
@@ -43,6 +43,7 @@ namespace Ryujinx.Graphics.Vulkan
public readonly bool SupportsGeometryShader;
public readonly bool SupportsViewportArray2;
public readonly bool SupportsHostImportedMemory;
+ public readonly bool SupportsDepthClipControl;
public readonly uint MinSubgroupSize;
public readonly uint MaxSubgroupSize;
public readonly ShaderStageFlags RequiredSubgroupSizeStages;
@@ -79,6 +80,7 @@ namespace Ryujinx.Graphics.Vulkan
bool supportsGeometryShader,
bool supportsViewportArray2,
bool supportsHostImportedMemory,
+ bool supportsDepthClipControl,
uint minSubgroupSize,
uint maxSubgroupSize,
ShaderStageFlags requiredSubgroupSizeStages,
@@ -114,6 +116,7 @@ namespace Ryujinx.Graphics.Vulkan
SupportsGeometryShader = supportsGeometryShader;
SupportsViewportArray2 = supportsViewportArray2;
SupportsHostImportedMemory = supportsHostImportedMemory;
+ SupportsDepthClipControl = supportsDepthClipControl;
MinSubgroupSize = minSubgroupSize;
MaxSubgroupSize = maxSubgroupSize;
RequiredSubgroupSizeStages = requiredSubgroupSizeStages;
diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
index ce6148e2f7..b4eccfbb22 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
@@ -813,8 +813,12 @@ namespace Ryujinx.Graphics.Vulkan
public void SetDepthMode(DepthMode mode)
{
- // Currently this is emulated on the shader, because Vulkan had no support for changing the depth mode.
- // In the future, we may want to use the VK_EXT_depth_clip_control extension to change it here.
+ bool oldMode = _newState.DepthMode;
+ _newState.DepthMode = mode == DepthMode.MinusOneToOne;
+ if (_newState.DepthMode != oldMode)
+ {
+ SignalStateChange();
+ }
}
public void SetDepthTest(DepthTestDescriptor depthTest)
diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
index a3d8dd6fbe..aff3f13f01 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
@@ -304,6 +304,12 @@ namespace Ryujinx.Graphics.Vulkan
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFCF) | ((ulong)value << 4);
}
+ public bool DepthMode
+ {
+ get => ((Internal.Id9 >> 6) & 0x1) != 0UL;
+ set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6);
+ }
+
public NativeArray Stages;
public NativeArray StageRequiredSubgroupSizes;
public PipelineLayout PipelineLayout;
@@ -331,6 +337,7 @@ namespace Ryujinx.Graphics.Vulkan
LineWidth = 1f;
SamplesCount = 1;
+ DepthMode = true;
}
public unsafe Auto CreateComputePipeline(
@@ -482,6 +489,17 @@ namespace Ryujinx.Graphics.Vulkan
PScissors = pScissors
};
+ if (gd.Capabilities.SupportsDepthClipControl)
+ {
+ var viewportDepthClipControlState = new PipelineViewportDepthClipControlCreateInfoEXT()
+ {
+ SType = StructureType.PipelineViewportDepthClipControlCreateInfoExt,
+ NegativeOneToOne = DepthMode
+ };
+
+ viewportState.PNext = &viewportDepthClipControlState;
+ }
+
var multisampleState = new PipelineMultisampleStateCreateInfo
{
SType = StructureType.PipelineMultisampleStateCreateInfo,
diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs
index 499a9ef78c..51a3b129ac 100644
--- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs
+++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs
@@ -41,6 +41,7 @@ namespace Ryujinx.Graphics.Vulkan
"VK_EXT_subgroup_size_control",
"VK_NV_geometry_shader_passthrough",
"VK_NV_viewport_array2",
+ "VK_EXT_depth_clip_control",
"VK_KHR_portability_subset" // As per spec, we should enable this if present.
};
@@ -345,6 +346,17 @@ namespace Ryujinx.Graphics.Vulkan
features2.PNext = &supportedFeaturesRobustness2;
}
+ PhysicalDeviceDepthClipControlFeaturesEXT supportedFeaturesDepthClipControl = new PhysicalDeviceDepthClipControlFeaturesEXT()
+ {
+ SType = StructureType.PhysicalDeviceDepthClipControlFeaturesExt,
+ PNext = features2.PNext
+ };
+
+ if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_depth_clip_control"))
+ {
+ features2.PNext = &supportedFeaturesDepthClipControl;
+ }
+
api.GetPhysicalDeviceFeatures2(physicalDevice.PhysicalDevice, &features2);
var supportedFeatures = features2.Features;
@@ -507,6 +519,21 @@ namespace Ryujinx.Graphics.Vulkan
pExtendedFeatures = &featuresCustomBorderColor;
}
+ PhysicalDeviceDepthClipControlFeaturesEXT featuresDepthClipControl;
+
+ if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_depth_clip_control") &&
+ supportedFeaturesDepthClipControl.DepthClipControl)
+ {
+ featuresDepthClipControl = new PhysicalDeviceDepthClipControlFeaturesEXT()
+ {
+ SType = StructureType.PhysicalDeviceDepthClipControlFeaturesExt,
+ PNext = pExtendedFeatures,
+ DepthClipControl = true
+ };
+
+ pExtendedFeatures = &featuresDepthClipControl;
+ }
+
var enabledExtensions = _requiredExtensions.Union(_desirableExtensions.Intersect(physicalDevice.DeviceExtensions)).ToArray();
IntPtr* ppEnabledExtensions = stackalloc IntPtr[enabledExtensions.Length];
diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
index 4f3f72345b..3987be9b47 100644
--- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
+++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
@@ -216,6 +216,11 @@ namespace Ryujinx.Graphics.Vulkan
SType = StructureType.PhysicalDeviceCustomBorderColorFeaturesExt
};
+ PhysicalDeviceDepthClipControlFeaturesEXT featuresDepthClipControl = new PhysicalDeviceDepthClipControlFeaturesEXT()
+ {
+ SType = StructureType.PhysicalDeviceDepthClipControlFeaturesExt
+ };
+
PhysicalDevicePortabilitySubsetFeaturesKHR featuresPortabilitySubset = new PhysicalDevicePortabilitySubsetFeaturesKHR()
{
SType = StructureType.PhysicalDevicePortabilitySubsetFeaturesKhr
@@ -244,6 +249,14 @@ namespace Ryujinx.Graphics.Vulkan
features2.PNext = &featuresCustomBorderColor;
}
+ bool supportsDepthClipControl = _physicalDevice.IsDeviceExtensionPresent("VK_EXT_depth_clip_control");
+
+ if (supportsDepthClipControl)
+ {
+ featuresDepthClipControl.PNext = features2.PNext;
+ features2.PNext = &featuresDepthClipControl;
+ }
+
bool usePortability = _physicalDevice.IsDeviceExtensionPresent("VK_KHR_portability_subset");
if (usePortability)
@@ -310,6 +323,7 @@ namespace Ryujinx.Graphics.Vulkan
_physicalDevice.PhysicalDeviceFeatures.GeometryShader,
_physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"),
_physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName),
+ supportsDepthClipControl && featuresDepthClipControl.DepthClipControl,
propertiesSubgroupSizeControl.MinSubgroupSize,
propertiesSubgroupSizeControl.MaxSubgroupSize,
propertiesSubgroupSizeControl.RequiredSubgroupSizeStages,
@@ -585,6 +599,7 @@ namespace Ryujinx.Graphics.Vulkan
supportsViewportMask: Capabilities.SupportsViewportArray2,
supportsViewportSwizzle: false,
supportsIndirectParameters: true,
+ supportsDepthClipControl: Capabilities.SupportsDepthClipControl,
maximumUniformBuffersPerStage: Constants.MaxUniformBuffersPerStage,
maximumStorageBuffersPerStage: Constants.MaxStorageBuffersPerStage,
maximumTexturesPerStage: Constants.MaxTexturesPerStage,