aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2019-02-15 00:23:14 -0300
committerjduncanator <1518948+jduncanator@users.noreply.github.com>2019-02-15 14:23:14 +1100
commit9cbcbaa90c2af78873d145850e0676b19b2ae79e (patch)
treef1280ddc743d86c93c0000ffb82841a03e8aeda2
parentb126ea48c63a3de8da8f3b817860c0323f2621ef (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.cs36
-rw-r--r--Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs4
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs139
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs5
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);