diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs index 56745bc150..d703653cc6 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs @@ -94,7 +94,8 @@ namespace Ryujinx.Graphics.Gal.Shader m_Preds = new Dictionary(); } - public GlslDecl(ShaderIrBlock[] Blocks, GalShaderType ShaderType) : this(ShaderType) + public GlslDecl(ShaderIrBlock[] Blocks, GalShaderType ShaderType, ShaderHeader Header) + : this(ShaderType) { StagePrefix = StagePrefixes[(int)ShaderType] + "_"; @@ -153,6 +154,11 @@ namespace Ryujinx.Graphics.Gal.Shader return Combined; } + public static string GetGprName(int Index) + { + return GprName + Index; + } + private static void Merge( Dictionary C, Dictionary A, @@ -318,7 +324,7 @@ namespace Ryujinx.Graphics.Gal.Shader { if (!Gpr.IsConst && !HasName(m_Gprs, Gpr.Index)) { - string Name = GprName + Gpr.Index; + string Name = GetGprName(Gpr.Index); m_Gprs.TryAdd(Gpr.Index, new ShaderDeclInfo(Name, Gpr.Index)); } diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs index 726379846d..335be0c3d3 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs @@ -120,8 +120,8 @@ namespace Ryujinx.Graphics.Gal.Shader Blocks = ShaderDecoder.Decode(Memory, VpAPosition); BlocksB = ShaderDecoder.Decode(Memory, VpBPosition); - GlslDecl DeclVpA = new GlslDecl(Blocks, ShaderType); - GlslDecl DeclVpB = new GlslDecl(BlocksB, ShaderType); + GlslDecl DeclVpA = new GlslDecl(Blocks, ShaderType, Header); + GlslDecl DeclVpB = new GlslDecl(BlocksB, ShaderType, HeaderB); Decl = GlslDecl.Merge(DeclVpA, DeclVpB); @@ -136,7 +136,7 @@ namespace Ryujinx.Graphics.Gal.Shader Blocks = ShaderDecoder.Decode(Memory, Position); BlocksB = null; - Decl = new GlslDecl(Blocks, ShaderType); + Decl = new GlslDecl(Blocks, ShaderType, Header); return Decompile(); } @@ -432,6 +432,14 @@ namespace Ryujinx.Graphics.Gal.Shader PrintAttrToOutput(); } + if (Decl.ShaderType == GalShaderType.Fragment) + { + if (Header.OmapDepth) + { + SB.AppendLine(IdentationStr + "gl_FragDepth = " + GlslDecl.GetGprName(Header.DepthRegister) + ";"); + } + } + SB.AppendLine("}"); } diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderHeader.cs b/Ryujinx.Graphics/Gal/Shader/ShaderHeader.cs index 8e5057ed9e..6b7375a155 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderHeader.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderHeader.cs @@ -1,5 +1,15 @@ namespace Ryujinx.Graphics.Gal.Shader { + struct OmapTarget + { + public bool Red; + public bool Green; + public bool Blue; + public bool Alpha; + + public bool Enabled => Red || Green || Blue || Alpha; + } + class ShaderHeader { public const int PointList = 1; @@ -30,6 +40,10 @@ public int StoreReqStart { get; private set; } public int StoreReqEnd { get; private set; } + public OmapTarget[] OmapTargets { get; private set; } + public bool OmapSampleMask { get; private set; } + public bool OmapDepth { get; private set; } + public ShaderHeader(IGalMemory Memory, long Position) { uint CommonWord0 = (uint)Memory.ReadInt32(Position + 0); @@ -61,8 +75,48 @@ MaxOutputVertexCount = ReadBits(CommonWord4, 0, 12); StoreReqStart = ReadBits(CommonWord4, 12, 8); StoreReqEnd = ReadBits(CommonWord4, 24, 8); + + //Type 2 (fragment?) reading + uint Type2OmapTarget = (uint)Memory.ReadInt32(Position + 72); + uint Type2Omap = (uint)Memory.ReadInt32(Position + 76); + + OmapTargets = new OmapTarget[8]; + + for (int i = 0; i < OmapTargets.Length; i++) + { + int Offset = i * 4; + + OmapTargets[i] = new OmapTarget + { + Red = ReadBits(Type2OmapTarget, Offset + 0, 1) != 0, + Green = ReadBits(Type2OmapTarget, Offset + 1, 1) != 0, + Blue = ReadBits(Type2OmapTarget, Offset + 2, 1) != 0, + Alpha = ReadBits(Type2OmapTarget, Offset + 3, 1) != 0 + }; + } + + OmapSampleMask = ReadBits(Type2Omap, 0, 1) != 0; + OmapDepth = ReadBits(Type2Omap, 1, 1) != 0; } + public int FragOutputCount + { + get + { + int Index = 0; + + while (OmapTargets[Index].Enabled && Index < 8) + { + Index++; + } + + return Index; + } + } + + // Depth register is always two registers after the last color output + public int DepthRegister => FragOutputCount * 4 + 1; + private static int ReadBits(uint Word, int Offset, int BitWidth) { uint Mask = (1u << BitWidth) - 1u;