Implement TMML and TMML.B (#1270)

* Implement TMML and TMML.B

This implement TMML and TMML.B instructions

* Fix TmmlB declaration alignment

* Address gdkchan's comments

* Fix inverted encoding definitions
This commit is contained in:
Thog 2020-05-23 12:04:35 +02:00 committed by GitHub
parent 5011640b30
commit ff7a933ec0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 126 additions and 0 deletions

View File

@ -231,6 +231,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
Set("11011101xx111x", InstEmit.TldB, typeof(OpCodeTld)); Set("11011101xx111x", InstEmit.TldB, typeof(OpCodeTld));
Set("110010xxxx111x", InstEmit.Tld4, typeof(OpCodeTld4)); Set("110010xxxx111x", InstEmit.Tld4, typeof(OpCodeTld4));
Set("1101111011111x", InstEmit.Tld4, typeof(OpCodeTld4B)); Set("1101111011111x", InstEmit.Tld4, typeof(OpCodeTld4B));
Set("11011111011000", InstEmit.TmmlB, typeof(OpCodeTexture));
Set("11011111010110", InstEmit.Tmml, typeof(OpCodeTexture));
Set("110111100x1110", InstEmit.Txd, typeof(OpCodeTxd)); Set("110111100x1110", InstEmit.Txd, typeof(OpCodeTxd));
Set("1101111101001x", InstEmit.Txq, typeof(OpCodeTex)); Set("1101111101001x", InstEmit.Txq, typeof(OpCodeTex));
Set("1101111101010x", InstEmit.TxqB, typeof(OpCodeTex)); Set("1101111101010x", InstEmit.TxqB, typeof(OpCodeTex));

View File

@ -716,6 +716,130 @@ namespace Ryujinx.Graphics.Shader.Instructions
} }
} }
public static void TmmlB(EmitterContext context)
{
EmitTextureMipMapLevel(context, true);
}
public static void Tmml(EmitterContext context)
{
EmitTextureMipMapLevel(context, false);
}
private static void EmitTextureMipMapLevel(EmitterContext context, bool isBindless)
{
OpCodeTexture op = (OpCodeTexture)context.CurrOp;
if (op.Rd.IsRZ)
{
return;
}
int raIndex = op.Ra.Index;
int rbIndex = op.Rb.Index;
Operand Ra()
{
if (raIndex > RegisterConsts.RegisterZeroIndex)
{
return Const(0);
}
return context.Copy(Register(raIndex++, RegisterType.Gpr));
}
Operand Rb()
{
if (rbIndex > RegisterConsts.RegisterZeroIndex)
{
return Const(0);
}
return context.Copy(Register(rbIndex++, RegisterType.Gpr));
}
TextureFlags flags = TextureFlags.None;
List<Operand> sourcesList = new List<Operand>();
if (isBindless)
{
sourcesList.Add(Rb());
flags |= TextureFlags.Bindless;
}
SamplerType type = ConvertSamplerType(op.Dimensions);
int coordsCount = type.GetDimensions();
Operand arrayIndex = op.IsArray ? Ra() : null;
for (int index = 0; index < coordsCount; index++)
{
sourcesList.Add(Ra());
}
if (op.IsArray)
{
sourcesList.Add(arrayIndex);
type |= SamplerType.Array;
}
Operand[] sources = sourcesList.ToArray();
int rdIndex = op.Rd.Index;
Operand GetDest()
{
if (rdIndex > RegisterConsts.RegisterZeroIndex)
{
return Const(0);
}
return Register(rdIndex++, RegisterType.Gpr);
}
int handle = !isBindless ? op.Immediate : 0;
for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
{
if ((compMask & 1) != 0)
{
Operand dest = GetDest();
// Components z and w aren't standard, we return 0 in this case and add a comment.
if (compIndex >= 2)
{
context.Add(new CommentNode("Unsupported component z or w found"));
context.Copy(dest, Const(0));
}
else
{
Operand tempDest = Local();
TextureOperation operation = new TextureOperation(
Instruction.Lod,
type,
flags,
handle,
compIndex,
tempDest,
sources);
context.Add(operation);
tempDest = context.FPMultiply(tempDest, ConstF(256.0f));
Operand finalValue = context.FPConvertToS32(tempDest);
context.Copy(dest, finalValue);
}
}
}
}
public static void Txd(EmitterContext context) public static void Txd(EmitterContext context)
{ {
OpCodeTxd op = (OpCodeTxd)context.CurrOp; OpCodeTxd op = (OpCodeTxd)context.CurrOp;