diff --git a/Ryujinx.Graphics/Gal/GalBlendFactor.cs b/Ryujinx.Graphics/Gal/GalBlendFactor.cs index 7237c4edac..001aaaeca8 100644 --- a/Ryujinx.Graphics/Gal/GalBlendFactor.cs +++ b/Ryujinx.Graphics/Gal/GalBlendFactor.cs @@ -20,6 +20,7 @@ namespace Ryujinx.Graphics.Gal ConstantColor = 0x61, OneMinusConstantColor = 0x62, ConstantAlpha = 0x63, - OneMinusConstantAlpha = 0x64 + OneMinusConstantAlpha = 0x64, + ConstantColorG80 = 0xc001 } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs index cb2c1a0e8b..349c695e5b 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs @@ -187,7 +187,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL case GalBlendFactor.OneMinusSrcAlpha: return BlendingFactor.OneMinusSrcAlpha; case GalBlendFactor.DstAlpha: return BlendingFactor.DstAlpha; case GalBlendFactor.OneMinusDstAlpha: return BlendingFactor.OneMinusDstAlpha; - case GalBlendFactor.ConstantColor: return BlendingFactor.ConstantColor; case GalBlendFactor.OneMinusConstantColor: return BlendingFactor.OneMinusConstantColor; case GalBlendFactor.ConstantAlpha: return BlendingFactor.ConstantAlpha; case GalBlendFactor.OneMinusConstantAlpha: return BlendingFactor.OneMinusConstantAlpha; @@ -196,6 +195,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL case GalBlendFactor.OneMinusSrc1Color: return (BlendingFactor)BlendingFactorSrc.OneMinusSrc1Color; case GalBlendFactor.Src1Alpha: return BlendingFactor.Src1Alpha; case GalBlendFactor.OneMinusSrc1Alpha: return (BlendingFactor)BlendingFactorSrc.OneMinusSrc1Alpha; + + case GalBlendFactor.ConstantColor: + case GalBlendFactor.ConstantColorG80: + return BlendingFactor.ConstantColor; } throw new ArgumentException(nameof(BlendFactor)); diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs index 867f901604..d3284f9f55 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs @@ -9,6 +9,7 @@ namespace Ryujinx.Graphics.Gal.Shader public const int TessCoordAttrZ = 0x2f8; public const int InstanceIdAttr = 0x2f8; public const int VertexIdAttr = 0x2fc; + public const int FaceAttr = 0x3fc; public const int GlPositionWAttr = 0x7c; public const int MaxUboSize = 1024; @@ -208,7 +209,8 @@ namespace Ryujinx.Graphics.Gal.Shader { //This is a built-in input variable. if (Abuf.Offs == VertexIdAttr || - Abuf.Offs == InstanceIdAttr) + Abuf.Offs == InstanceIdAttr || + Abuf.Offs == FaceAttr) { break; } diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs index 87d448689b..f3075a504e 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs @@ -658,6 +658,14 @@ namespace Ryujinx.Graphics.Gal.Shader case GlslDecl.TessCoordAttrZ: return "gl_TessCoord.z"; } } + else if (Decl.ShaderType == GalShaderType.Fragment) + { + switch (Abuf.Offs) + { + //Note: It's a guess that Maxwell's face is 1 when gl_FrontFacing == true + case GlslDecl.FaceAttr: return "(gl_FrontFacing ? 1 : 0)"; + } + } return GetAttrTempName(Abuf); } @@ -1084,7 +1092,8 @@ namespace Ryujinx.Graphics.Gal.Shader { case ShaderIrOperAbuf Abuf: return Abuf.Offs == GlslDecl.VertexIdAttr || - Abuf.Offs == GlslDecl.InstanceIdAttr + Abuf.Offs == GlslDecl.InstanceIdAttr || + Abuf.Offs == GlslDecl.FaceAttr ? OperType.I32 : OperType.F32; diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs index c50f0144bb..083b0c63a1 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs @@ -8,6 +8,29 @@ namespace Ryujinx.Graphics.Gal.Shader { private const int TempRegStart = 0x100; + private const int ____ = 0x0; + private const int R___ = 0x1; + private const int _G__ = 0x2; + private const int RG__ = 0x3; + private const int __B_ = 0x4; + private const int RGB_ = 0x7; + private const int ___A = 0x8; + private const int R__A = 0x9; + private const int _G_A = 0xa; + private const int RG_A = 0xb; + private const int __BA = 0xc; + private const int R_BA = 0xd; + private const int _GBA = 0xe; + private const int RGBA = 0xf; + + private static int[,] MaskLut = new int[,] + { + { ____, ____, ____, ____, ____, ____, ____, ____ }, + { R___, _G__, __B_, ___A, RG__, ____, ____, ____ }, + { R___, _G__, __B_, ___A, RG__, R__A, _G_A, __BA }, + { RGB_, RG_A, R_BA, _GBA, RGBA, ____, ____, ____ } + }; + public static void Ld_A(ShaderIrBlock Block, long OpCode) { ShaderIrNode[] Opers = GetOperAbuf20(OpCode); @@ -167,20 +190,12 @@ namespace Ryujinx.Graphics.Gal.Shader ShaderIrNode OperB = GetOperGpr20 (OpCode); ShaderIrNode OperC = GetOperImm13_36(OpCode); - bool TwoDests = GetOperGpr28(OpCode).Index != ShaderIrOperGpr.ZRIndex; + int LutIndex; - int ChMask; + LutIndex = GetOperGpr0(OpCode).Index != ShaderIrOperGpr.ZRIndex ? 1 : 0; + LutIndex |= GetOperGpr28(OpCode).Index != ShaderIrOperGpr.ZRIndex ? 2 : 0; - switch ((OpCode >> 50) & 7) - { - case 0: ChMask = TwoDests ? 0x7 : 0x1; break; - case 1: ChMask = TwoDests ? 0xb : 0x2; break; - case 2: ChMask = TwoDests ? 0xd : 0x4; break; - case 3: ChMask = TwoDests ? 0xe : 0x8; break; - case 4: ChMask = TwoDests ? 0xf : 0x3; break; - - default: throw new InvalidOperationException(); - } + int ChMask = MaskLut[LutIndex, (OpCode >> 50) & 7]; for (int Ch = 0; Ch < 4; Ch++) {