aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs')
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs82
1 files changed, 80 insertions, 2 deletions
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs
index 7e39c8a3..c927f33d 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs
@@ -1,6 +1,7 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Gpu.Image;
using Ryujinx.Graphics.Gpu.Memory;
+using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Shader.DiskCache;
using Ryujinx.Graphics.Shader;
using System;
@@ -19,6 +20,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
private const uint TfbdMagic = (byte)'T' | ((byte)'F' << 8) | ((byte)'B' << 16) | ((byte)'D' << 24);
private const uint TexkMagic = (byte)'T' | ((byte)'E' << 8) | ((byte)'X' << 16) | ((byte)'K' << 24);
private const uint TexsMagic = (byte)'T' | ((byte)'E' << 8) | ((byte)'X' << 16) | ((byte)'S' << 24);
+ private const uint PgpsMagic = (byte)'P' | ((byte)'G' << 8) | ((byte)'P' << 16) | ((byte)'S' << 24);
/// <summary>
/// Flags indicating GPU state that is used by the shader.
@@ -52,6 +54,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
public Array5<uint> ConstantBufferUse;
/// <summary>
+ /// Pipeline state captured at the time of shader use.
+ /// </summary>
+ public ProgramPipelineState? PipelineState;
+
+ /// <summary>
/// Transform feedback buffers active at the time the shader was compiled.
/// </summary>
public TransformFeedbackDescriptor[] TransformFeedbackDescriptors;
@@ -179,7 +186,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// Creates a new instance of the shader specialization state.
/// </summary>
/// <param name="state">Current compute engine state</param>
- public ShaderSpecializationState(GpuChannelComputeState state) : this()
+ public ShaderSpecializationState(ref GpuChannelComputeState state) : this()
{
ComputeState = state;
_compute = true;
@@ -190,7 +197,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
/// <param name="state">Current 3D engine state</param>
/// <param name="descriptors">Optional transform feedback buffers in use, if any</param>
- public ShaderSpecializationState(GpuChannelGraphicsState state, TransformFeedbackDescriptor[] descriptors) : this()
+ private ShaderSpecializationState(ref GpuChannelGraphicsState state, TransformFeedbackDescriptor[] descriptors) : this()
{
GraphicsState = state;
_compute = false;
@@ -245,6 +252,34 @@ namespace Ryujinx.Graphics.Gpu.Shader
}
/// <summary>
+ /// Creates a new instance of the shader specialization state.
+ /// </summary>
+ /// <param name="state">Current 3D engine state</param>
+ /// <param name="pipelineState">Current program pipeline state</param>
+ /// <param name="descriptors">Optional transform feedback buffers in use, if any</param>
+ public ShaderSpecializationState(
+ ref GpuChannelGraphicsState state,
+ ref ProgramPipelineState pipelineState,
+ TransformFeedbackDescriptor[] descriptors) : this(ref state, descriptors)
+ {
+ PipelineState = pipelineState;
+ }
+
+ /// <summary>
+ /// Creates a new instance of the shader specialization state.
+ /// </summary>
+ /// <param name="state">Current 3D engine state</param>
+ /// <param name="pipelineState">Current program pipeline state</param>
+ /// <param name="descriptors">Optional transform feedback buffers in use, if any</param>
+ public ShaderSpecializationState(
+ ref GpuChannelGraphicsState state,
+ ProgramPipelineState? pipelineState,
+ TransformFeedbackDescriptor[] descriptors) : this(ref state, descriptors)
+ {
+ PipelineState = pipelineState;
+ }
+
+ /// <summary>
/// Indicates that the shader accesses the early Z force state.
/// </summary>
public void RecordEarlyZForce()
@@ -463,6 +498,28 @@ namespace Ryujinx.Graphics.Gpu.Shader
return false;
}
+ if (graphicsState.DepthMode != GraphicsState.DepthMode)
+ {
+ return false;
+ }
+
+ if (graphicsState.AlphaTestEnable != GraphicsState.AlphaTestEnable)
+ {
+ return false;
+ }
+
+ if (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);
}
@@ -685,6 +742,17 @@ namespace Ryujinx.Graphics.Gpu.Shader
constantBufferUsePerStageMask &= ~(1 << index);
}
+ bool hasPipelineState = false;
+
+ dataReader.Read(ref hasPipelineState);
+
+ if (hasPipelineState)
+ {
+ ProgramPipelineState pipelineState = default;
+ dataReader.ReadWithMagicAndSize(ref pipelineState, PgpsMagic);
+ specState.PipelineState = pipelineState;
+ }
+
if (specState._queriedState.HasFlag(QueriedStateFlags.TransformFeedback))
{
ushort tfCount = 0;
@@ -743,6 +811,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
constantBufferUsePerStageMask &= ~(1 << index);
}
+ bool hasPipelineState = PipelineState.HasValue;
+
+ dataWriter.Write(ref hasPipelineState);
+
+ if (hasPipelineState)
+ {
+ ProgramPipelineState pipelineState = PipelineState.Value;
+ dataWriter.WriteWithMagicAndSize(ref pipelineState, PgpsMagic);
+ }
+
if (_queriedState.HasFlag(QueriedStateFlags.TransformFeedback))
{
ushort tfCount = (ushort)TransformFeedbackDescriptors.Length;