From 597388ecda35b0feaa3b678b7216689a5d84bbac Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 28 May 2023 19:17:07 -0300 Subject: [PATCH] Fix incorrect vertex attribute format change (#5112) * Fix incorrect vertex attribute format change * Only change vertex format if the host supports the new format --- .../FormatCapabilities.cs | 7 +++ src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 1 - src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 50 +++++++++++++------ 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs index 7019dfd9..a2ebc518 100644 --- a/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs +++ b/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs @@ -65,6 +65,13 @@ namespace Ryujinx.Graphics.Vulkan return (formatFeatureFlags & flags) == flags; } + public bool BufferFormatSupports(FormatFeatureFlags flags, VkFormat format) + { + _api.GetPhysicalDeviceFormatProperties(_physicalDevice, format, out var fp); + + return (fp.BufferFeatures & flags) == flags; + } + public bool OptimalFormatSupports(FormatFeatureFlags flags, GAL.Format format) { var formatFeatureFlags = _optimalTable[(int)format]; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index b4eccfbb..c254d378 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -551,7 +551,6 @@ namespace Ryujinx.Graphics.Vulkan (uint)maxDrawCount, (uint)stride); } - } else { diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index aff3f13f..1a396b5c 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -414,7 +414,7 @@ namespace Ryujinx.Graphics.Vulkan if (isMoltenVk) { - UpdateVertexAttributeDescriptions(); + UpdateVertexAttributeDescriptions(gd); } fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0]) @@ -641,7 +641,7 @@ namespace Ryujinx.Graphics.Vulkan } } - private void UpdateVertexAttributeDescriptions() + private void UpdateVertexAttributeDescriptions(VulkanRenderer gd) { // Vertex attributes exceeding the stride are invalid. // In metal, they cause glitches with the vertex shader fetching incorrect values. @@ -651,30 +651,52 @@ namespace Ryujinx.Graphics.Vulkan for (int index = 0; index < VertexAttributeDescriptionsCount; index++) { var attribute = Internal.VertexAttributeDescriptions[index]; - ref var vb = ref Internal.VertexBindingDescriptions[(int)attribute.Binding]; + int vbIndex = GetVertexBufferIndex(attribute.Binding); - Format format = attribute.Format; - - while (vb.Stride != 0 && attribute.Offset + FormatTable.GetAttributeFormatSize(format) > vb.Stride) + if (vbIndex >= 0) { - Format newFormat = FormatTable.DropLastComponent(format); + ref var vb = ref Internal.VertexBindingDescriptions[vbIndex]; - if (newFormat == format) + Format format = attribute.Format; + + while (vb.Stride != 0 && attribute.Offset + FormatTable.GetAttributeFormatSize(format) > vb.Stride) { - // That case means we failed to find a format that fits within the stride, - // so just restore the original format and give up. - format = attribute.Format; - break; + Format newFormat = FormatTable.DropLastComponent(format); + + if (newFormat == format) + { + // That case means we failed to find a format that fits within the stride, + // so just restore the original format and give up. + format = attribute.Format; + break; + } + + format = newFormat; } - format = newFormat; + if (attribute.Format != format && gd.FormatCapabilities.BufferFormatSupports(FormatFeatureFlags.VertexBufferBit, format)) + { + attribute.Format = format; + } } - attribute.Format = format; _vertexAttributeDescriptions2[index] = attribute; } } + private int GetVertexBufferIndex(uint binding) + { + for (int index = 0; index < VertexBindingDescriptionsCount; index++) + { + if (Internal.VertexBindingDescriptions[index].Binding == binding) + { + return index; + } + } + + return -1; + } + public void Dispose() { Stages.Dispose();