Add support for VK_EXT_depth_clip_control. (#5027)

* Add support for VK_EXT_depth_clip_control.

* Code review feedback

Minor formatting

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Check .DepthClipControl to make sure the host actually supports the feature.

* Review feedback: remove Vulkan platform switch, relying on QueryHostSupportsDepthClipControl to drive the behaviour - OpenGL returns true, and any future platforms that don't support the [-1, 1] depth mode can return false for the transformation.

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
This commit is contained in:
cstamford 2023-05-28 22:31:56 +01:00 committed by GitHub
parent 994f4dc77d
commit dc0dbc50ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 87 additions and 5 deletions

View file

@ -39,6 +39,7 @@ namespace Ryujinx.Graphics.GAL
public readonly bool SupportsViewportMask; public readonly bool SupportsViewportMask;
public readonly bool SupportsViewportSwizzle; public readonly bool SupportsViewportSwizzle;
public readonly bool SupportsIndirectParameters; public readonly bool SupportsIndirectParameters;
public readonly bool SupportsDepthClipControl;
public readonly uint MaximumUniformBuffersPerStage; public readonly uint MaximumUniformBuffersPerStage;
public readonly uint MaximumStorageBuffersPerStage; public readonly uint MaximumStorageBuffersPerStage;
@ -85,6 +86,7 @@ namespace Ryujinx.Graphics.GAL
bool supportsViewportMask, bool supportsViewportMask,
bool supportsViewportSwizzle, bool supportsViewportSwizzle,
bool supportsIndirectParameters, bool supportsIndirectParameters,
bool supportsDepthClipControl,
uint maximumUniformBuffersPerStage, uint maximumUniformBuffersPerStage,
uint maximumStorageBuffersPerStage, uint maximumStorageBuffersPerStage,
uint maximumTexturesPerStage, uint maximumTexturesPerStage,
@ -127,6 +129,7 @@ namespace Ryujinx.Graphics.GAL
SupportsViewportMask = supportsViewportMask; SupportsViewportMask = supportsViewportMask;
SupportsViewportSwizzle = supportsViewportSwizzle; SupportsViewportSwizzle = supportsViewportSwizzle;
SupportsIndirectParameters = supportsIndirectParameters; SupportsIndirectParameters = supportsIndirectParameters;
SupportsDepthClipControl = supportsDepthClipControl;
MaximumUniformBuffersPerStage = maximumUniformBuffersPerStage; MaximumUniformBuffersPerStage = maximumUniformBuffersPerStage;
MaximumStorageBuffersPerStage = maximumStorageBuffersPerStage; MaximumStorageBuffersPerStage = maximumStorageBuffersPerStage;
MaximumTexturesPerStage = maximumTexturesPerStage; MaximumTexturesPerStage = maximumTexturesPerStage;

View file

@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1; private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2; private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor; 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 SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data"; private const string SharedDataFileName = "shared.data";

View file

@ -165,6 +165,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
public bool QueryHostSupportsViewportMask() => _context.Capabilities.SupportsViewportMask; public bool QueryHostSupportsViewportMask() => _context.Capabilities.SupportsViewportMask;
public bool QueryHostSupportsDepthClipControl() => _context.Capabilities.SupportsDepthClipControl;
/// <summary> /// <summary>
/// Converts a packed Maxwell texture format to the shader translator texture format. /// Converts a packed Maxwell texture format to the shader translator texture format.
/// </summary> /// </summary>

View file

@ -163,6 +163,7 @@ namespace Ryujinx.Graphics.OpenGL
supportsViewportMask: HwCapabilities.SupportsViewportArray2, supportsViewportMask: HwCapabilities.SupportsViewportArray2,
supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle, supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle,
supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters, supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters,
supportsDepthClipControl: true,
maximumUniformBuffersPerStage: 13, // TODO: Avoid hardcoding those limits here and get from driver? maximumUniformBuffersPerStage: 13, // TODO: Avoid hardcoding those limits here and get from driver?
maximumStorageBuffersPerStage: 16, maximumStorageBuffersPerStage: 16,
maximumTexturesPerStage: 32, maximumTexturesPerStage: 32,

View file

@ -367,6 +367,15 @@ namespace Ryujinx.Graphics.Shader
return true; return true;
} }
/// <summary>
/// Queries whether the host supports depth clip control.
/// </summary>
/// <returns>True if the GPU and driver supports depth clip control, false otherwise</returns>
bool QueryHostSupportsDepthClipControl()
{
return true;
}
/// <summary> /// <summary>
/// Queries the point size from the GPU state, used when it is not explicitly set on the shader. /// Queries the point size from the GPU state, used when it is not explicitly set on the shader.
/// </summary> /// </summary>

View file

@ -246,7 +246,7 @@ namespace Ryujinx.Graphics.Shader.Translation
this.Store(StorageKind.Output, IoVariable.Position, null, Const(1), this.FPFusedMultiplyAdd(y, yScale, negativeOne)); 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 z = this.Load(StorageKind.Output, IoVariable.Position, null, Const(2));
Operand w = this.Load(StorageKind.Output, IoVariable.Position, null, Const(3)); Operand w = this.Load(StorageKind.Output, IoVariable.Position, null, Const(3));
@ -283,7 +283,7 @@ namespace Ryujinx.Graphics.Shader.Translation
oldYLocal = null; oldYLocal = null;
} }
if (Config.Options.TargetApi == TargetApi.Vulkan && Config.GpuAccessor.QueryTransformDepthMinusOneToOne()) if (Config.GpuAccessor.QueryTransformDepthMinusOneToOne() && !Config.GpuAccessor.QueryHostSupportsDepthClipControl())
{ {
oldZLocal = Local(); oldZLocal = Local();
this.Copy(oldZLocal, this.Load(StorageKind.Output, IoVariable.Position, null, Const(2))); this.Copy(oldZLocal, this.Load(StorageKind.Output, IoVariable.Position, null, Const(2)));

View file

@ -43,6 +43,7 @@ namespace Ryujinx.Graphics.Vulkan
public readonly bool SupportsGeometryShader; public readonly bool SupportsGeometryShader;
public readonly bool SupportsViewportArray2; public readonly bool SupportsViewportArray2;
public readonly bool SupportsHostImportedMemory; public readonly bool SupportsHostImportedMemory;
public readonly bool SupportsDepthClipControl;
public readonly uint MinSubgroupSize; public readonly uint MinSubgroupSize;
public readonly uint MaxSubgroupSize; public readonly uint MaxSubgroupSize;
public readonly ShaderStageFlags RequiredSubgroupSizeStages; public readonly ShaderStageFlags RequiredSubgroupSizeStages;
@ -79,6 +80,7 @@ namespace Ryujinx.Graphics.Vulkan
bool supportsGeometryShader, bool supportsGeometryShader,
bool supportsViewportArray2, bool supportsViewportArray2,
bool supportsHostImportedMemory, bool supportsHostImportedMemory,
bool supportsDepthClipControl,
uint minSubgroupSize, uint minSubgroupSize,
uint maxSubgroupSize, uint maxSubgroupSize,
ShaderStageFlags requiredSubgroupSizeStages, ShaderStageFlags requiredSubgroupSizeStages,
@ -114,6 +116,7 @@ namespace Ryujinx.Graphics.Vulkan
SupportsGeometryShader = supportsGeometryShader; SupportsGeometryShader = supportsGeometryShader;
SupportsViewportArray2 = supportsViewportArray2; SupportsViewportArray2 = supportsViewportArray2;
SupportsHostImportedMemory = supportsHostImportedMemory; SupportsHostImportedMemory = supportsHostImportedMemory;
SupportsDepthClipControl = supportsDepthClipControl;
MinSubgroupSize = minSubgroupSize; MinSubgroupSize = minSubgroupSize;
MaxSubgroupSize = maxSubgroupSize; MaxSubgroupSize = maxSubgroupSize;
RequiredSubgroupSizeStages = requiredSubgroupSizeStages; RequiredSubgroupSizeStages = requiredSubgroupSizeStages;

View file

@ -813,8 +813,12 @@ namespace Ryujinx.Graphics.Vulkan
public void SetDepthMode(DepthMode mode) public void SetDepthMode(DepthMode mode)
{ {
// Currently this is emulated on the shader, because Vulkan had no support for changing the depth mode. bool oldMode = _newState.DepthMode;
// In the future, we may want to use the VK_EXT_depth_clip_control extension to change it here. _newState.DepthMode = mode == DepthMode.MinusOneToOne;
if (_newState.DepthMode != oldMode)
{
SignalStateChange();
}
} }
public void SetDepthTest(DepthTestDescriptor depthTest) public void SetDepthTest(DepthTestDescriptor depthTest)

View file

@ -304,6 +304,12 @@ namespace Ryujinx.Graphics.Vulkan
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFCF) | ((ulong)value << 4); 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<PipelineShaderStageCreateInfo> Stages; public NativeArray<PipelineShaderStageCreateInfo> Stages;
public NativeArray<PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT> StageRequiredSubgroupSizes; public NativeArray<PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT> StageRequiredSubgroupSizes;
public PipelineLayout PipelineLayout; public PipelineLayout PipelineLayout;
@ -331,6 +337,7 @@ namespace Ryujinx.Graphics.Vulkan
LineWidth = 1f; LineWidth = 1f;
SamplesCount = 1; SamplesCount = 1;
DepthMode = true;
} }
public unsafe Auto<DisposablePipeline> CreateComputePipeline( public unsafe Auto<DisposablePipeline> CreateComputePipeline(
@ -482,6 +489,17 @@ namespace Ryujinx.Graphics.Vulkan
PScissors = pScissors PScissors = pScissors
}; };
if (gd.Capabilities.SupportsDepthClipControl)
{
var viewportDepthClipControlState = new PipelineViewportDepthClipControlCreateInfoEXT()
{
SType = StructureType.PipelineViewportDepthClipControlCreateInfoExt,
NegativeOneToOne = DepthMode
};
viewportState.PNext = &viewportDepthClipControlState;
}
var multisampleState = new PipelineMultisampleStateCreateInfo var multisampleState = new PipelineMultisampleStateCreateInfo
{ {
SType = StructureType.PipelineMultisampleStateCreateInfo, SType = StructureType.PipelineMultisampleStateCreateInfo,

View file

@ -41,6 +41,7 @@ namespace Ryujinx.Graphics.Vulkan
"VK_EXT_subgroup_size_control", "VK_EXT_subgroup_size_control",
"VK_NV_geometry_shader_passthrough", "VK_NV_geometry_shader_passthrough",
"VK_NV_viewport_array2", "VK_NV_viewport_array2",
"VK_EXT_depth_clip_control",
"VK_KHR_portability_subset" // As per spec, we should enable this if present. "VK_KHR_portability_subset" // As per spec, we should enable this if present.
}; };
@ -345,6 +346,17 @@ namespace Ryujinx.Graphics.Vulkan
features2.PNext = &supportedFeaturesRobustness2; 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); api.GetPhysicalDeviceFeatures2(physicalDevice.PhysicalDevice, &features2);
var supportedFeatures = features2.Features; var supportedFeatures = features2.Features;
@ -507,6 +519,21 @@ namespace Ryujinx.Graphics.Vulkan
pExtendedFeatures = &featuresCustomBorderColor; 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(); var enabledExtensions = _requiredExtensions.Union(_desirableExtensions.Intersect(physicalDevice.DeviceExtensions)).ToArray();
IntPtr* ppEnabledExtensions = stackalloc IntPtr[enabledExtensions.Length]; IntPtr* ppEnabledExtensions = stackalloc IntPtr[enabledExtensions.Length];

View file

@ -216,6 +216,11 @@ namespace Ryujinx.Graphics.Vulkan
SType = StructureType.PhysicalDeviceCustomBorderColorFeaturesExt SType = StructureType.PhysicalDeviceCustomBorderColorFeaturesExt
}; };
PhysicalDeviceDepthClipControlFeaturesEXT featuresDepthClipControl = new PhysicalDeviceDepthClipControlFeaturesEXT()
{
SType = StructureType.PhysicalDeviceDepthClipControlFeaturesExt
};
PhysicalDevicePortabilitySubsetFeaturesKHR featuresPortabilitySubset = new PhysicalDevicePortabilitySubsetFeaturesKHR() PhysicalDevicePortabilitySubsetFeaturesKHR featuresPortabilitySubset = new PhysicalDevicePortabilitySubsetFeaturesKHR()
{ {
SType = StructureType.PhysicalDevicePortabilitySubsetFeaturesKhr SType = StructureType.PhysicalDevicePortabilitySubsetFeaturesKhr
@ -244,6 +249,14 @@ namespace Ryujinx.Graphics.Vulkan
features2.PNext = &featuresCustomBorderColor; 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"); bool usePortability = _physicalDevice.IsDeviceExtensionPresent("VK_KHR_portability_subset");
if (usePortability) if (usePortability)
@ -310,6 +323,7 @@ namespace Ryujinx.Graphics.Vulkan
_physicalDevice.PhysicalDeviceFeatures.GeometryShader, _physicalDevice.PhysicalDeviceFeatures.GeometryShader,
_physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"), _physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"),
_physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName), _physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName),
supportsDepthClipControl && featuresDepthClipControl.DepthClipControl,
propertiesSubgroupSizeControl.MinSubgroupSize, propertiesSubgroupSizeControl.MinSubgroupSize,
propertiesSubgroupSizeControl.MaxSubgroupSize, propertiesSubgroupSizeControl.MaxSubgroupSize,
propertiesSubgroupSizeControl.RequiredSubgroupSizeStages, propertiesSubgroupSizeControl.RequiredSubgroupSizeStages,
@ -585,6 +599,7 @@ namespace Ryujinx.Graphics.Vulkan
supportsViewportMask: Capabilities.SupportsViewportArray2, supportsViewportMask: Capabilities.SupportsViewportArray2,
supportsViewportSwizzle: false, supportsViewportSwizzle: false,
supportsIndirectParameters: true, supportsIndirectParameters: true,
supportsDepthClipControl: Capabilities.SupportsDepthClipControl,
maximumUniformBuffersPerStage: Constants.MaxUniformBuffersPerStage, maximumUniformBuffersPerStage: Constants.MaxUniformBuffersPerStage,
maximumStorageBuffersPerStage: Constants.MaxStorageBuffersPerStage, maximumStorageBuffersPerStage: Constants.MaxStorageBuffersPerStage,
maximumTexturesPerStage: Constants.MaxTexturesPerStage, maximumTexturesPerStage: Constants.MaxTexturesPerStage,