From 2000e904f14c023f0e5993f53a81c2b33e322ac3 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Thu, 5 Apr 2018 15:47:35 -0300 Subject: [PATCH] Add support for float immediates, implement FSETP (immediate) on shader decoder --- Ryujinx.Graphics/Gal/Shader/GlslDecl.cs | 2 +- Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs | 22 +++++--- .../Gal/Shader/ShaderDecodeAlu.cs | 53 +++++++++++-------- .../Gal/Shader/ShaderDecodeHelper.cs | 16 +++++- .../Gal/Shader/ShaderIrOperImm.cs | 6 +-- .../Gal/Shader/ShaderIrOperImmf.cs | 6 +-- .../Gal/Shader/ShaderOpCodeTable.cs | 17 +++--- 7 files changed, 74 insertions(+), 48 deletions(-) diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs index b0f9886d84..64090285e2 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs @@ -106,7 +106,7 @@ namespace Ryujinx.Graphics.Gal.Shader Op.Inst == ShaderIrInst.Texb || Op.Inst == ShaderIrInst.Texa) { - int Handle = ((ShaderIrOperImm)Op.OperandC).Imm; + int Handle = ((ShaderIrOperImm)Op.OperandC).Value; int Index = Handle - TexStartIndex; diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs index edd28fa8dd..2048dde5a1 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs @@ -264,11 +264,12 @@ namespace Ryujinx.Graphics.Gal.Shader { switch (Node) { - case ShaderIrOperAbuf Abuf: return GetName(Abuf); - case ShaderIrOperCbuf Cbuf: return GetName(Cbuf); - case ShaderIrOperGpr Gpr: return GetName(Gpr); - case ShaderIrOperImm Imm: return GetName(Imm); - case ShaderIrOperPred Pred: return GetName(Pred); + case ShaderIrOperAbuf Abuf: return GetName (Abuf); + case ShaderIrOperCbuf Cbuf: return GetName (Cbuf); + case ShaderIrOperGpr Gpr: return GetName (Gpr); + case ShaderIrOperImm Imm: return GetValue(Imm); + case ShaderIrOperImmf Immf: return GetValue(Immf); + case ShaderIrOperPred Pred: return GetName (Pred); case ShaderIrOp Op: string Expr; @@ -332,9 +333,14 @@ namespace Ryujinx.Graphics.Gal.Shader return Gpr.IsConst ? "0" : GetNameWithSwizzle(Decl.Gprs, Gpr.Index); } - private string GetName(ShaderIrOperImm Imm) + private string GetValue(ShaderIrOperImm Imm) { - return Imm.Imm.ToString(CultureInfo.InvariantCulture); + return Imm.Value.ToString(CultureInfo.InvariantCulture); + } + + private string GetValue(ShaderIrOperImmf Immf) + { + return Immf.Value.ToString(CultureInfo.InvariantCulture); } private string GetName(ShaderIrOperPred Pred) @@ -443,7 +449,7 @@ namespace Ryujinx.Graphics.Gal.Shader { ShaderIrOperImm Node = (ShaderIrOperImm)Op.OperandC; - int Handle = ((ShaderIrOperImm)Op.OperandC).Imm; + int Handle = ((ShaderIrOperImm)Op.OperandC).Value; if (!Decl.Textures.TryGetValue(Handle, out ShaderDeclInfo DeclInfo)) { diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs index 0405625ef9..e43531e5a3 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs @@ -8,30 +8,25 @@ namespace Ryujinx.Graphics.Gal.Shader { private enum ShaderOper { + CR, RR, RC, - CR, Imm } - public static void Fadd_R(ShaderIrBlock Block, long OpCode) - { - EmitAluBinary(Block, OpCode, ShaderOper.RR, ShaderIrInst.Fadd); - } - public static void Fadd_C(ShaderIrBlock Block, long OpCode) { EmitAluBinary(Block, OpCode, ShaderOper.CR, ShaderIrInst.Fadd); } - public static void Fadd_Imm(ShaderIrBlock Block, long OpCode) + public static void Fadd_I(ShaderIrBlock Block, long OpCode) { EmitAluBinary(Block, OpCode, ShaderOper.Imm, ShaderIrInst.Fadd); } - public static void Ffma_RR(ShaderIrBlock Block, long OpCode) + public static void Fadd_R(ShaderIrBlock Block, long OpCode) { - EmitAluFfma(Block, OpCode, ShaderOper.RR); + EmitAluBinary(Block, OpCode, ShaderOper.RR, ShaderIrInst.Fadd); } public static void Ffma_CR(ShaderIrBlock Block, long OpCode) @@ -39,19 +34,19 @@ namespace Ryujinx.Graphics.Gal.Shader EmitAluFfma(Block, OpCode, ShaderOper.CR); } + public static void Ffma_I(ShaderIrBlock Block, long OpCode) + { + EmitAluFfma(Block, OpCode, ShaderOper.Imm); + } + public static void Ffma_RC(ShaderIrBlock Block, long OpCode) { EmitAluFfma(Block, OpCode, ShaderOper.RC); } - public static void Ffma_Imm(ShaderIrBlock Block, long OpCode) + public static void Ffma_RR(ShaderIrBlock Block, long OpCode) { - EmitAluFfma(Block, OpCode, ShaderOper.Imm); - } - - public static void Fmul_R(ShaderIrBlock Block, long OpCode) - { - EmitAluBinary(Block, OpCode, ShaderOper.RR, ShaderIrInst.Fmul); + EmitAluFfma(Block, OpCode, ShaderOper.RR); } public static void Fmul_C(ShaderIrBlock Block, long OpCode) @@ -59,14 +54,14 @@ namespace Ryujinx.Graphics.Gal.Shader EmitAluBinary(Block, OpCode, ShaderOper.CR, ShaderIrInst.Fmul); } - public static void Fmul_Imm(ShaderIrBlock Block, long OpCode) + public static void Fmul_I(ShaderIrBlock Block, long OpCode) { EmitAluBinary(Block, OpCode, ShaderOper.Imm, ShaderIrInst.Fmul); } - public static void Fsetp_R(ShaderIrBlock Block, long OpCode) + public static void Fmul_R(ShaderIrBlock Block, long OpCode) { - EmitFsetp(Block, OpCode, ShaderOper.RR); + EmitAluBinary(Block, OpCode, ShaderOper.RR, ShaderIrInst.Fmul); } public static void Fsetp_C(ShaderIrBlock Block, long OpCode) @@ -74,6 +69,16 @@ namespace Ryujinx.Graphics.Gal.Shader EmitFsetp(Block, OpCode, ShaderOper.CR); } + public static void Fsetp_I(ShaderIrBlock Block, long OpCode) + { + EmitFsetp(Block, OpCode, ShaderOper.Imm); + } + + public static void Fsetp_R(ShaderIrBlock Block, long OpCode) + { + EmitFsetp(Block, OpCode, ShaderOper.RR); + } + public static void Ipa(ShaderIrBlock Block, long OpCode) { ShaderIrNode OperA = GetOperAbuf28(OpCode); @@ -101,6 +106,8 @@ namespace Ryujinx.Graphics.Gal.Shader case 3: Inst = ShaderIrInst.Flg2; break; case 4: Inst = ShaderIrInst.Frcp; break; case 5: Inst = ShaderIrInst.Frsq; break; + + default: throw new NotImplementedException(SubOp.ToString()); } ShaderIrNode OperA = GetOperGpr8(OpCode); @@ -131,9 +138,9 @@ namespace Ryujinx.Graphics.Gal.Shader switch (Oper) { - case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break; case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break; case ShaderOper.Imm: OperB = GetOperImmf19_20(OpCode); break; + case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break; default: throw new ArgumentException(nameof(Oper)); } @@ -156,10 +163,10 @@ namespace Ryujinx.Graphics.Gal.Shader switch (Oper) { - case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break; case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break; - case ShaderOper.RC: OperB = GetOperGpr39 (OpCode); break; case ShaderOper.Imm: OperB = GetOperImmf19_20(OpCode); break; + case ShaderOper.RC: OperB = GetOperGpr39 (OpCode); break; + case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break; default: throw new ArgumentException(nameof(Oper)); } @@ -191,9 +198,9 @@ namespace Ryujinx.Graphics.Gal.Shader switch (Oper) { - case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break; case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break; case ShaderOper.Imm: OperB = GetOperImmf19_20(OpCode); break; + case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break; default: throw new ArgumentException(nameof(Oper)); } diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs index 2ab1bcbf67..c9b904b38b 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs @@ -62,8 +62,20 @@ namespace Ryujinx.Graphics.Gal.Shader public static ShaderIrNode GetOperImmf19_20(long OpCode) { - //TODO: This should be a float immediate. - return new ShaderIrOperImm((int)(OpCode >> 36) & 0x1fff); + uint Imm = (uint)(OpCode >> 20) & 0x7ffff; + + bool Neg = ((OpCode >> 56) & 1) != 0; + + Imm <<= 12; + + if (Neg) + { + Imm |= 0x80000000; + } + + float Value = BitConverter.Int32BitsToSingle((int)Imm); + + return new ShaderIrOperImmf(Value); } public static ShaderIrOperImm GetOperImm13_36(long OpCode) diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImm.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImm.cs index 421d55a17a..ba2c2c9b24 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImm.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImm.cs @@ -2,11 +2,11 @@ namespace Ryujinx.Graphics.Gal.Shader { class ShaderIrOperImm : ShaderIrNode { - public int Imm { get; private set; } + public int Value { get; private set; } - public ShaderIrOperImm(int Imm) + public ShaderIrOperImm(int Value) { - this.Imm = Imm; + this.Value = Value; } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImmf.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImmf.cs index 5fe3e00b40..3c27e48361 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImmf.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImmf.cs @@ -2,11 +2,11 @@ namespace Ryujinx.Graphics.Gal.Shader { class ShaderIrOperImmf : ShaderIrNode { - public float Imm { get; private set; } + public float Value { get; private set; } - public ShaderIrOperImmf(float Imm) + public ShaderIrOperImmf(float Value) { - this.Imm = Imm; + this.Value = Value; } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs b/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs index 7a2313a4b6..aa9682036f 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs @@ -14,18 +14,19 @@ namespace Ryujinx.Graphics.Gal.Shader #region Instructions Set("111000110000xx", ShaderDecode.Exit); - Set("0101110001011x", ShaderDecode.Fadd_R); Set("0100110001011x", ShaderDecode.Fadd_C); - Set("0011100x01011x", ShaderDecode.Fadd_Imm); - Set("010110011xxxxx", ShaderDecode.Ffma_RR); - Set("010100011xxxxx", ShaderDecode.Ffma_RC); + Set("0011100x01011x", ShaderDecode.Fadd_I); + Set("0101110001011x", ShaderDecode.Fadd_R); Set("010010011xxxxx", ShaderDecode.Ffma_CR); - Set("001100101xxxxx", ShaderDecode.Ffma_Imm); - Set("0101110001101x", ShaderDecode.Fmul_R); + Set("001100101xxxxx", ShaderDecode.Ffma_I); + Set("010100011xxxxx", ShaderDecode.Ffma_RC); + Set("010110011xxxxx", ShaderDecode.Ffma_RR); Set("0100110001101x", ShaderDecode.Fmul_C); - Set("0011100x01101x", ShaderDecode.Fmul_Imm); - Set("010110111011xx", ShaderDecode.Fsetp_R); + Set("0011100x01101x", ShaderDecode.Fmul_I); + Set("0101110001101x", ShaderDecode.Fmul_R); Set("010010111011xx", ShaderDecode.Fsetp_C); + Set("0011011x1011xx", ShaderDecode.Fsetp_I); + Set("010110111011xx", ShaderDecode.Fsetp_R); Set("11100000xxxxxx", ShaderDecode.Ipa); Set("111000110011xx", ShaderDecode.Kil); Set("1110111111011x", ShaderDecode.Ld_A);