diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs index 1d492214..d10e4671 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 396b0443..610b2da1 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 00000000..4b1fbb06 --- /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 02136982..f714d97b 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 2783714b..c0ad481e 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 3293ae8e..6ec94c1b 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 825564b8..d43fe632 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 cb9db922..fe034c57 100644 --- a/Ryujinx.Graphics.Shader/IGpuAccessor.cs +++ b/Ryujinx.Graphics.Shader/IGpuAccessor.cs @@ -78,5 +78,10 @@ { return TextureFormat.R8G8B8A8Unorm; } + + bool QueryEarlyZForce() + { + return false; + } } }