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; + } } }