diff options
Diffstat (limited to 'Ryujinx.Graphics.Vulkan')
-rw-r--r-- | Ryujinx.Graphics.Vulkan/FormatCapabilities.cs | 83 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/PipelineBase.cs | 4 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/PipelineConverter.cs | 2 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/TextureView.cs | 8 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/VulkanConfiguration.cs | 1 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 6 |
6 files changed, 87 insertions, 17 deletions
diff --git a/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs b/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs index 6159f2cc..741d8956 100644 --- a/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs +++ b/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs @@ -8,7 +8,8 @@ namespace Ryujinx.Graphics.Vulkan { class FormatCapabilities { - private readonly FormatFeatureFlags[] _table; + private readonly FormatFeatureFlags[] _bufferTable; + private readonly FormatFeatureFlags[] _optimalTable; private readonly Vk _api; private readonly PhysicalDevice _physicalDevice; @@ -17,14 +18,18 @@ namespace Ryujinx.Graphics.Vulkan { _api = api; _physicalDevice = physicalDevice; - _table = new FormatFeatureFlags[Enum.GetNames(typeof(GAL.Format)).Length]; + + int totalFormats = Enum.GetNames(typeof(GAL.Format)).Length; + + _bufferTable = new FormatFeatureFlags[totalFormats]; + _optimalTable = new FormatFeatureFlags[totalFormats]; } - public bool FormatsSupports(FormatFeatureFlags flags, params GAL.Format[] formats) + public bool BufferFormatsSupport(FormatFeatureFlags flags, params GAL.Format[] formats) { foreach (GAL.Format format in formats) { - if (!FormatSupports(flags, format)) + if (!BufferFormatSupports(flags, format)) { return false; } @@ -33,15 +38,42 @@ namespace Ryujinx.Graphics.Vulkan return true; } - public bool FormatSupports(FormatFeatureFlags flags, GAL.Format format) + public bool OptimalFormatsSupport(FormatFeatureFlags flags, params GAL.Format[] formats) { - var formatFeatureFlags = _table[(int)format]; + foreach (GAL.Format format in formats) + { + if (!OptimalFormatSupports(flags, format)) + { + return false; + } + } + + return true; + } + + public bool BufferFormatSupports(FormatFeatureFlags flags, GAL.Format format) + { + var formatFeatureFlags = _bufferTable[(int)format]; + + if (formatFeatureFlags == 0) + { + _api.GetPhysicalDeviceFormatProperties(_physicalDevice, FormatTable.GetFormat(format), out var fp); + formatFeatureFlags = fp.BufferFeatures; + _bufferTable[(int)format] = formatFeatureFlags; + } + + return (formatFeatureFlags & flags) == flags; + } + + public bool OptimalFormatSupports(FormatFeatureFlags flags, GAL.Format format) + { + var formatFeatureFlags = _optimalTable[(int)format]; if (formatFeatureFlags == 0) { _api.GetPhysicalDeviceFormatProperties(_physicalDevice, FormatTable.GetFormat(format), out var fp); formatFeatureFlags = fp.OptimalTilingFeatures; - _table[(int)format] = formatFeatureFlags; + _optimalTable[(int)format] = formatFeatureFlags; } return (formatFeatureFlags & flags) == flags; @@ -69,7 +101,7 @@ namespace Ryujinx.Graphics.Vulkan requiredFeatures |= FormatFeatureFlags.FormatFeatureStorageImageBit; } - if (!FormatSupports(requiredFeatures, srcFormat) || (IsD24S8(srcFormat) && VulkanConfiguration.ForceD24S8Unsupported)) + if (!OptimalFormatSupports(requiredFeatures, srcFormat) || (IsD24S8(srcFormat) && VulkanConfiguration.ForceD24S8Unsupported)) { // The format is not supported. Can we convert it to a higher precision format? if (IsD24S8(srcFormat)) @@ -85,9 +117,44 @@ namespace Ryujinx.Graphics.Vulkan return format; } + public VkFormat ConvertToVertexVkFormat(GAL.Format srcFormat) + { + var format = FormatTable.GetFormat(srcFormat); + + if (!BufferFormatSupports(FormatFeatureFlags.FormatFeatureVertexBufferBit, srcFormat) || + (IsRGB16IntFloat(srcFormat) && VulkanConfiguration.ForceRGB16IntFloatUnsupported)) + { + // The format is not supported. Can we convert it to an alternative format? + switch (srcFormat) + { + case GAL.Format.R16G16B16Float: + format = VkFormat.R16G16B16A16Sfloat; + break; + case GAL.Format.R16G16B16Sint: + format = VkFormat.R16G16B16A16Sint; + break; + case GAL.Format.R16G16B16Uint: + format = VkFormat.R16G16B16A16Uint; + break; + default: + Logger.Error?.Print(LogClass.Gpu, $"Format {srcFormat} is not supported by the host."); + break; + } + } + + return format; + } + public static bool IsD24S8(GAL.Format format) { return format == GAL.Format.D24UnormS8Uint || format == GAL.Format.S8UintD24Unorm; } + + private static bool IsRGB16IntFloat(GAL.Format format) + { + return format == GAL.Format.R16G16B16Float || + format == GAL.Format.R16G16B16Sint || + format == GAL.Format.R16G16B16Uint; + } } } diff --git a/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/Ryujinx.Graphics.Vulkan/PipelineBase.cs index b66124f5..30eeafb8 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -730,6 +730,8 @@ namespace Ryujinx.Graphics.Vulkan public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs) { + var formatCapabilities = Gd.FormatCapabilities; + int count = Math.Min(Constants.MaxVertexAttributes, vertexAttribs.Length); for (int i = 0; i < count; i++) @@ -740,7 +742,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.Internal.VertexAttributeDescriptions[i] = new VertexInputAttributeDescription( (uint)i, (uint)bufferIndex, - FormatTable.GetFormat(attribute.Format), + formatCapabilities.ConvertToVertexVkFormat(attribute.Format), (uint)attribute.Offset); } diff --git a/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index ff194d71..315df1b1 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -211,7 +211,7 @@ namespace Ryujinx.Graphics.Vulkan pipeline.Internal.VertexAttributeDescriptions[i] = new VertexInputAttributeDescription( (uint)i, (uint)bufferIndex, - FormatTable.GetFormat(attribute.Format), + gd.FormatCapabilities.ConvertToVertexVkFormat(attribute.Format), (uint)attribute.Offset); } diff --git a/Ryujinx.Graphics.Vulkan/TextureView.cs b/Ryujinx.Graphics.Vulkan/TextureView.cs index bb79b09c..d94587bd 100644 --- a/Ryujinx.Graphics.Vulkan/TextureView.cs +++ b/Ryujinx.Graphics.Vulkan/TextureView.cs @@ -451,8 +451,8 @@ namespace Ryujinx.Graphics.Vulkan return; } - else if (_gd.FormatCapabilities.FormatSupports(FormatFeatureFlags.FormatFeatureBlitSrcBit, srcFormat) && - _gd.FormatCapabilities.FormatSupports(FormatFeatureFlags.FormatFeatureBlitDstBit, dstFormat)) + else if (_gd.FormatCapabilities.OptimalFormatSupports(FormatFeatureFlags.FormatFeatureBlitSrcBit, srcFormat) && + _gd.FormatCapabilities.OptimalFormatSupports(FormatFeatureFlags.FormatFeatureBlitDstBit, dstFormat)) { TextureCopy.Blit( _gd.Api, @@ -761,8 +761,8 @@ namespace Ryujinx.Graphics.Vulkan private bool SupportsBlitFromD32FS8ToD32FAndS8() { var formatFeatureFlags = FormatFeatureFlags.FormatFeatureBlitSrcBit | FormatFeatureFlags.FormatFeatureBlitDstBit; - return _gd.FormatCapabilities.FormatSupports(formatFeatureFlags, GAL.Format.D32Float) && - _gd.FormatCapabilities.FormatSupports(formatFeatureFlags, GAL.Format.S8Uint); + return _gd.FormatCapabilities.OptimalFormatSupports(formatFeatureFlags, GAL.Format.D32Float) && + _gd.FormatCapabilities.OptimalFormatSupports(formatFeatureFlags, GAL.Format.S8Uint); } public TextureView GetView(GAL.Format format) diff --git a/Ryujinx.Graphics.Vulkan/VulkanConfiguration.cs b/Ryujinx.Graphics.Vulkan/VulkanConfiguration.cs index 75b45809..752d4f7c 100644 --- a/Ryujinx.Graphics.Vulkan/VulkanConfiguration.cs +++ b/Ryujinx.Graphics.Vulkan/VulkanConfiguration.cs @@ -7,5 +7,6 @@ public const bool UsePushDescriptors = false; public const bool ForceD24S8Unsupported = false; + public const bool ForceRGB16IntFloatUnsupported = false; } } diff --git a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index c7396630..b2f69636 100644 --- a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -377,7 +377,7 @@ namespace Ryujinx.Graphics.Vulkan FormatFeatureFlags.FormatFeatureTransferSrcBit | FormatFeatureFlags.FormatFeatureTransferDstBit; - bool supportsBc123CompressionFormat = FormatCapabilities.FormatsSupports(compressedFormatFeatureFlags, + bool supportsBc123CompressionFormat = FormatCapabilities.OptimalFormatsSupport(compressedFormatFeatureFlags, GAL.Format.Bc1RgbaSrgb, GAL.Format.Bc1RgbaUnorm, GAL.Format.Bc2Srgb, @@ -385,13 +385,13 @@ namespace Ryujinx.Graphics.Vulkan GAL.Format.Bc3Srgb, GAL.Format.Bc3Unorm); - bool supportsBc45CompressionFormat = FormatCapabilities.FormatsSupports(compressedFormatFeatureFlags, + bool supportsBc45CompressionFormat = FormatCapabilities.OptimalFormatsSupport(compressedFormatFeatureFlags, GAL.Format.Bc4Snorm, GAL.Format.Bc4Unorm, GAL.Format.Bc5Snorm, GAL.Format.Bc5Unorm); - bool supportsBc67CompressionFormat = FormatCapabilities.FormatsSupports(compressedFormatFeatureFlags, + bool supportsBc67CompressionFormat = FormatCapabilities.OptimalFormatsSupport(compressedFormatFeatureFlags, GAL.Format.Bc6HSfloat, GAL.Format.Bc6HUfloat, GAL.Format.Bc7Srgb, |