aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/Instructions
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2019-12-06 19:37:00 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commitcb171f6ebfa7e1aa5721503d1c1115719957932d (patch)
tree20de7fca78819fe436fbde629544aa547f446cc8 /Ryujinx.Graphics.Shader/Instructions
parente25b7c9848b6ec486eb513297b5c536857665c7f (diff)
Support shared color mask, implement more shader instructions
Support shared color masks (used by Nouveau and maybe the NVIDIA driver). Support draw buffers (also required by OpenGL). Support viewport transform disable (disabled for now as it breaks some games). Fix instanced rendering draw being ignored for multi draw. Fix IADD and IADD3 immediate shader encodings, that was not matching some ops. Implement FFMA32I shader instruction. Implement IMAD shader instruction.
Diffstat (limited to 'Ryujinx.Graphics.Shader/Instructions')
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs44
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs20
2 files changed, 64 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs
index 1d3a1101..2a8f00cc 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs
@@ -200,6 +200,50 @@ namespace Ryujinx.Graphics.Shader.Instructions
// TODO: CC, X, corner cases
}
+ public static void Imad(EmitterContext context)
+ {
+ OpCodeAlu op = (OpCodeAlu)context.CurrOp;
+
+ bool signedA = context.CurrOp.RawOpCode.Extract(48);
+ bool signedB = context.CurrOp.RawOpCode.Extract(53);
+ bool high = context.CurrOp.RawOpCode.Extract(54);
+
+ Operand srcA = GetSrcA(context);
+ Operand srcB = GetSrcB(context);
+ Operand srcC = GetSrcC(context);
+
+ Operand res;
+
+ if (high)
+ {
+ if (signedA && signedB)
+ {
+ res = context.MultiplyHighS32(srcA, srcB);
+ }
+ else
+ {
+ res = context.MultiplyHighU32(srcA, srcB);
+
+ if (signedA)
+ {
+ res = context.IAdd(res, context.IMultiply(srcB, context.ShiftRightS32(srcA, Const(31))));
+ }
+ else if (signedB)
+ {
+ res = context.IAdd(res, context.IMultiply(srcA, context.ShiftRightS32(srcB, Const(31))));
+ }
+ }
+ }
+ else
+ {
+ res = context.IMultiply(srcA, srcB);
+ }
+
+ res = context.IAdd(res, srcC);
+
+ context.Copy(GetDest(context), res);
+ }
+
public static void Imnmx(EmitterContext context)
{
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
index 3b8d7305..63d1efcb 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
@@ -59,6 +59,26 @@ namespace Ryujinx.Graphics.Shader.Instructions
SetFPZnFlags(context, dest, op.SetCondCode);
}
+ public static void Ffma32i(EmitterContext context)
+ {
+ IOpCodeFArith op = (IOpCodeFArith)context.CurrOp;
+
+ bool saturate = op.RawOpCode.Extract(55);
+ bool negateA = op.RawOpCode.Extract(56);
+ bool negateC = op.RawOpCode.Extract(57);
+
+ Operand srcA = context.FPNegate(GetSrcA(context), negateA);
+ Operand srcC = context.FPNegate(GetDest(context), negateC);
+
+ Operand srcB = GetSrcB(context);
+
+ Operand dest = GetDest(context);
+
+ context.Copy(dest, context.FPSaturate(context.FPFusedMultiplyAdd(srcA, srcB, srcC), saturate));
+
+ SetFPZnFlags(context, dest, op.SetCondCode);
+ }
+
public static void Fmnmx(EmitterContext context)
{
IOpCodeFArith op = (IOpCodeFArith)context.CurrOp;