Some small sync primitive fixes, logging fixes, started to implement the 2D engine on the GPU, fixed DrawArrays, implemented a few more shader instructions, made a start on nvdrv refactor, etc...

This commit is contained in:
gdkchan 2018-04-25 23:11:26 -03:00
parent 211f7f69db
commit a38a72b062
27 changed files with 816 additions and 199 deletions

View file

@ -31,51 +31,53 @@ namespace Ryujinx.Graphics.Gal.Shader
{
InstsExpr = new Dictionary<ShaderIrInst, GetInstExpr>()
{
{ ShaderIrInst.And, GetAndExpr },
{ ShaderIrInst.Asr, GetAsrExpr },
{ ShaderIrInst.Band, GetBandExpr },
{ ShaderIrInst.Bnot, GetBnotExpr },
{ ShaderIrInst.Ceil, GetCeilExpr },
{ ShaderIrInst.Ceq, GetCeqExpr },
{ ShaderIrInst.Cge, GetCgeExpr },
{ ShaderIrInst.Cgt, GetCgtExpr },
{ ShaderIrInst.Clamp, GetClampExpr },
{ ShaderIrInst.Cle, GetCleExpr },
{ ShaderIrInst.Clt, GetCltExpr },
{ ShaderIrInst.Cne, GetCneExpr },
{ ShaderIrInst.Exit, GetExitExpr },
{ ShaderIrInst.Fabs, GetFabsExpr },
{ ShaderIrInst.Fadd, GetFaddExpr },
{ ShaderIrInst.Fceq, GetCeqExpr },
{ ShaderIrInst.Fcge, GetCgeExpr },
{ ShaderIrInst.Fcgt, GetCgtExpr },
{ ShaderIrInst.Fcle, GetCleExpr },
{ ShaderIrInst.Fclt, GetCltExpr },
{ ShaderIrInst.Fcne, GetCneExpr },
{ ShaderIrInst.Fcos, GetFcosExpr },
{ ShaderIrInst.Fex2, GetFex2Expr },
{ ShaderIrInst.Ffma, GetFfmaExpr },
{ ShaderIrInst.Flg2, GetFlg2Expr },
{ ShaderIrInst.Floor, GetFloorExpr },
{ ShaderIrInst.Fmul, GetFmulExpr },
{ ShaderIrInst.Fneg, GetFnegExpr },
{ ShaderIrInst.Frcp, GetFrcpExpr },
{ ShaderIrInst.Frsq, GetFrsqExpr },
{ ShaderIrInst.Fsin, GetFsinExpr },
{ ShaderIrInst.Ftos, GetFtosExpr },
{ ShaderIrInst.Ftou, GetFtouExpr },
{ ShaderIrInst.Ipa, GetIpaExpr },
{ ShaderIrInst.Kil, GetKilExpr },
{ ShaderIrInst.Lsr, GetLsrExpr },
{ ShaderIrInst.Not, GetNotExpr },
{ ShaderIrInst.Or, GetOrExpr },
{ ShaderIrInst.Stof, GetStofExpr },
{ ShaderIrInst.Texq, GetTexqExpr },
{ ShaderIrInst.Texs, GetTexsExpr },
{ ShaderIrInst.Trunc, GetTruncExpr },
{ ShaderIrInst.Txlf, GetTxlfExpr },
{ ShaderIrInst.Utof, GetUtofExpr },
{ ShaderIrInst.Xor, GetXorExpr }
{ ShaderIrInst.And, GetAndExpr },
{ ShaderIrInst.Asr, GetAsrExpr },
{ ShaderIrInst.Band, GetBandExpr },
{ ShaderIrInst.Bnot, GetBnotExpr },
{ ShaderIrInst.Ceil, GetCeilExpr },
{ ShaderIrInst.Ceq, GetCeqExpr },
{ ShaderIrInst.Cge, GetCgeExpr },
{ ShaderIrInst.Cgt, GetCgtExpr },
{ ShaderIrInst.Clamps, GetClampsExpr },
{ ShaderIrInst.Clampu, GetClampuExpr },
{ ShaderIrInst.Cle, GetCleExpr },
{ ShaderIrInst.Clt, GetCltExpr },
{ ShaderIrInst.Cne, GetCneExpr },
{ ShaderIrInst.Exit, GetExitExpr },
{ ShaderIrInst.Fabs, GetFabsExpr },
{ ShaderIrInst.Fadd, GetFaddExpr },
{ ShaderIrInst.Fceq, GetCeqExpr },
{ ShaderIrInst.Fcge, GetCgeExpr },
{ ShaderIrInst.Fcgt, GetCgtExpr },
{ ShaderIrInst.Fclamp, GetFclampExpr },
{ ShaderIrInst.Fcle, GetCleExpr },
{ ShaderIrInst.Fclt, GetCltExpr },
{ ShaderIrInst.Fcne, GetCneExpr },
{ ShaderIrInst.Fcos, GetFcosExpr },
{ ShaderIrInst.Fex2, GetFex2Expr },
{ ShaderIrInst.Ffma, GetFfmaExpr },
{ ShaderIrInst.Flg2, GetFlg2Expr },
{ ShaderIrInst.Floor, GetFloorExpr },
{ ShaderIrInst.Fmul, GetFmulExpr },
{ ShaderIrInst.Fneg, GetFnegExpr },
{ ShaderIrInst.Frcp, GetFrcpExpr },
{ ShaderIrInst.Frsq, GetFrsqExpr },
{ ShaderIrInst.Fsin, GetFsinExpr },
{ ShaderIrInst.Ftos, GetFtosExpr },
{ ShaderIrInst.Ftou, GetFtouExpr },
{ ShaderIrInst.Ipa, GetIpaExpr },
{ ShaderIrInst.Kil, GetKilExpr },
{ ShaderIrInst.Lsr, GetLsrExpr },
{ ShaderIrInst.Not, GetNotExpr },
{ ShaderIrInst.Or, GetOrExpr },
{ ShaderIrInst.Stof, GetStofExpr },
{ ShaderIrInst.Texq, GetTexqExpr },
{ ShaderIrInst.Texs, GetTexsExpr },
{ ShaderIrInst.Trunc, GetTruncExpr },
{ ShaderIrInst.Txlf, GetTxlfExpr },
{ ShaderIrInst.Utof, GetUtofExpr },
{ ShaderIrInst.Xor, GetXorExpr }
};
}
@ -478,7 +480,19 @@ namespace Ryujinx.Graphics.Gal.Shader
private string GetCeilExpr(ShaderIrOp Op) => GetUnaryCall(Op, "ceil");
private string GetClampExpr(ShaderIrOp Op) => GetTernaryCall(Op, "clamp");
private string GetClampsExpr(ShaderIrOp Op)
{
return "clamp(" + GetOperExpr(Op, Op.OperandA) + ", " +
GetOperExpr(Op, Op.OperandB) + ", " +
GetOperExpr(Op, Op.OperandC) + ")";
}
private string GetClampuExpr(ShaderIrOp Op)
{
return "int(clamp(uint(" + GetOperExpr(Op, Op.OperandA) + "), " +
"uint(" + GetOperExpr(Op, Op.OperandB) + "), " +
"uint(" + GetOperExpr(Op, Op.OperandC) + ")))";
}
private string GetCltExpr(ShaderIrOp Op) => GetBinaryExpr(Op, "<");
private string GetCeqExpr(ShaderIrOp Op) => GetBinaryExpr(Op, "==");
@ -499,6 +513,8 @@ namespace Ryujinx.Graphics.Gal.Shader
private string GetFfmaExpr(ShaderIrOp Op) => GetTernaryExpr(Op, "*", "+");
private string GetFclampExpr(ShaderIrOp Op) => GetTernaryCall(Op, "clamp");
private string GetFlg2Expr(ShaderIrOp Op) => GetUnaryCall(Op, "log2");
private string GetFloorExpr(ShaderIrOp Op) => GetUnaryCall(Op, "floor");

View file

@ -66,6 +66,21 @@ namespace Ryujinx.Graphics.Gal.Shader
EmitAluBinaryF(Block, OpCode, ShaderOper.RR, ShaderIrInst.Fmul);
}
public static void Fset_C(ShaderIrBlock Block, long OpCode)
{
EmitFset(Block, OpCode, ShaderOper.CR);
}
public static void Fset_I(ShaderIrBlock Block, long OpCode)
{
EmitFset(Block, OpCode, ShaderOper.Immf);
}
public static void Fset_R(ShaderIrBlock Block, long OpCode)
{
EmitFset(Block, OpCode, ShaderOper.RR);
}
public static void Fsetp_C(ShaderIrBlock Block, long OpCode)
{
EmitFsetp(Block, OpCode, ShaderOper.CR);
@ -279,6 +294,78 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
}
private static void EmitFset(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
EmitSet(Block, OpCode, true, Oper);
}
private static void EmitIset(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
EmitSet(Block, OpCode, false, Oper);
}
private static void EmitSet(ShaderIrBlock Block, long OpCode, bool IsFloat, ShaderOper Oper)
{
bool Na = ((OpCode >> 43) & 1) != 0;
bool Ab = ((OpCode >> 44) & 1) != 0;
bool Nb = ((OpCode >> 53) & 1) != 0;
bool Aa = ((OpCode >> 54) & 1) != 0;
ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
switch (Oper)
{
case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
case ShaderOper.Imm: OperB = GetOperImm19_20 (OpCode); break;
case ShaderOper.Immf: OperB = GetOperImmf19_20(OpCode); break;
case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
default: throw new ArgumentException(nameof(Oper));
}
ShaderIrInst CmpInst;
if (IsFloat)
{
OperA = GetAluAbsNeg(OperA, Aa, Na);
OperB = GetAluAbsNeg(OperB, Ab, Nb);
CmpInst = GetCmpF(OpCode);
}
else
{
CmpInst = GetCmp(OpCode);
}
ShaderIrOp Op = new ShaderIrOp(CmpInst, OperA, OperB);
ShaderIrInst LopInst = GetBLop(OpCode);
ShaderIrOperPred PNode = GetOperPred39(OpCode);
ShaderIrOperImmf Imm0 = new ShaderIrOperImmf(0);
ShaderIrOperImmf Imm1 = new ShaderIrOperImmf(1);
ShaderIrNode Asg0 = new ShaderIrAsg(GetOperGpr0(OpCode), Imm0);
ShaderIrNode Asg1 = new ShaderIrAsg(GetOperGpr0(OpCode), Imm1);
if (LopInst != ShaderIrInst.Band || !PNode.IsConst)
{
ShaderIrOp Op2 = new ShaderIrOp(LopInst, Op, PNode);
Asg0 = new ShaderIrCond(Op2, Asg0, Not: true);
Asg1 = new ShaderIrCond(Op2, Asg1, Not: false);
}
else
{
Asg0 = new ShaderIrCond(Op, Asg0, Not: true);
Asg1 = new ShaderIrCond(Op, Asg1, Not: false);
}
Block.AddNode(GetPredNode(Asg0, OpCode));
Block.AddNode(GetPredNode(Asg1, OpCode));
}
private static void EmitFsetp(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
EmitSetp(Block, OpCode, true, Oper);

View file

@ -70,6 +70,21 @@ namespace Ryujinx.Graphics.Gal.Shader
EmitI2f(Block, OpCode, ShaderOper.RR);
}
public static void I2i_C(ShaderIrBlock Block, long OpCode)
{
EmitI2i(Block, OpCode, ShaderOper.CR);
}
public static void I2i_I(ShaderIrBlock Block, long OpCode)
{
EmitI2i(Block, OpCode, ShaderOper.Imm);
}
public static void I2i_R(ShaderIrBlock Block, long OpCode)
{
EmitI2i(Block, OpCode, ShaderOper.RR);
}
public static void Mov_C(ShaderIrBlock Block, long OpCode)
{
ShaderIrOperCbuf Cbuf = GetOperCbuf34(OpCode);
@ -183,7 +198,7 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrOperImmf IMin = new ShaderIrOperImmf(CMin);
ShaderIrOperImmf IMax = new ShaderIrOperImmf(CMax);
OperA = new ShaderIrOp(ShaderIrInst.Clamp, OperA, IMin, IMax);
OperA = new ShaderIrOp(ShaderIrInst.Fclamp, OperA, IMin, IMax);
}
ShaderIrInst Inst = Signed
@ -252,6 +267,81 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
}
private static void EmitI2i(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
IntType Type = GetIntType(OpCode);
if (Type == IntType.U64 ||
Type == IntType.S64)
{
//TODO: 64-bits support.
//Note: GLSL doesn't support 64-bits integers.
throw new NotImplementedException();
}
int Sel = (int)(OpCode >> 41) & 3;
bool NegA = ((OpCode >> 45) & 1) != 0;
bool AbsA = ((OpCode >> 49) & 1) != 0;
bool SatA = ((OpCode >> 50) & 1) != 0;
ShaderIrNode OperA;
switch (Oper)
{
case ShaderOper.CR: OperA = GetOperCbuf34 (OpCode); break;
case ShaderOper.Immf: OperA = GetOperImmf19_20(OpCode); break;
case ShaderOper.RR: OperA = GetOperGpr20 (OpCode); break;
default: throw new ArgumentException(nameof(Oper));
}
OperA = GetAluAbsNeg(OperA, AbsA, NegA);
bool Signed = Type >= IntType.S8;
int Shift = Sel * 8;
int Size = 8 << ((int)Type & 3);
if (Shift != 0)
{
OperA = new ShaderIrOp(ShaderIrInst.Asr, OperA, new ShaderIrOperImm(Shift));
}
if (Size < 32)
{
uint Mask = uint.MaxValue >> (32 - Size);
if (SatA)
{
uint CMin = 0;
uint CMax = Mask;
if (Signed)
{
uint HalfMask = Mask >> 1;
CMin -= HalfMask + 1;
CMax = HalfMask;
}
ShaderIrOperImm IMin = new ShaderIrOperImm((int)CMin);
ShaderIrOperImm IMax = new ShaderIrOperImm((int)CMax);
OperA = new ShaderIrOp(Signed
? ShaderIrInst.Clamps
: ShaderIrInst.Clampu, OperA, IMin, IMax);
}
else
{
OperA = new ShaderIrOp(ShaderIrInst.And, OperA, new ShaderIrOperImm((int)Mask));
}
}
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), OperA), OpCode));
}
private static IntType GetIntType(long OpCode)
{
bool Signed = ((OpCode >> 13) & 1) != 0;

View file

@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Gal.Shader
F_Start,
Ceil,
Clamp,
Fabs,
Fadd,
Fceq,
@ -22,6 +22,7 @@ namespace Ryujinx.Graphics.Gal.Shader
Fcgeu,
Fcgt,
Fcgtu,
Fclamp,
Fcle,
Fcleu,
Fclt,
@ -53,6 +54,8 @@ namespace Ryujinx.Graphics.Gal.Shader
Ceq,
Cge,
Cgt,
Clamps,
Clampu,
Cle,
Clt,
Cne,

View file

@ -6,11 +6,24 @@ namespace Ryujinx.Graphics.Gal.Shader
{
private const int EncodingBits = 14;
private static ShaderDecodeFunc[] OpCodes;
private class ShaderDecodeEntry
{
public ShaderDecodeFunc Func;
public int XBits;
public ShaderDecodeEntry(ShaderDecodeFunc Func, int XBits)
{
this.Func = Func;
this.XBits = XBits;
}
}
private static ShaderDecodeEntry[] OpCodes;
static ShaderOpCodeTable()
{
OpCodes = new ShaderDecodeFunc[1 << EncodingBits];
OpCodes = new ShaderDecodeEntry[1 << EncodingBits];
#region Instructions
Set("111000110000xx", ShaderDecode.Exit);
@ -31,12 +44,18 @@ namespace Ryujinx.Graphics.Gal.Shader
Set("0100110001101x", ShaderDecode.Fmul_C);
Set("0011100x01101x", ShaderDecode.Fmul_I);
Set("0101110001101x", ShaderDecode.Fmul_R);
Set("0100100xxxxxxx", ShaderDecode.Fset_C);
Set("0011000xxxxxxx", ShaderDecode.Fset_I);
Set("01011000xxxxxx", ShaderDecode.Fset_R);
Set("010010111011xx", ShaderDecode.Fsetp_C);
Set("0011011x1011xx", ShaderDecode.Fsetp_I);
Set("010110111011xx", ShaderDecode.Fsetp_R);
Set("0100110010111x", ShaderDecode.I2f_C);
Set("0011100x10111x", ShaderDecode.I2f_I);
Set("0101110010111x", ShaderDecode.I2f_R);
Set("0100110011100x", ShaderDecode.I2i_C);
Set("0011100x11100x", ShaderDecode.I2i_I);
Set("0101110011100x", ShaderDecode.I2i_R);
Set("11100000xxxxxx", ShaderDecode.Ipa);
Set("010010110110xx", ShaderDecode.Isetp_C);
Set("0011011x0110xx", ShaderDecode.Isetp_I);
@ -91,6 +110,8 @@ namespace Ryujinx.Graphics.Gal.Shader
XMask = ~XMask;
ShaderDecodeEntry Entry = new ShaderDecodeEntry(Func, XBits);
for (int Index = 0; Index < (1 << XBits); Index++)
{
Value &= XMask;
@ -100,13 +121,16 @@ namespace Ryujinx.Graphics.Gal.Shader
Value |= ((Index >> X) & 1) << XPos[X];
}
OpCodes[Value] = Func;
if (OpCodes[Value] == null || OpCodes[Value].XBits > XBits)
{
OpCodes[Value] = Entry;
}
}
}
public static ShaderDecodeFunc GetDecoder(long OpCode)
{
return OpCodes[(ulong)OpCode >> (64 - EncodingBits)];
return OpCodes[(ulong)OpCode >> (64 - EncodingBits)]?.Func;
}
}
}