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
parent 2d669d4c23
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.Texa)
{
int Handle = ((ShaderIrOperImm)Op.OperandC).Imm;
int Handle = ((ShaderIrOperImm)Op.OperandC).Value;
int Index = Handle - TexStartIndex;

View file

@ -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))
{

View file

@ -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));
}

View file

@ -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)

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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);