diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs
index 1d492214e..d10e46711 100644
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs
@@ -332,6 +332,23 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache
return null;
}
+ ///
+ /// Builds gpu state flags using information from the given gpu accessor.
+ ///
+ /// The gpu accessor
+ /// The gpu state flags
+ private static GuestGpuStateFlags GetGpuStateFlags(IGpuAccessor gpuAccessor)
+ {
+ GuestGpuStateFlags flags = 0;
+
+ if (gpuAccessor.QueryEarlyZForce())
+ {
+ flags |= GuestGpuStateFlags.EarlyZForce;
+ }
+
+ return flags;
+ }
+
///
/// Create a new instance of from an gpu accessor.
///
@@ -347,6 +364,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache
ComputeLocalMemorySize = gpuAccessor.QueryComputeLocalMemorySize(),
ComputeSharedMemorySize = gpuAccessor.QueryComputeSharedMemorySize(),
PrimitiveTopology = gpuAccessor.QueryPrimitiveTopology(),
+ StateFlags = GetGpuStateFlags(gpuAccessor)
};
}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuAccessorHeader.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuAccessorHeader.cs
index 396b04430..610b2da10 100644
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuAccessorHeader.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuAccessorHeader.cs
@@ -55,8 +55,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
public ushort Reserved2;
///
- /// Unused/reserved.
+ /// GPU boolean state that can influence shader compilation.
///
- public byte Reserved3;
+ public GuestGpuStateFlags StateFlags;
}
}
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuStateFlags.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuStateFlags.cs
new file mode 100644
index 000000000..4b1fbb066
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/GuestGpuStateFlags.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
+{
+ [Flags]
+ enum GuestGpuStateFlags : byte
+ {
+ EarlyZForce = 1 << 0
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs
index 021369821..f714d97bd 100644
--- a/Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs
@@ -150,5 +150,14 @@ namespace Ryujinx.Graphics.Gpu.Shader
return textureDescriptor;
}
+
+ ///
+ /// Queries if host state forces early depth testing.
+ ///
+ /// True if early depth testing is forced
+ public bool QueryEarlyZForce()
+ {
+ return (_header.StateFlags & GuestGpuStateFlags.EarlyZForce) != 0;
+ }
}
}
diff --git a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs
index 2783714b3..c0ad481ea 100644
--- a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs
@@ -196,5 +196,14 @@ namespace Ryujinx.Graphics.Gpu.Shader
return _context.Methods.TextureManager.GetGraphicsTextureDescriptor(_state, _stageIndex, handle);
}
}
+
+ ///
+ /// Queries if host state forces early depth testing.
+ ///
+ /// True if early depth testing is forced
+ public bool QueryEarlyZForce()
+ {
+ return _state.Get(MethodOffset.EarlyZForce);
+ }
}
}
diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
index 3293ae8ec..6ec94c1b0 100644
--- a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
+++ b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
@@ -13,6 +13,7 @@ namespace Ryujinx.Graphics.Gpu.State
LaunchDma = 0x6c,
LoadInlineData = 0x6d,
CopyDstTexture = 0x80,
+ EarlyZForce = 0x84,
CopySrcTexture = 0x8c,
DispatchParamsAddress = 0xad,
Dispatch = 0xaf,
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
index 825564b8c..d43fe6324 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
@@ -141,6 +141,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{
if (context.Config.Stage == ShaderStage.Fragment)
{
+ if (context.Config.GpuAccessor.QueryEarlyZForce())
+ {
+ context.AppendLine("layout(early_fragment_tests) in;");
+ context.AppendLine();
+ }
+
context.AppendLine($"uniform bool {DefaultNames.IsBgraName}[8];");
context.AppendLine();
}
diff --git a/Ryujinx.Graphics.Shader/IGpuAccessor.cs b/Ryujinx.Graphics.Shader/IGpuAccessor.cs
index cb9db9221..fe034c57c 100644
--- a/Ryujinx.Graphics.Shader/IGpuAccessor.cs
+++ b/Ryujinx.Graphics.Shader/IGpuAccessor.cs
@@ -78,5 +78,10 @@
{
return TextureFormat.R8G8B8A8Unorm;
}
+
+ bool QueryEarlyZForce()
+ {
+ return false;
+ }
}
}