Implement TLD4 and TLD4S
This commit is contained in:
parent
82e10ad3ad
commit
a1df758958
7 changed files with 256 additions and 9 deletions
|
@ -226,6 +226,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
|
||||
if (Op.Inst == ShaderIrInst.Texq ||
|
||||
Op.Inst == ShaderIrInst.Texs ||
|
||||
Op.Inst == ShaderIrInst.Tld4 ||
|
||||
Op.Inst == ShaderIrInst.Txlf)
|
||||
{
|
||||
int Handle = ((ShaderIrOperImm)Op.OperandC).Value;
|
||||
|
@ -241,14 +242,14 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
// TODO: non 2d texture type for TEXQ?
|
||||
if (Op.Inst == ShaderIrInst.Texq)
|
||||
{
|
||||
TextureType = TextureType.TwoD;
|
||||
TextureType = TextureType.TwoD;
|
||||
TextureInstructionSuffix = TextureInstructionSuffix.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShaderIrMetaTex Meta = ((ShaderIrMetaTex)Op.MetaData);
|
||||
|
||||
TextureType = Meta.TextureType;
|
||||
TextureType = Meta.TextureType;
|
||||
TextureInstructionSuffix = Meta.TextureInstructionSuffix;
|
||||
}
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
{ ShaderIrInst.Texb, GetTexbExpr },
|
||||
{ ShaderIrInst.Texq, GetTexqExpr },
|
||||
{ ShaderIrInst.Texs, GetTexsExpr },
|
||||
{ ShaderIrInst.Tld4, GetTld4Expr },
|
||||
{ ShaderIrInst.Trunc, GetTruncExpr },
|
||||
{ ShaderIrInst.Txlf, GetTxlfExpr },
|
||||
{ ShaderIrInst.Utof, GetUtofExpr },
|
||||
|
@ -837,6 +838,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
case ShaderIrInst.Ipa:
|
||||
case ShaderIrInst.Texq:
|
||||
case ShaderIrInst.Texs:
|
||||
case ShaderIrInst.Tld4:
|
||||
case ShaderIrInst.Txlf:
|
||||
return false;
|
||||
}
|
||||
|
@ -1219,6 +1221,19 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
return GetTextureOperation(Op, Sampler, Coords, Ch);
|
||||
}
|
||||
|
||||
private string GetTld4Expr(ShaderIrOp Op)
|
||||
{
|
||||
ShaderIrMetaTex Meta = (ShaderIrMetaTex)Op.MetaData;
|
||||
|
||||
string Sampler = GetTexSamplerName(Op);
|
||||
|
||||
string Coords = GetTexSamplerCoords(Op);
|
||||
|
||||
string Ch = "rgba".Substring(Meta.Elem, 1);
|
||||
|
||||
return GetTextureGatherOperation(Op, Sampler, Coords, Ch);
|
||||
}
|
||||
|
||||
private string GetTxlfExpr(ShaderIrOp Op)
|
||||
{
|
||||
// TODO: DC AND MZ
|
||||
|
@ -1346,7 +1361,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
string DepthArgument = "";
|
||||
|
||||
int VecSize = Coords;
|
||||
if (HasDepth)
|
||||
if (HasDepth && Op.Inst != ShaderIrInst.Tld4)
|
||||
{
|
||||
VecSize++;
|
||||
DepthArgument = $", {GetOperExpr(Op, Meta.DepthCompare)}";
|
||||
|
@ -1406,6 +1421,29 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
}
|
||||
}
|
||||
|
||||
private string GetTextureGatherOperation(ShaderIrOp Op, string Sampler, string Coords, string Ch)
|
||||
{
|
||||
ShaderIrMetaTex Meta = (ShaderIrMetaTex)Op.MetaData;
|
||||
|
||||
TextureInstructionSuffix Suffix = Meta.TextureInstructionSuffix;
|
||||
|
||||
string ChString = "." + Ch;
|
||||
|
||||
string Comp = Meta.Component.ToString();
|
||||
|
||||
if ((Suffix & TextureInstructionSuffix.DC) != 0)
|
||||
{
|
||||
Comp = GetOperExpr(Op, Meta.DepthCompare);
|
||||
}
|
||||
|
||||
// TODO
|
||||
if ((Suffix & TextureInstructionSuffix.AOFFI) != 0)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
return "textureGather(" + Sampler + ", " + Coords + ", " + Comp + ")" + ChString;
|
||||
}
|
||||
|
||||
private string GetTextureOperation(ShaderIrOp Op, string Sampler, string Coords, string Ch)
|
||||
{
|
||||
ShaderIrMetaTex Meta = (ShaderIrMetaTex)Op.MetaData;
|
||||
|
|
|
@ -279,9 +279,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
TextureInstructionSuffix |= TextureInstructionSuffix.DC;
|
||||
}
|
||||
|
||||
ShaderIrOperGpr[] Coords = null;
|
||||
|
||||
Coords = new ShaderIrOperGpr[ImageUtils.GetCoordsCountTextureType(TextureType)];
|
||||
ShaderIrOperGpr[] Coords = new ShaderIrOperGpr[ImageUtils.GetCoordsCountTextureType(TextureType)];
|
||||
|
||||
int IndexExtraCoord = 0;
|
||||
|
||||
|
@ -453,6 +451,63 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
EmitTexs(Block, OpCode, ShaderIrInst.Txlf, TextureType, GetSuffix());
|
||||
}
|
||||
|
||||
public static void Tld4(ShaderIrBlock Block, long OpCode, int Position)
|
||||
{
|
||||
TextureInstructionSuffix GetSuffix()
|
||||
{
|
||||
int RawSuffix = OpCode.Read(0x34, 0x38);
|
||||
|
||||
switch (RawSuffix)
|
||||
{
|
||||
case 0:
|
||||
return TextureInstructionSuffix.None;
|
||||
case 0x4:
|
||||
return TextureInstructionSuffix.AOFFI;
|
||||
case 0x8:
|
||||
return TextureInstructionSuffix.PTP;
|
||||
default:
|
||||
throw new InvalidOperationException($"Invalid Suffix for TLD4 instruction {RawSuffix}");
|
||||
}
|
||||
}
|
||||
|
||||
bool IsShadow = OpCode.Read(0x32);
|
||||
|
||||
bool IsArray = OpCode.HasArray();
|
||||
int ChMask = OpCode.Read(31, 0xf);
|
||||
|
||||
TextureType TextureType = TexToTextureType(OpCode.Read(28, 6), IsArray);
|
||||
|
||||
TextureInstructionSuffix Suffix = GetSuffix();
|
||||
|
||||
if (IsShadow)
|
||||
{
|
||||
Suffix |= TextureInstructionSuffix.DC;
|
||||
}
|
||||
|
||||
EmitTld4(Block, OpCode, TextureType, Suffix, ChMask, OpCode.Read(0x38, 0x3), false);
|
||||
}
|
||||
|
||||
public static void Tld4s(ShaderIrBlock Block, long OpCode, int Position)
|
||||
{
|
||||
TextureInstructionSuffix Suffix = TextureInstructionSuffix.None;
|
||||
|
||||
bool IsOffset = OpCode.Read(0x33);
|
||||
bool IsShadow = OpCode.Read(0x32);
|
||||
|
||||
if (IsOffset)
|
||||
{
|
||||
Suffix |= TextureInstructionSuffix.AOFFI;
|
||||
}
|
||||
|
||||
if (IsShadow)
|
||||
{
|
||||
Suffix |= TextureInstructionSuffix.DC;
|
||||
}
|
||||
|
||||
// TLD4S seems to only support 2D textures with RGBA mask?
|
||||
EmitTld4(Block, OpCode, TextureType.TwoD, Suffix, RGBA, OpCode.Read(0x34, 0x3), true);
|
||||
}
|
||||
|
||||
private static void EmitTexs(ShaderIrBlock Block, long OpCode, ShaderIrInst Inst, TextureType TextureType, TextureInstructionSuffix TextureInstructionSuffix)
|
||||
{
|
||||
if (Inst == ShaderIrInst.Txlf && TextureType == TextureType.CubeArray)
|
||||
|
@ -640,6 +695,154 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
}
|
||||
}
|
||||
|
||||
private static void EmitTld4(ShaderIrBlock Block, long OpCode, TextureType TextureType, TextureInstructionSuffix TextureInstructionSuffix, int ChMask, int Component, bool Scalar)
|
||||
{
|
||||
ShaderIrOperGpr OperA = OpCode.Gpr8();
|
||||
ShaderIrOperGpr OperB = OpCode.Gpr20();
|
||||
ShaderIrOperImm OperC = OpCode.Imm13_36();
|
||||
|
||||
ShaderIrOperGpr[] Coords = new ShaderIrOperGpr[ImageUtils.GetCoordsCountTextureType(TextureType)];
|
||||
|
||||
ShaderIrOperGpr Offset = null;
|
||||
ShaderIrOperGpr DepthCompare = null;
|
||||
|
||||
bool IsArray = ImageUtils.IsArray(TextureType);
|
||||
|
||||
int OperBIndex = 0;
|
||||
|
||||
if (Scalar)
|
||||
{
|
||||
int CoordStartIndex = 0;
|
||||
|
||||
if (IsArray)
|
||||
{
|
||||
CoordStartIndex++;
|
||||
Coords[Coords.Length - 1] = OperB;
|
||||
}
|
||||
|
||||
switch (Coords.Length - CoordStartIndex)
|
||||
{
|
||||
case 1:
|
||||
Coords[0] = OpCode.Gpr8();
|
||||
|
||||
break;
|
||||
case 2:
|
||||
Coords[0] = OpCode.Gpr8();
|
||||
Coords[0].Index += CoordStartIndex;
|
||||
|
||||
break;
|
||||
case 3:
|
||||
Coords[0] = OpCode.Gpr8();
|
||||
Coords[0].Index += CoordStartIndex;
|
||||
|
||||
Coords[1] = OpCode.Gpr8();
|
||||
Coords[1].Index += 1 + CoordStartIndex;
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException($"{Coords.Length - CoordStartIndex} coords textures aren't supported in TLD4S");
|
||||
}
|
||||
|
||||
if (Coords.Length - CoordStartIndex != 1)
|
||||
{
|
||||
Coords[Coords.Length - CoordStartIndex - 1] = OperB;
|
||||
OperBIndex++;
|
||||
}
|
||||
|
||||
if (TextureInstructionSuffix != TextureInstructionSuffix.None && TextureType == TextureType.TwoD)
|
||||
{
|
||||
Coords[Coords.Length - CoordStartIndex - 1] = OpCode.Gpr8();
|
||||
Coords[Coords.Length - CoordStartIndex - 1].Index += Coords.Length - CoordStartIndex - 1;
|
||||
OperBIndex--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int IndexExtraCoord = 0;
|
||||
|
||||
if (IsArray)
|
||||
{
|
||||
IndexExtraCoord++;
|
||||
|
||||
Coords[Coords.Length - 1] = OpCode.Gpr8();
|
||||
}
|
||||
|
||||
for (int Index = 0; Index < Coords.Length - IndexExtraCoord; Index++)
|
||||
{
|
||||
Coords[Index] = OpCode.Gpr8();
|
||||
|
||||
Coords[Index].Index += Index;
|
||||
|
||||
Coords[Index].Index += IndexExtraCoord;
|
||||
|
||||
if (Coords[Index].Index > ShaderIrOperGpr.ZRIndex)
|
||||
{
|
||||
Coords[Index].Index = ShaderIrOperGpr.ZRIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((TextureInstructionSuffix & TextureInstructionSuffix.AOFFI) != 0)
|
||||
{
|
||||
Offset = OpCode.Gpr20();
|
||||
Offset.Index += OperBIndex;
|
||||
OperBIndex++;
|
||||
}
|
||||
|
||||
if ((TextureInstructionSuffix & TextureInstructionSuffix.DC) != 0)
|
||||
{
|
||||
DepthCompare = OpCode.Gpr20();
|
||||
DepthCompare.Index += OperBIndex;
|
||||
OperBIndex++;
|
||||
}
|
||||
|
||||
|
||||
for (int Ch = 0; Ch < 4; Ch++)
|
||||
{
|
||||
// Avoid usuless variable creation
|
||||
if (!IsChannelUsed(ChMask, Ch))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ShaderIrOperGpr Dst = new ShaderIrOperGpr(TempRegStart + Ch);
|
||||
|
||||
ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch, TextureType, TextureInstructionSuffix, Coords)
|
||||
{
|
||||
Component = Component,
|
||||
Offset = Offset,
|
||||
DepthCompare = DepthCompare
|
||||
};
|
||||
|
||||
ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Tld4, OperA, OperB, OperC, Meta);
|
||||
|
||||
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(Dst, Op)));
|
||||
}
|
||||
|
||||
int RegInc = 0;
|
||||
|
||||
for (int Ch = 0; Ch < 4; Ch++)
|
||||
{
|
||||
if (!IsChannelUsed(ChMask, Ch))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ShaderIrOperGpr Src = new ShaderIrOperGpr(TempRegStart + Ch);
|
||||
|
||||
ShaderIrOperGpr Dst = OpCode.Gpr0();
|
||||
|
||||
Dst.Index += RegInc++;
|
||||
|
||||
if (Dst.Index >= ShaderIrOperGpr.ZRIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(Dst, Src)));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsChannelUsed(int ChMask, int Ch)
|
||||
{
|
||||
return (ChMask & (1 << Ch)) != 0;
|
||||
|
|
|
@ -49,6 +49,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
Ipa,
|
||||
Texb,
|
||||
Texs,
|
||||
Tld4,
|
||||
Trunc,
|
||||
F_End,
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
public ShaderIrOperGpr LevelOfDetail;
|
||||
public ShaderIrOperGpr Offset;
|
||||
public ShaderIrOperGpr DepthCompare;
|
||||
public int Component; // for TLD4(S)
|
||||
|
||||
public ShaderIrMetaTex(int Elem, TextureType TextureType, TextureInstructionSuffix TextureInstructionSuffix, params ShaderIrNode[] Coordinates)
|
||||
{
|
||||
|
|
|
@ -122,6 +122,8 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
Set("1101111101001x", ShaderDecode.Texq);
|
||||
Set("1101x00xxxxxxx", ShaderDecode.Texs);
|
||||
Set("1101101xxxxxxx", ShaderDecode.Tlds);
|
||||
Set("110010xxxx111x", ShaderDecode.Tld4);
|
||||
Set("1101111100xxxx", ShaderDecode.Tld4s);
|
||||
Set("01011111xxxxxx", ShaderDecode.Vmad);
|
||||
Set("0100111xxxxxxx", ShaderDecode.Xmad_CR);
|
||||
Set("0011011x00xxxx", ShaderDecode.Xmad_I);
|
||||
|
|
|
@ -9,10 +9,11 @@ namespace Ryujinx.Graphics.Texture
|
|||
LZ = 0x02, // Load LOD Zero
|
||||
LB = 0x08, // Load Bias
|
||||
LL = 0x10, // Load LOD
|
||||
LBA = 0x20, // Load Bias with OperA?
|
||||
LLA = 0x40, // Load LOD with OperA?
|
||||
LBA = 0x20, // Load Bias with OperA? Auto?
|
||||
LLA = 0x40, // Load LOD with OperA? Auto?
|
||||
DC = 0x80, // Depth Compare
|
||||
AOFFI = 0x100, // Offset
|
||||
MZ = 0x200 // Multisample Zero?
|
||||
MZ = 0x200, // Multisample Zero?
|
||||
PTP = 0x400 // ???
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue