aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThog <me@thog.eu>2020-05-23 12:04:35 +0200
committerGitHub <noreply@github.com>2020-05-23 12:04:35 +0200
commitff7a933ec01f790aa842b0ef75081ed3e0a654a2 (patch)
treeb557c53e149482d65b4baefbb0e1ebaba19d93d0
parent5011640b3086b86b0f0b39b60fdb2aa946d4f5c8 (diff)
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
-rw-r--r--Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs2
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs124
2 files changed, 126 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs
index dcb6b1f6..be93f137 100644
--- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs
@@ -231,6 +231,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
Set("11011101xx111x", InstEmit.TldB, typeof(OpCodeTld));
Set("110010xxxx111x", InstEmit.Tld4, typeof(OpCodeTld4));
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("1101111101001x", InstEmit.Txq, typeof(OpCodeTex));
Set("1101111101010x", InstEmit.TxqB, typeof(OpCodeTex));
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
index 7f7a48a6..af5122be 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
@@ -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)
{
OpCodeTxd op = (OpCodeTxd)context.CurrOp;