aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Vulkan/PipelineState.cs')
-rw-r--r--src/Ryujinx.Graphics.Vulkan/PipelineState.cs49
1 files changed, 47 insertions, 2 deletions
diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
index dccc8ce6..a3d8dd6f 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
@@ -1,4 +1,5 @@
-using Silk.NET.Vulkan;
+using Ryujinx.Common.Memory;
+using Silk.NET.Vulkan;
using System;
namespace Ryujinx.Graphics.Vulkan
@@ -308,6 +309,8 @@ namespace Ryujinx.Graphics.Vulkan
public PipelineLayout PipelineLayout;
public SpecData SpecializationData;
+ private Array32<VertexInputAttributeDescription> _vertexAttributeDescriptions2;
+
public void Initialize()
{
Stages = new NativeArray<PipelineShaderStageCreateInfo>(Constants.MaxShaderStages);
@@ -400,7 +403,15 @@ namespace Ryujinx.Graphics.Vulkan
Pipeline pipelineHandle = default;
+ bool isMoltenVk = gd.IsMoltenVk;
+
+ if (isMoltenVk)
+ {
+ UpdateVertexAttributeDescriptions();
+ }
+
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0])
+ fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0])
fixed (VertexInputBindingDescription* pVertexBindingDescriptions = &Internal.VertexBindingDescriptions[0])
fixed (Viewport* pViewports = &Internal.Viewports[0])
fixed (Rect2D* pScissors = &Internal.Scissors[0])
@@ -410,7 +421,7 @@ namespace Ryujinx.Graphics.Vulkan
{
SType = StructureType.PipelineVertexInputStateCreateInfo,
VertexAttributeDescriptionCount = VertexAttributeDescriptionsCount,
- PVertexAttributeDescriptions = pVertexAttributeDescriptions,
+ PVertexAttributeDescriptions = isMoltenVk ? pVertexAttributeDescriptions2 : pVertexAttributeDescriptions,
VertexBindingDescriptionCount = VertexBindingDescriptionsCount,
PVertexBindingDescriptions = pVertexBindingDescriptions
};
@@ -612,6 +623,40 @@ namespace Ryujinx.Graphics.Vulkan
}
}
+ private void UpdateVertexAttributeDescriptions()
+ {
+ // Vertex attributes exceeding the stride are invalid.
+ // In metal, they cause glitches with the vertex shader fetching incorrect values.
+ // To work around this, we reduce the format to something that doesn't exceed the stride if possible.
+ // The assumption is that the exceeding components are not actually accessed on the shader.
+
+ for (int index = 0; index < VertexAttributeDescriptionsCount; index++)
+ {
+ var attribute = Internal.VertexAttributeDescriptions[index];
+ ref var vb = ref Internal.VertexBindingDescriptions[(int)attribute.Binding];
+
+ Format format = attribute.Format;
+
+ while (vb.Stride != 0 && attribute.Offset + FormatTable.GetAttributeFormatSize(format) > vb.Stride)
+ {
+ 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;
+ }
+
+ attribute.Format = format;
+ _vertexAttributeDescriptions2[index] = attribute;
+ }
+ }
+
public void Dispose()
{
Stages.Dispose();