Add support for float immediates, implement FSETP (immediate) on shader decoder

This commit is contained in:
gdkchan 2018-04-05 15:47:35 -03:00
commit 2000e904f1
7 changed files with 74 additions and 48 deletions

View file

@ -106,7 +106,7 @@ namespace Ryujinx.Graphics.Gal.Shader
Op.Inst == ShaderIrInst.Texb || Op.Inst == ShaderIrInst.Texb ||
Op.Inst == ShaderIrInst.Texa) Op.Inst == ShaderIrInst.Texa)
{ {
int Handle = ((ShaderIrOperImm)Op.OperandC).Imm; int Handle = ((ShaderIrOperImm)Op.OperandC).Value;
int Index = Handle - TexStartIndex; int Index = Handle - TexStartIndex;

View file

@ -267,7 +267,8 @@ namespace Ryujinx.Graphics.Gal.Shader
case ShaderIrOperAbuf Abuf: return GetName (Abuf); case ShaderIrOperAbuf Abuf: return GetName (Abuf);
case ShaderIrOperCbuf Cbuf: return GetName (Cbuf); case ShaderIrOperCbuf Cbuf: return GetName (Cbuf);
case ShaderIrOperGpr Gpr: return GetName (Gpr); case ShaderIrOperGpr Gpr: return GetName (Gpr);
case ShaderIrOperImm Imm: return GetName(Imm); case ShaderIrOperImm Imm: return GetValue(Imm);
case ShaderIrOperImmf Immf: return GetValue(Immf);
case ShaderIrOperPred Pred: return GetName (Pred); case ShaderIrOperPred Pred: return GetName (Pred);
case ShaderIrOp Op: case ShaderIrOp Op:
@ -332,9 +333,14 @@ namespace Ryujinx.Graphics.Gal.Shader
return Gpr.IsConst ? "0" : GetNameWithSwizzle(Decl.Gprs, Gpr.Index); 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) private string GetName(ShaderIrOperPred Pred)
@ -443,7 +449,7 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
ShaderIrOperImm Node = (ShaderIrOperImm)Op.OperandC; 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)) if (!Decl.Textures.TryGetValue(Handle, out ShaderDeclInfo DeclInfo))
{ {

View file

@ -8,30 +8,25 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
private enum ShaderOper private enum ShaderOper
{ {
CR,
RR, RR,
RC, RC,
CR,
Imm 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) public static void Fadd_C(ShaderIrBlock Block, long OpCode)
{ {
EmitAluBinary(Block, OpCode, ShaderOper.CR, ShaderIrInst.Fadd); 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); 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) public static void Ffma_CR(ShaderIrBlock Block, long OpCode)
@ -39,19 +34,19 @@ namespace Ryujinx.Graphics.Gal.Shader
EmitAluFfma(Block, OpCode, ShaderOper.CR); 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) public static void Ffma_RC(ShaderIrBlock Block, long OpCode)
{ {
EmitAluFfma(Block, OpCode, ShaderOper.RC); 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); EmitAluFfma(Block, OpCode, ShaderOper.RR);
}
public static void Fmul_R(ShaderIrBlock Block, long OpCode)
{
EmitAluBinary(Block, OpCode, ShaderOper.RR, ShaderIrInst.Fmul);
} }
public static void Fmul_C(ShaderIrBlock Block, long OpCode) 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); 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); 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) public static void Fsetp_C(ShaderIrBlock Block, long OpCode)
@ -74,6 +69,16 @@ namespace Ryujinx.Graphics.Gal.Shader
EmitFsetp(Block, OpCode, ShaderOper.CR); 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) public static void Ipa(ShaderIrBlock Block, long OpCode)
{ {
ShaderIrNode OperA = GetOperAbuf28(OpCode); ShaderIrNode OperA = GetOperAbuf28(OpCode);
@ -101,6 +106,8 @@ namespace Ryujinx.Graphics.Gal.Shader
case 3: Inst = ShaderIrInst.Flg2; break; case 3: Inst = ShaderIrInst.Flg2; break;
case 4: Inst = ShaderIrInst.Frcp; break; case 4: Inst = ShaderIrInst.Frcp; break;
case 5: Inst = ShaderIrInst.Frsq; break; case 5: Inst = ShaderIrInst.Frsq; break;
default: throw new NotImplementedException(SubOp.ToString());
} }
ShaderIrNode OperA = GetOperGpr8(OpCode); ShaderIrNode OperA = GetOperGpr8(OpCode);
@ -131,9 +138,9 @@ namespace Ryujinx.Graphics.Gal.Shader
switch (Oper) switch (Oper)
{ {
case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break; case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
case ShaderOper.Imm: OperB = GetOperImmf19_20(OpCode); break; case ShaderOper.Imm: OperB = GetOperImmf19_20(OpCode); break;
case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
default: throw new ArgumentException(nameof(Oper)); default: throw new ArgumentException(nameof(Oper));
} }
@ -156,10 +163,10 @@ namespace Ryujinx.Graphics.Gal.Shader
switch (Oper) switch (Oper)
{ {
case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
case ShaderOper.CR: OperB = GetOperCbuf34 (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.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)); default: throw new ArgumentException(nameof(Oper));
} }
@ -191,9 +198,9 @@ namespace Ryujinx.Graphics.Gal.Shader
switch (Oper) switch (Oper)
{ {
case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break; case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
case ShaderOper.Imm: OperB = GetOperImmf19_20(OpCode); break; case ShaderOper.Imm: OperB = GetOperImmf19_20(OpCode); break;
case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
default: throw new ArgumentException(nameof(Oper)); default: throw new ArgumentException(nameof(Oper));
} }

View file

@ -62,8 +62,20 @@ namespace Ryujinx.Graphics.Gal.Shader
public static ShaderIrNode GetOperImmf19_20(long OpCode) public static ShaderIrNode GetOperImmf19_20(long OpCode)
{ {
//TODO: This should be a float immediate. uint Imm = (uint)(OpCode >> 20) & 0x7ffff;
return new ShaderIrOperImm((int)(OpCode >> 36) & 0x1fff);
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) public static ShaderIrOperImm GetOperImm13_36(long OpCode)

View file

@ -2,11 +2,11 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
class ShaderIrOperImm : ShaderIrNode 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;
} }
} }
} }

View file

@ -2,11 +2,11 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
class ShaderIrOperImmf : ShaderIrNode 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;
} }
} }
} }

View file

@ -14,18 +14,19 @@ namespace Ryujinx.Graphics.Gal.Shader
#region Instructions #region Instructions
Set("111000110000xx", ShaderDecode.Exit); Set("111000110000xx", ShaderDecode.Exit);
Set("0101110001011x", ShaderDecode.Fadd_R);
Set("0100110001011x", ShaderDecode.Fadd_C); Set("0100110001011x", ShaderDecode.Fadd_C);
Set("0011100x01011x", ShaderDecode.Fadd_Imm); Set("0011100x01011x", ShaderDecode.Fadd_I);
Set("010110011xxxxx", ShaderDecode.Ffma_RR); Set("0101110001011x", ShaderDecode.Fadd_R);
Set("010100011xxxxx", ShaderDecode.Ffma_RC);
Set("010010011xxxxx", ShaderDecode.Ffma_CR); Set("010010011xxxxx", ShaderDecode.Ffma_CR);
Set("001100101xxxxx", ShaderDecode.Ffma_Imm); Set("001100101xxxxx", ShaderDecode.Ffma_I);
Set("0101110001101x", ShaderDecode.Fmul_R); Set("010100011xxxxx", ShaderDecode.Ffma_RC);
Set("010110011xxxxx", ShaderDecode.Ffma_RR);
Set("0100110001101x", ShaderDecode.Fmul_C); Set("0100110001101x", ShaderDecode.Fmul_C);
Set("0011100x01101x", ShaderDecode.Fmul_Imm); Set("0011100x01101x", ShaderDecode.Fmul_I);
Set("010110111011xx", ShaderDecode.Fsetp_R); Set("0101110001101x", ShaderDecode.Fmul_R);
Set("010010111011xx", ShaderDecode.Fsetp_C); Set("010010111011xx", ShaderDecode.Fsetp_C);
Set("0011011x1011xx", ShaderDecode.Fsetp_I);
Set("010110111011xx", ShaderDecode.Fsetp_R);
Set("11100000xxxxxx", ShaderDecode.Ipa); Set("11100000xxxxxx", ShaderDecode.Ipa);
Set("111000110011xx", ShaderDecode.Kil); Set("111000110011xx", ShaderDecode.Kil);
Set("1110111111011x", ShaderDecode.Ld_A); Set("1110111111011x", ShaderDecode.Ld_A);