aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdk <gab.dark.100@gmail.com>2019-11-25 16:02:52 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commitb8528c6317423d91aefe12d927466df0c09cc172 (patch)
tree15e4f33d48b49504fb79ccf8b442f2f2fa5bb1b5
parent65428f5842311e2cacb49d2b9e24a3b803fe1f82 (diff)
Implement HSET2 shader instruction and fix errors uncovered by Rodrigo tests
-rw-r--r--Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs3
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs8
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs32
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs55
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs8
-rw-r--r--Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs5
6 files changed, 81 insertions, 30 deletions
diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs
index d84a5820..599c674f 100644
--- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs
@@ -89,6 +89,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
Set("0111100x0xxxxx", InstEmit.Hmul2, typeof(OpCodeAluImm2x10));
Set("0010101xxxxxxx", InstEmit.Hmul2, typeof(OpCodeAluImm32));
Set("0101110100001x", InstEmit.Hmul2, typeof(OpCodeAluReg));
+ Set("0111110x1xxxxx", InstEmit.Hset2, typeof(OpCodeSetCbuf));
+ Set("0111110x0xxxxx", InstEmit.Hset2, typeof(OpCodeHsetImm2x10));
+ Set("0101110100011x", InstEmit.Hset2, typeof(OpCodeSetReg));
Set("0111111x1xxxxx", InstEmit.Hsetp2, typeof(OpCodeSetCbuf));
Set("0111111x0xxxxx", InstEmit.Hsetp2, typeof(OpCodeHsetImm2x10));
Set("0101110100100x", InstEmit.Hsetp2, typeof(OpCodeSetReg));
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs
index 5c4f5398..e283c3b7 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs
@@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
{
static class InstEmitAluHelper
{
- public static int GetIntMin(IntegerType type)
+ public static long GetIntMin(IntegerType type)
{
switch (type)
{
@@ -18,14 +18,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
case IntegerType.S8: return sbyte.MinValue;
case IntegerType.U16: return ushort.MinValue;
case IntegerType.S16: return short.MinValue;
- case IntegerType.U32: return (int)uint.MinValue;
+ case IntegerType.U32: return uint.MinValue;
case IntegerType.S32: return int.MinValue;
}
throw new ArgumentException($"The type \"{type}\" is not a supported int type.");
}
- public static int GetIntMax(IntegerType type)
+ public static long GetIntMax(IntegerType type)
{
switch (type)
{
@@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
case IntegerType.S8: return sbyte.MaxValue;
case IntegerType.U16: return ushort.MaxValue;
case IntegerType.S16: return short.MaxValue;
- case IntegerType.U32: return unchecked((int)uint.MaxValue);
+ case IntegerType.U32: return uint.MaxValue;
case IntegerType.S32: return int.MaxValue;
}
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs
index 5aa925d9..b1524152 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs
@@ -14,18 +14,16 @@ namespace Ryujinx.Graphics.Shader.Instructions
{
OpCodeFArith op = (OpCodeFArith)context.CurrOp;
- FPType srcType = (FPType)op.RawOpCode.Extract(8, 2);
- FPType dstType = (FPType)op.RawOpCode.Extract(10, 2);
+ FPType dstType = (FPType)op.RawOpCode.Extract(8, 2);
+ FPType srcType = (FPType)op.RawOpCode.Extract(10, 2);
- bool pass = op.RawOpCode.Extract(40);
+ bool round = op.RawOpCode.Extract(42);
bool negateB = op.RawOpCode.Extract(45);
bool absoluteB = op.RawOpCode.Extract(49);
- pass &= op.RoundingMode == RoundingMode.TowardsNegativeInfinity;
-
Operand srcB = context.FPAbsNeg(GetSrcB(context, srcType), absoluteB, negateB);
- if (!pass)
+ if (round)
{
switch (op.RoundingMode)
{
@@ -84,6 +82,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
switch (op.RoundingMode)
{
+ case RoundingMode.ToNearest:
+ srcB = context.FPRound(srcB);
+ break;
+
case RoundingMode.TowardsNegativeInfinity:
srcB = context.FPFloor(srcB);
break;
@@ -97,18 +99,12 @@ namespace Ryujinx.Graphics.Shader.Instructions
break;
}
- srcB = context.FPConvertToS32(srcB);
+ long min = GetIntMin(intType);
+ long max = GetIntMax(intType);
- // TODO: S/U64, conversion overflow handling.
- if (intType != IntegerType.S32)
- {
- int min = GetIntMin(intType);
- int max = GetIntMax(intType);
+ srcB = context.FPClamp(srcB, ConstF(min), ConstF(max));
- srcB = isSignedInt
- ? context.IClampS32(srcB, Const(min), Const(max))
- : context.IClampU32(srcB, Const(min), Const(max));
- }
+ srcB = context.FPConvertToS32(srcB);
Operand dest = GetDest(context);
@@ -194,8 +190,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
dstType |= IntegerType.S8;
}
- int min = GetIntMin(dstType);
- int max = GetIntMax(dstType);
+ int min = (int)GetIntMin(dstType);
+ int max = (int)GetIntMax(dstType);
srcB = dstIsSignedInt
? context.IClampS32(srcB, Const(min), Const(max))
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
index 79d92c2d..3b8d7305 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
@@ -232,7 +232,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
bool saturate = op.RawOpCode.Extract(op is IOpCodeReg ? 32 : 52);
- Operand[] srcA = GetHalfSrcA(context);
+ Operand[] srcA = GetHalfSrcA(context, isAdd);
Operand[] srcB = GetHalfSrcB(context);
Operand[] res = new Operand[2];
@@ -254,13 +254,17 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.Copy(GetDest(context), GetHalfPacked(context, res));
}
- public static void Hsetp2(EmitterContext context)
+ public static void Hset2(EmitterContext context)
{
OpCodeSet op = (OpCodeSet)context.CurrOp;
- bool hAnd = op.RawOpCode.Extract(53);
+ bool isRegVariant = op is IOpCodeReg;
- Condition cmpOp = op is IOpCodeReg
+ bool boolFloat = isRegVariant
+ ? op.RawOpCode.Extract(49)
+ : op.RawOpCode.Extract(53);
+
+ Condition cmpOp = isRegVariant
? (Condition)op.RawOpCode.Extract(35, 4)
: (Condition)op.RawOpCode.Extract(49, 4);
@@ -269,8 +273,49 @@ namespace Ryujinx.Graphics.Shader.Instructions
Operand[] res = new Operand[2];
+ res[0] = GetFPComparison(context, cmpOp, srcA[0], srcB[0]);
+ res[1] = GetFPComparison(context, cmpOp, srcA[1], srcB[1]);
+
Operand pred = GetPredicate39(context);
+ res[0] = GetPredLogicalOp(context, op.LogicalOp, res[0], pred);
+ res[1] = GetPredLogicalOp(context, op.LogicalOp, res[1], pred);
+
+ if (boolFloat)
+ {
+ res[0] = context.ConditionalSelect(res[0], ConstF(1), Const(0));
+ res[1] = context.ConditionalSelect(res[1], ConstF(1), Const(0));
+
+ context.Copy(GetDest(context), context.PackHalf2x16(res[0], res[1]));
+ }
+ else
+ {
+ Operand low = context.BitwiseAnd(res[0], Const(0xffff));
+ Operand high = context.ShiftLeft (res[1], Const(16));
+
+ Operand packed = context.BitwiseOr(low, high);
+
+ context.Copy(GetDest(context), packed);
+ }
+ }
+
+ public static void Hsetp2(EmitterContext context)
+ {
+ OpCodeSet op = (OpCodeSet)context.CurrOp;
+
+ bool isRegVariant = op is IOpCodeReg;
+
+ bool hAnd = isRegVariant
+ ? op.RawOpCode.Extract(49)
+ : op.RawOpCode.Extract(53);
+
+ Condition cmpOp = isRegVariant
+ ? (Condition)op.RawOpCode.Extract(35, 4)
+ : (Condition)op.RawOpCode.Extract(49, 4);
+
+ Operand[] srcA = GetHalfSrcA(context);
+ Operand[] srcB = GetHalfSrcB(context);
+
Operand p0Res = GetFPComparison(context, cmpOp, srcA[0], srcB[0]);
Operand p1Res = GetFPComparison(context, cmpOp, srcA[1], srcB[1]);
@@ -280,6 +325,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
p1Res = context.BitwiseNot(p0Res);
}
+ Operand pred = GetPredicate39(context);
+
p0Res = GetPredLogicalOp(context, op.LogicalOp, p0Res, pred);
p1Res = GetPredLogicalOp(context, op.LogicalOp, p1Res, pred);
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs
index 4b85e96f..22e2a140 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs
@@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
// TODO: Warn about invalid floating point type.
- return Const(0);
+ return ConstF(0);
}
public static Operand GetSrcB(EmitterContext context)
@@ -98,13 +98,13 @@ namespace Ryujinx.Graphics.Shader.Instructions
throw new InvalidOperationException($"Unexpected opcode type \"{context.CurrOp.GetType().Name}\".");
}
- public static Operand[] GetHalfSrcA(EmitterContext context)
+ public static Operand[] GetHalfSrcA(EmitterContext context, bool isAdd = false)
{
OpCode op = context.CurrOp;
bool absoluteA = false, negateA = false;
- if (op is IOpCodeCbuf || op is IOpCodeImm)
+ if (isAdd || op is IOpCodeCbuf || op is IOpCodeImm)
{
negateA = op.RawOpCode.Extract(43);
absoluteA = op.RawOpCode.Extract(44);
@@ -113,7 +113,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
{
absoluteA = op.RawOpCode.Extract(44);
}
- else if (op is OpCodeAluImm32 && op.Emitter == InstEmit.Hadd2)
+ else if (op is OpCodeAluImm32 && isAdd)
{
negateA = op.RawOpCode.Extract(56);
}
diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs
index e94d4d2d..c55e3430 100644
--- a/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs
+++ b/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs
@@ -206,6 +206,11 @@ namespace Ryujinx.Graphics.Shader.Translation
return context.Add(Instruction.FP | Instruction.Ceiling, Local(), a);
}
+ public static Operand FPClamp(this EmitterContext context, Operand a, Operand b, Operand c)
+ {
+ return context.Add(Instruction.FP | Instruction.Clamp, Local(), a, b, c);
+ }
+
public static Operand FPCompareEqual(this EmitterContext context, Operand a, Operand b)
{
return context.Add(Instruction.FP | Instruction.CompareEqual, Local(), a, b);