diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
index c8deb84cc..33c33d4c8 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
@@ -1,4 +1,5 @@
using Ryujinx.Common.Logging;
+using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Engine.Types;
using Ryujinx.Graphics.Gpu.Image;
@@ -1267,6 +1268,20 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// Current GPU channel state
private GpuChannelGraphicsState GetGraphicsState()
{
+ ref var vertexAttribState = ref _state.State.VertexAttribState;
+
+ Array32 attributeTypes = new Array32();
+
+ for (int location = 0; location < attributeTypes.Length; location++)
+ {
+ attributeTypes[location] = vertexAttribState[location].UnpackType() switch
+ {
+ 3 => AttributeType.Sint,
+ 4 => AttributeType.Uint,
+ _ => AttributeType.Float
+ };
+ }
+
return new GpuChannelGraphicsState(
_state.State.EarlyZForce,
_drawState.Topology,
@@ -1277,7 +1292,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_state.State.PointSize,
_state.State.AlphaTestEnable,
_state.State.AlphaTestFunc,
- _state.State.AlphaTestRef);
+ _state.State.AlphaTestRef,
+ ref attributeTypes);
}
private DepthMode GetDepthMode()
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Migration.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Migration.cs
index bd7a86da8..49acd3add 100644
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Migration.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/Cache/Migration.cs
@@ -163,6 +163,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache
_ => PrimitiveTopology.Points
};
+ Array32 attributeTypes = default;
+
GpuChannelGraphicsState graphicsState = new GpuChannelGraphicsState(
accessorHeader.StateFlags.HasFlag(GuestGpuStateFlags.EarlyZForce),
topology,
@@ -173,7 +175,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache
1f,
false,
CompareOp.Always,
- 0f);
+ 0f,
+ ref attributeTypes);
TransformFeedbackDescriptor[] tfdNew = null;
diff --git a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs
index ebbd18b5c..a53be4a7f 100644
--- a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs
@@ -15,7 +15,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
{
private readonly GpuChannel _channel;
private readonly GpuAccessorState _state;
- private readonly AttributeType[] _attributeTypes;
private readonly int _stageIndex;
private readonly bool _compute;
private readonly bool _isVulkan;
@@ -26,19 +25,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// GPU context
/// GPU channel
/// Current GPU state
- /// Type of the vertex attributes consumed by the shader
/// Graphics shader stage index (0 = Vertex, 4 = Fragment)
public GpuAccessor(
GpuContext context,
GpuChannel channel,
GpuAccessorState state,
- AttributeType[] attributeTypes,
int stageIndex) : base(context, state.ResourceCounts, stageIndex)
{
_isVulkan = context.Capabilities.Api == TargetApi.Vulkan;
_channel = channel;
_state = state;
- _attributeTypes = attributeTypes;
_stageIndex = stageIndex;
}
@@ -108,12 +104,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
///
public AttributeType QueryAttributeType(int location)
{
- if (_attributeTypes != null)
- {
- return _attributeTypes[location];
- }
-
- return AttributeType.Float;
+ return _state.GraphicsState.AttributeTypes[location];
}
///
diff --git a/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs b/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs
index 486d93b5b..f52e040f3 100644
--- a/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs
@@ -1,5 +1,7 @@
+using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Engine.Threed;
+using Ryujinx.Graphics.Shader;
namespace Ryujinx.Graphics.Gpu.Shader
{
@@ -60,6 +62,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
///
public readonly float AlphaTestReference;
+ ///
+ /// Type of the vertex attributes consumed by the shader.
+ ///
+ public Array32 AttributeTypes;
+
///
/// Creates a new GPU graphics state.
///
@@ -73,6 +80,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// Indicates whenever alpha test is enabled
/// When alpha test is enabled, indicates the comparison that decides if the fragment is discarded
/// When alpha test is enabled, indicates the value to compare with the fragment output alpha
+ /// Type of the vertex attributes consumed by the shader
public GpuChannelGraphicsState(
bool earlyZForce,
PrimitiveTopology topology,
@@ -83,7 +91,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
float pointSize,
bool alphaTestEnable,
CompareOp alphaTestCompare,
- float alphaTestReference)
+ float alphaTestReference,
+ ref Array32 attributeTypes)
{
EarlyZForce = earlyZForce;
Topology = topology;
@@ -95,6 +104,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
AlphaTestEnable = alphaTestEnable;
AlphaTestCompare = alphaTestCompare;
AlphaTestReference = alphaTestReference;
+ AttributeTypes = attributeTypes;
}
}
}
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
index 6d86e8f70..33d3c48f9 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
@@ -305,18 +305,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
return gpShaders;
}
- AttributeType[] attributeTypes = new AttributeType[32];
-
- for (int location = 0; location < attributeTypes.Length; location++)
- {
- attributeTypes[location] = state.VertexAttribState[location].UnpackType() switch
- {
- 3 => AttributeType.Sint,
- 4 => AttributeType.Uint,
- _ => AttributeType.Float
- };
- }
-
TransformFeedbackDescriptor[] transformFeedbackDescriptors = GetTransformFeedbackDescriptors(ref state);
ShaderSpecializationState specState = new ShaderSpecializationState(graphicsState, transformFeedbackDescriptors);
@@ -335,7 +323,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
if (gpuVa != 0)
{
- GpuAccessor gpuAccessor = new GpuAccessor(_context, channel, gpuAccessorState, attributeTypes, stageIndex);
+ GpuAccessor gpuAccessor = new GpuAccessor(_context, channel, gpuAccessorState, stageIndex);
TranslatorContext currentStage = DecodeGraphicsShader(gpuAccessor, api, DefaultFlags, gpuVa);
if (nextStage != null)
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs
index 44ffd687d..120a4b179 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs
@@ -455,6 +455,23 @@ namespace Ryujinx.Graphics.Gpu.Shader
return false;
}
+ if (graphicsState.DepthMode != GraphicsState.DepthMode)
+ {
+ return false;
+ }
+
+ if (graphicsState.AlphaTestEnable != GraphicsState.AlphaTestEnable ||
+ graphicsState.AlphaTestCompare != GraphicsState.AlphaTestCompare ||
+ graphicsState.AlphaTestReference != GraphicsState.AlphaTestReference)
+ {
+ return false;
+ }
+
+ if (!graphicsState.AttributeTypes.ToSpan().SequenceEqual(GraphicsState.AttributeTypes.ToSpan()))
+ {
+ return false;
+ }
+
return Matches(channel, poolState, checkTextures, isCompute: false);
}
diff --git a/Ryujinx.Graphics.Shader/AttributeType.cs b/Ryujinx.Graphics.Shader/AttributeType.cs
index 11112f682..466f06cc8 100644
--- a/Ryujinx.Graphics.Shader/AttributeType.cs
+++ b/Ryujinx.Graphics.Shader/AttributeType.cs
@@ -2,7 +2,7 @@ using System;
namespace Ryujinx.Graphics.Shader
{
- public enum AttributeType
+ public enum AttributeType : byte
{
Float,
Sint,