diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2019-02-15 00:23:14 -0300 |
|---|---|---|
| committer | jduncanator <1518948+jduncanator@users.noreply.github.com> | 2019-02-15 14:23:14 +1100 |
| commit | 9cbcbaa90c2af78873d145850e0676b19b2ae79e (patch) | |
| tree | f1280ddc743d86c93c0000ffb82841a03e8aeda2 | |
| parent | b126ea48c63a3de8da8f3b817860c0323f2621ef (diff) | |
Fix XMAD shader instruction, gl_FrontFacing and enable face culling (#583)
* Fix XMAD shader instruction implementation
* Fix gl_FrontFacing constant value
* Enable face culling again
* Fix typo
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs | 36 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs | 4 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs | 139 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs | 5 |
4 files changed, 122 insertions, 62 deletions
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs index deccd890..6a928603 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs @@ -159,25 +159,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL Shader.SetExtraData(New.FlipX, New.FlipY, New.Instance); } - //Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved - - //if (New.FrontFace != Old.FrontFace) - //{ - // GL.FrontFace(OGLEnumConverter.GetFrontFace(New.FrontFace)); - //} - - //if (New.CullFaceEnabled != Old.CullFaceEnabled) - //{ - // Enable(EnableCap.CullFace, New.CullFaceEnabled); - //} - - //if (New.CullFaceEnabled) - //{ - // if (New.CullFace != Old.CullFace) - // { - // GL.CullFace(OGLEnumConverter.GetCullFace(New.CullFace)); - // } - //} + if (New.FrontFace != Old.FrontFace) + { + GL.FrontFace(OGLEnumConverter.GetFrontFace(New.FrontFace)); + } + + if (New.CullFaceEnabled != Old.CullFaceEnabled) + { + Enable(EnableCap.CullFace, New.CullFaceEnabled); + } + + if (New.CullFaceEnabled) + { + if (New.CullFace != Old.CullFace) + { + GL.CullFace(OGLEnumConverter.GetCullFace(New.CullFace)); + } + } if (New.DepthTestEnabled != Old.DepthTestEnabled) { diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs index 77a451e9..854c827e 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs @@ -845,9 +845,7 @@ namespace Ryujinx.Graphics.Gal.Shader { case GlslDecl.PointCoordAttrX: return "gl_PointCoord.x"; case GlslDecl.PointCoordAttrY: return "gl_PointCoord.y"; - - //Note: It's a guess that Maxwell's face is 1 when gl_FrontFacing == true - case GlslDecl.FaceAttr: return "(gl_FrontFacing ? 1 : 0)"; + case GlslDecl.FaceAttr: return "(gl_FrontFacing ? -1 : 0)"; } } diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs index 24c85c8f..469092a2 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs @@ -1148,41 +1148,87 @@ namespace Ryujinx.Graphics.Gal.Shader Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op))); } + private enum XmadMode + { + Cfull = 0, + Clo = 1, + Chi = 2, + Csfu = 3, + Cbcc = 4 + } + private static void EmitXmad(ShaderIrBlock Block, long OpCode, ShaderOper Oper) { - //TODO: Confirm SignAB/C, it is just a guess. - //TODO: Implement Mode 3 (CSFU), what it does? - bool SignAB = OpCode.Read(48); - bool SignC = OpCode.Read(49); - bool HighB = OpCode.Read(52); - bool HighA = OpCode.Read(53); + bool SignedA = OpCode.Read(48); + bool SignedB = OpCode.Read(49); + bool HighB = OpCode.Read(52); + bool HighA = OpCode.Read(53); int Mode = OpCode.Read(50, 7); ShaderIrNode OperA = OpCode.Gpr8(), OperB, OperC; - ShaderIrOperImm Imm16 = new ShaderIrOperImm(16); - ShaderIrOperImm ImmMsk = new ShaderIrOperImm(0xffff); + switch (Oper) + { + case ShaderOper.CR: OperB = OpCode.Cbuf34(); break; + case ShaderOper.Imm: OperB = OpCode.ImmU16_20(); break; + case ShaderOper.RC: OperB = OpCode.Gpr39(); break; + case ShaderOper.RR: OperB = OpCode.Gpr20(); break; + + default: throw new ArgumentException(nameof(Oper)); + } - ShaderIrInst ShiftAB = SignAB ? ShaderIrInst.Asr : ShaderIrInst.Lsr; - ShaderIrInst ShiftC = SignC ? ShaderIrInst.Asr : ShaderIrInst.Lsr; + ShaderIrNode OperB2 = OperB; - if (HighA) + if (Oper == ShaderOper.Imm) { - OperA = new ShaderIrOp(ShiftAB, OperA, Imm16); + int Imm = ((ShaderIrOperImm)OperB2).Value; + + if (!HighB) + { + Imm <<= 16; + } + + if (SignedB) + { + Imm >>= 16; + } + else + { + Imm = (int)((uint)Imm >> 16); + } + + OperB2 = new ShaderIrOperImm(Imm); } - switch (Oper) + ShaderIrOperImm Imm16 = new ShaderIrOperImm(16); + + //If we are working with the lower 16-bits of the A/B operands, + //we need to shift the lower 16-bits to the top 16-bits. Later, + //they will be right shifted. For U16 types, this will be a logical + //right shift, and for S16 types, a arithmetic right shift. + if (!HighA) { - case ShaderOper.CR: OperB = OpCode.Cbuf34(); break; - case ShaderOper.Imm: OperB = OpCode.Imm19_20(); break; - case ShaderOper.RC: OperB = OpCode.Gpr39(); break; - case ShaderOper.RR: OperB = OpCode.Gpr20(); break; + OperA = new ShaderIrOp(ShaderIrInst.Lsl, OperA, Imm16); + } - default: throw new ArgumentException(nameof(Oper)); + if (!HighB && Oper != ShaderOper.Imm) + { + OperB2 = new ShaderIrOp(ShaderIrInst.Lsl, OperB2, Imm16); } - bool ProductShiftLeft = false, Merge = false; + ShaderIrInst ShiftA = SignedA ? ShaderIrInst.Asr : ShaderIrInst.Lsr; + ShaderIrInst ShiftB = SignedB ? ShaderIrInst.Asr : ShaderIrInst.Lsr; + + OperA = new ShaderIrOp(ShiftA, OperA, Imm16); + + if (Oper != ShaderOper.Imm) + { + OperB2 = new ShaderIrOp(ShiftB, OperB2, Imm16); + } + + bool ProductShiftLeft = false; + bool Merge = false; if (Oper == ShaderOper.RC) { @@ -1196,40 +1242,53 @@ namespace Ryujinx.Graphics.Gal.Shader Merge = OpCode.Read(37); } - switch (Mode) - { - //CLO. - case 1: OperC = ExtendTo32(OperC, SignC, 16); break; + ShaderIrOp MulOp = new ShaderIrOp(ShaderIrInst.Mul, OperA, OperB2); - //CHI. - case 2: OperC = new ShaderIrOp(ShiftC, OperC, Imm16); break; + if (ProductShiftLeft) + { + MulOp = new ShaderIrOp(ShaderIrInst.Lsl, MulOp, Imm16); } - ShaderIrNode OperBH = OperB; - - if (HighB) + switch ((XmadMode)Mode) { - OperBH = new ShaderIrOp(ShiftAB, OperBH, Imm16); - } + case XmadMode.Clo: OperC = ExtendTo32(OperC, Signed: false, Size: 16); break; - ShaderIrOp MulOp = new ShaderIrOp(ShaderIrInst.Mul, OperA, OperBH); + case XmadMode.Chi: OperC = new ShaderIrOp(ShaderIrInst.Lsr, OperC, Imm16); break; - if (ProductShiftLeft) - { - MulOp = new ShaderIrOp(ShaderIrInst.Lsl, MulOp, Imm16); + case XmadMode.Cbcc: + { + ShaderIrOp OperBLsh16 = new ShaderIrOp(ShaderIrInst.Lsl, OperB, Imm16); + + OperC = new ShaderIrOp(ShaderIrInst.Add, OperC, OperBLsh16); + + break; + } + + case XmadMode.Csfu: + { + ShaderIrOperImm Imm31 = new ShaderIrOperImm(31); + + ShaderIrOp SignAdjustA = new ShaderIrOp(ShaderIrInst.Lsr, OperA, Imm31); + ShaderIrOp SignAdjustB = new ShaderIrOp(ShaderIrInst.Lsr, OperB2, Imm31); + + SignAdjustA = new ShaderIrOp(ShaderIrInst.Lsl, SignAdjustA, Imm16); + SignAdjustB = new ShaderIrOp(ShaderIrInst.Lsl, SignAdjustB, Imm16); + + ShaderIrOp SignAdjust = new ShaderIrOp(ShaderIrInst.Add, SignAdjustA, SignAdjustB); + + OperC = new ShaderIrOp(ShaderIrInst.Sub, OperC, SignAdjust); + + break; + } } ShaderIrOp AddOp = new ShaderIrOp(ShaderIrInst.Add, MulOp, OperC); if (Merge) { - AddOp = new ShaderIrOp(ShaderIrInst.And, AddOp, ImmMsk); - OperB = new ShaderIrOp(ShaderIrInst.Lsl, OperB, Imm16); - AddOp = new ShaderIrOp(ShaderIrInst.Or, AddOp, OperB); - } + ShaderIrOperImm Imm16Mask = new ShaderIrOperImm(0xffff); - if (Mode == 4) - { + AddOp = new ShaderIrOp(ShaderIrInst.And, AddOp, Imm16Mask); OperB = new ShaderIrOp(ShaderIrInst.Lsl, OperB, Imm16); AddOp = new ShaderIrOp(ShaderIrInst.Or, AddOp, OperB); } diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs index 6531138e..f0f92148 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs @@ -138,6 +138,11 @@ namespace Ryujinx.Graphics.Gal.Shader return new ShaderIrOperImmf(BitConverter.Int32BitsToSingle((int)(OpCode >> 20))); } + private static ShaderIrOperImm ImmU16_20(this long OpCode) + { + return new ShaderIrOperImm(OpCode.Read(20, 0xffff)); + } + private static ShaderIrOperImm Imm19_20(this long OpCode) { int Value = OpCode.Read(20, 0x7ffff); |
