Some small gpu improvements and shader improvements, add support for ASTC 4x4 textures (slow!)

This commit is contained in:
gdkchan 2018-06-02 00:50:56 -03:00
parent aeb1bbf50c
commit 53a6922f87
11 changed files with 332 additions and 100 deletions

View file

@ -389,6 +389,7 @@ namespace Ryujinx.Graphics.Gal.Shader
SB.AppendLine(Identation + "gl_Position.xy *= flip;");
SB.AppendLine(Identation + GlslDecl.PositionOutAttrName + " = gl_Position;");
SB.AppendLine(Identation + GlslDecl.PositionOutAttrName + ".w = 1;");
}
}

View file

@ -243,6 +243,75 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
}
public static void Psetp(ShaderIrBlock Block, long OpCode)
{
bool NegA = ((OpCode >> 15) & 1) != 0;
bool NegB = ((OpCode >> 32) & 1) != 0;
bool NegP = ((OpCode >> 42) & 1) != 0;
ShaderIrInst LopInst = GetBLop24(OpCode);
ShaderIrNode OperA = GetOperPred12(OpCode);
ShaderIrNode OperB = GetOperPred29(OpCode);
if (NegA)
{
OperA = new ShaderIrOp(ShaderIrInst.Bnot, OperA);
}
if (NegB)
{
OperB = new ShaderIrOp(ShaderIrInst.Bnot, OperB);
}
ShaderIrOp Op = new ShaderIrOp(LopInst, OperA, OperB);
ShaderIrOperPred P0Node = GetOperPred3 (OpCode);
ShaderIrOperPred P1Node = GetOperPred0 (OpCode);
ShaderIrOperPred P2Node = GetOperPred39(OpCode);
Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));
LopInst = GetBLop45(OpCode);
if (LopInst == ShaderIrInst.Band && P1Node.IsConst && P2Node.IsConst)
{
return;
}
ShaderIrNode P2NNode = P2Node;
if (NegP)
{
P2NNode = new ShaderIrOp(ShaderIrInst.Bnot, P2NNode);
}
Op = new ShaderIrOp(ShaderIrInst.Bnot, P0Node);
Op = new ShaderIrOp(LopInst, Op, P2NNode);
Block.AddNode(GetPredNode(new ShaderIrAsg(P1Node, Op), OpCode));
Op = new ShaderIrOp(LopInst, P0Node, P2NNode);
Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));
}
public static void Rro_C(ShaderIrBlock Block, long OpCode)
{
EmitRro(Block, OpCode, ShaderOper.CR);
}
public static void Rro_I(ShaderIrBlock Block, long OpCode)
{
EmitRro(Block, OpCode, ShaderOper.Immf);
}
public static void Rro_R(ShaderIrBlock Block, long OpCode)
{
EmitRro(Block, OpCode, ShaderOper.RR);
}
public static void Shl_C(ShaderIrBlock Block, long OpCode)
{
EmitAluBinary(Block, OpCode, ShaderOper.CR, ShaderIrInst.Lsl);
@ -445,6 +514,33 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
}
private static void EmitIscadd(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
bool NegB = ((OpCode >> 48) & 1) != 0;
bool NegA = ((OpCode >> 49) & 1) != 0;
ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
ShaderIrOperImm Scale = GetOperImm5_39(OpCode);
switch (Oper)
{
case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
case ShaderOper.Imm: OperB = GetOperImm19_20(OpCode); break;
case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
default: throw new ArgumentException(nameof(Oper));
}
OperA = GetAluIneg(OperA, NegA);
OperB = GetAluIneg(OperB, NegB);
ShaderIrOp ScaleOp = new ShaderIrOp(ShaderIrInst.Lsl, OperA, Scale);
ShaderIrOp AddOp = new ShaderIrOp(ShaderIrInst.Add, OperB, ScaleOp);
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), AddOp), OpCode));
}
private static void EmitFmnmx(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
EmitMnmx(Block, OpCode, true, Oper);
@ -524,31 +620,27 @@ namespace Ryujinx.Graphics.Gal.Shader
}
}
private static void EmitIscadd(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
public static void EmitRro(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
bool NegB = ((OpCode >> 48) & 1) != 0;
bool NegA = ((OpCode >> 49) & 1) != 0;
//Note: this is a range reduction instruction and is supposed to
//be used with Mufu, here it just moves the value and ignores the operation.
bool NegA = ((OpCode >> 45) & 1) != 0;
bool AbsA = ((OpCode >> 49) & 1) != 0;
ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
ShaderIrOperImm Scale = GetOperImm5_39(OpCode);
ShaderIrNode OperA;
switch (Oper)
{
case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
case ShaderOper.Imm: OperB = GetOperImm19_20(OpCode); break;
case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
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 = GetAluIneg(OperA, NegA);
OperB = GetAluIneg(OperB, NegB);
OperA = GetAluFabsFneg(OperA, AbsA, NegA);
ShaderIrOp ScaleOp = new ShaderIrOp(ShaderIrInst.Lsl, OperA, Scale);
ShaderIrOp AddOp = new ShaderIrOp(ShaderIrInst.Add, OperB, ScaleOp);
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), AddOp), OpCode));
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), OperA), OpCode));
}
private static void EmitFset(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
@ -597,7 +689,7 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrOp Op = new ShaderIrOp(CmpInst, OperA, OperB);
ShaderIrInst LopInst = GetBLop(OpCode);
ShaderIrInst LopInst = GetBLop45(OpCode);
ShaderIrOperPred PNode = GetOperPred39(OpCode);
@ -685,7 +777,7 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));
ShaderIrInst LopInst = GetBLop(OpCode);
ShaderIrInst LopInst = GetBLop45(OpCode);
if (LopInst == ShaderIrInst.Band && P1Node.IsConst && P2Node.IsConst)
{

View file

@ -119,14 +119,24 @@ namespace Ryujinx.Graphics.Gal.Shader
return new ShaderIrOperImmf(Value);
}
public static ShaderIrOperPred GetOperPred0(long OpCode)
{
return new ShaderIrOperPred((int)(OpCode >> 0) & 7);
}
public static ShaderIrOperPred GetOperPred3(long OpCode)
{
return new ShaderIrOperPred((int)(OpCode >> 3) & 7);
}
public static ShaderIrOperPred GetOperPred0(long OpCode)
public static ShaderIrOperPred GetOperPred12(long OpCode)
{
return new ShaderIrOperPred((int)(OpCode >> 0) & 7);
return new ShaderIrOperPred((int)(OpCode >> 12) & 7);
}
public static ShaderIrOperPred GetOperPred29(long OpCode)
{
return new ShaderIrOperPred((int)(OpCode >> 29) & 7);
}
public static ShaderIrNode GetOperPred39N(long OpCode)
@ -184,7 +194,7 @@ namespace Ryujinx.Graphics.Gal.Shader
throw new ArgumentException(nameof(OpCode));
}
public static ShaderIrInst GetBLop(long OpCode)
public static ShaderIrInst GetBLop45(long OpCode)
{
switch ((int)(OpCode >> 45) & 3)
{
@ -196,6 +206,18 @@ namespace Ryujinx.Graphics.Gal.Shader
throw new ArgumentException(nameof(OpCode));
}
public static ShaderIrInst GetBLop24(long OpCode)
{
switch ((int)(OpCode >> 24) & 3)
{
case 0: return ShaderIrInst.Band;
case 1: return ShaderIrInst.Bor;
case 2: return ShaderIrInst.Bxor;
}
throw new ArgumentException(nameof(OpCode));
}
public static ShaderIrNode GetPredNode(ShaderIrNode Node, long OpCode)
{
ShaderIrOperPred Pred = GetPredNode(OpCode);

View file

@ -6,6 +6,8 @@ namespace Ryujinx.Graphics.Gal.Shader
{
static partial class ShaderDecode
{
private const int TempRegStart = 0x100;
public static void Ld_A(ShaderIrBlock Block, long OpCode)
{
ShaderIrNode[] Opers = GetOperAbuf20(OpCode);
@ -92,6 +94,62 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(OperA, Op1), OpCode)); //Is this right?
}
public static void Tex(ShaderIrBlock Block, long OpCode)
{
//TODO: Support other formats.
ShaderIrOperGpr[] Coords = new ShaderIrOperGpr[2];
for (int Index = 0; Index < Coords.Length; Index++)
{
Coords[Index] = GetOperGpr8(OpCode);
Coords[Index].Index += Index;
if (Coords[Index].Index > ShaderIrOperGpr.ZRIndex)
{
Coords[Index].Index = ShaderIrOperGpr.ZRIndex;
}
}
int ChMask = (int)(OpCode >> 31) & 0xf;
ShaderIrNode OperC = GetOperImm13_36(OpCode);
for (int Ch = 0; Ch < 4; Ch++)
{
ShaderIrOperGpr Dst = new ShaderIrOperGpr(TempRegStart + Ch);
ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch);
ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Texs, Coords[0], Coords[1], OperC, Meta);
Block.AddNode(GetPredNode(new ShaderIrAsg(Dst, Op), OpCode));
}
int RegInc = 0;
for (int Ch = 0; Ch < 4; Ch++)
{
if (!IsChannelUsed(ChMask, Ch))
{
continue;
}
ShaderIrOperGpr Src = new ShaderIrOperGpr(TempRegStart + Ch);
ShaderIrOperGpr Dst = GetOperGpr0(OpCode);
Dst.Index += RegInc++;
if (Dst.Index >= ShaderIrOperGpr.ZRIndex)
{
continue;
}
Block.AddNode(GetPredNode(new ShaderIrAsg(Dst, Src), OpCode));
}
}
public static void Texs(ShaderIrBlock Block, long OpCode)
{
EmitTex(Block, OpCode, ShaderIrInst.Texs);
@ -109,11 +167,24 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode OperB = GetOperGpr20 (OpCode);
ShaderIrNode OperC = GetOperImm13_36(OpCode);
bool TwoDests = GetOperGpr28(OpCode).Index != ShaderIrOperGpr.ZRIndex;
int ChMask;
switch ((OpCode >> 50) & 7)
{
case 0: ChMask = TwoDests ? 0x7 : 0x1; break;
case 1: ChMask = TwoDests ? 0xb : 0x2; break;
case 2: ChMask = TwoDests ? 0xd : 0x4; break;
case 3: ChMask = TwoDests ? 0xe : 0x8; break;
case 4: ChMask = TwoDests ? 0xf : 0x3; break;
default: throw new InvalidOperationException();
}
for (int Ch = 0; Ch < 4; Ch++)
{
//Assign it to a temp because the destination registers
//may be used as texture coord input aswell.
ShaderIrOperGpr Dst = new ShaderIrOperGpr(0x100 + Ch);
ShaderIrOperGpr Dst = new ShaderIrOperGpr(TempRegStart + Ch);
ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch);
@ -122,15 +193,22 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(Dst, Op), OpCode));
}
int RegInc = 0;
for (int Ch = 0; Ch < 4; Ch++)
{
ShaderIrOperGpr Src = new ShaderIrOperGpr(0x100 + Ch);
if (!IsChannelUsed(ChMask, Ch))
{
continue;
}
ShaderIrOperGpr Dst = (Ch >> 1) != 0
ShaderIrOperGpr Src = new ShaderIrOperGpr(TempRegStart + Ch);
ShaderIrOperGpr Dst = (RegInc >> 1) != 0
? GetOperGpr28(OpCode)
: GetOperGpr0 (OpCode);
Dst.Index += Ch & 1;
Dst.Index += RegInc++ & 1;
if (Dst.Index >= ShaderIrOperGpr.ZRIndex)
{
@ -138,7 +216,17 @@ namespace Ryujinx.Graphics.Gal.Shader
}
Block.AddNode(GetPredNode(new ShaderIrAsg(Dst, Src), OpCode));
/*if (IsScalar)
{
break;
}*/
}
}
private static bool IsChannelUsed(int ChMask, int Ch)
{
return (ChMask & (1 << Ch)) != 0;
}
}
}

View file

@ -82,6 +82,10 @@ namespace Ryujinx.Graphics.Gal.Shader
Set("000000010000xx", ShaderDecode.Mov_I32);
Set("0101110010011x", ShaderDecode.Mov_R);
Set("0101000010000x", ShaderDecode.Mufu);
Set("0101000010010x", ShaderDecode.Psetp);
Set("0100110010010x", ShaderDecode.Rro_C);
Set("0011100x10010x", ShaderDecode.Rro_I);
Set("0101110010010x", ShaderDecode.Rro_R);
Set("0100110001001x", ShaderDecode.Shl_C);
Set("0011100x01001x", ShaderDecode.Shl_I);
Set("0101110001001x", ShaderDecode.Shl_R);
@ -89,6 +93,7 @@ namespace Ryujinx.Graphics.Gal.Shader
Set("0011100x00101x", ShaderDecode.Shr_I);
Set("0101110000101x", ShaderDecode.Shr_R);
Set("1110111111110x", ShaderDecode.St_A);
Set("110000xxxx111x", ShaderDecode.Tex);
Set("1101111101001x", ShaderDecode.Texq);
Set("1101100xxxxxxx", ShaderDecode.Texs);
Set("1101101xxxxxxx", ShaderDecode.Tlds);