From 7603dbe3c8b45c8563f320f17ce784151cb1f0a8 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 17 Oct 2021 17:48:36 -0300 Subject: [PATCH] Add missing U8/S8 types from shader I2I instruction (#2740) * Add missing U8/S8 types from shader I2I instruction * Better names * Fix dstIsSignedInt --- .../Decoders/InstDecoders.cs | 22 ++++++++---- .../Instructions/InstEmitAluHelper.cs | 28 +++++++++++++++ .../Instructions/InstEmitConversion.cs | 35 +++++++++---------- 3 files changed, 61 insertions(+), 24 deletions(-) diff --git a/Ryujinx.Graphics.Shader/Decoders/InstDecoders.cs b/Ryujinx.Graphics.Shader/Decoders/InstDecoders.cs index 5e7c40f4b..ca4ff12ad 100644 --- a/Ryujinx.Graphics.Shader/Decoders/InstDecoders.cs +++ b/Ryujinx.Graphics.Shader/Decoders/InstDecoders.cs @@ -277,6 +277,16 @@ namespace Ryujinx.Graphics.Shader.Decoders S64 = 7, } + enum ISrcDstFmt + { + U8 = 0, + U16 = 1, + U32 = 2, + S8 = 4, + S16 = 5, + S32 = 6, + } + enum RoundMode2 { Round = 0, @@ -2720,8 +2730,8 @@ namespace Ryujinx.Graphics.Shader.Decoders public bool AbsB => (_opcode & 0x2000000000000) != 0; public bool NegB => (_opcode & 0x200000000000) != 0; public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); - public IDstFmt IDstFmt => (IDstFmt)((int)((_opcode >> 10) & 0x4) | (int)((_opcode >> 8) & 0x3)); - public ISrcFmt SrcFmt => (ISrcFmt)((int)((_opcode >> 11) & 0x4) | (int)((_opcode >> 10) & 0x3)); + public ISrcDstFmt IDstFmt => (ISrcDstFmt)((int)((_opcode >> 10) & 0x4) | (int)((_opcode >> 8) & 0x3)); + public ISrcDstFmt ISrcFmt => (ISrcDstFmt)((int)((_opcode >> 11) & 0x4) | (int)((_opcode >> 10) & 0x3)); } struct InstI2iI @@ -2737,8 +2747,8 @@ namespace Ryujinx.Graphics.Shader.Decoders public bool AbsB => (_opcode & 0x2000000000000) != 0; public bool NegB => (_opcode & 0x200000000000) != 0; public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); - public IDstFmt IDstFmt => (IDstFmt)((int)((_opcode >> 10) & 0x4) | (int)((_opcode >> 8) & 0x3)); - public ISrcFmt SrcFmt => (ISrcFmt)((int)((_opcode >> 11) & 0x4) | (int)((_opcode >> 10) & 0x3)); + public ISrcDstFmt IDstFmt => (ISrcDstFmt)((int)((_opcode >> 10) & 0x4) | (int)((_opcode >> 8) & 0x3)); + public ISrcDstFmt ISrcFmt => (ISrcDstFmt)((int)((_opcode >> 11) & 0x4) | (int)((_opcode >> 10) & 0x3)); } struct InstI2iC @@ -2755,8 +2765,8 @@ namespace Ryujinx.Graphics.Shader.Decoders public bool AbsB => (_opcode & 0x2000000000000) != 0; public bool NegB => (_opcode & 0x200000000000) != 0; public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); - public IDstFmt IDstFmt => (IDstFmt)((int)((_opcode >> 10) & 0x4) | (int)((_opcode >> 8) & 0x3)); - public ISrcFmt SrcFmt => (ISrcFmt)((int)((_opcode >> 11) & 0x4) | (int)((_opcode >> 10) & 0x3)); + public ISrcDstFmt IDstFmt => (ISrcDstFmt)((int)((_opcode >> 10) & 0x4) | (int)((_opcode >> 8) & 0x3)); + public ISrcDstFmt ISrcFmt => (ISrcDstFmt)((int)((_opcode >> 11) & 0x4) | (int)((_opcode >> 10) & 0x3)); } struct InstIaddR diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs index 3dda53162..3fbd0aeb2 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs @@ -34,6 +34,34 @@ namespace Ryujinx.Graphics.Shader.Instructions }; } + public static long GetIntMin(ISrcDstFmt type) + { + return type switch + { + ISrcDstFmt.U8 => byte.MinValue, + ISrcDstFmt.S8 => sbyte.MinValue, + ISrcDstFmt.U16 => ushort.MinValue, + ISrcDstFmt.S16 => short.MinValue, + ISrcDstFmt.U32 => uint.MinValue, + ISrcDstFmt.S32 => int.MinValue, + _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.") + }; + } + + public static long GetIntMax(ISrcDstFmt type) + { + return type switch + { + ISrcDstFmt.U8 => byte.MaxValue, + ISrcDstFmt.S8 => sbyte.MaxValue, + ISrcDstFmt.U16 => ushort.MaxValue, + ISrcDstFmt.S16 => short.MaxValue, + ISrcDstFmt.U32 => uint.MaxValue, + ISrcDstFmt.S32 => int.MaxValue, + _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.") + }; + } + public static Operand GetPredLogicalOp(EmitterContext context, BoolOp logicOp, Operand input, Operand pred) { return logicOp switch diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs index 43b07cc2b..01cdc4454 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs @@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Shader.Instructions var src = GetSrcReg(context, op.SrcB); - EmitI2I(context, op.SrcFmt, op.IDstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB, op.Sat); + EmitI2I(context, op.ISrcFmt, op.IDstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB, op.Sat); } public static void I2iI(EmitterContext context) @@ -107,7 +107,7 @@ namespace Ryujinx.Graphics.Shader.Instructions var src = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - EmitI2I(context, op.SrcFmt, op.IDstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB, op.Sat); + EmitI2I(context, op.ISrcFmt, op.IDstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB, op.Sat); } public static void I2iC(EmitterContext context) @@ -116,7 +116,7 @@ namespace Ryujinx.Graphics.Shader.Instructions var src = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - EmitI2I(context, op.SrcFmt, op.IDstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB, op.Sat); + EmitI2I(context, op.ISrcFmt, op.IDstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB, op.Sat); } private static void EmitF2F( @@ -261,8 +261,8 @@ namespace Ryujinx.Graphics.Shader.Instructions private static void EmitI2I( EmitterContext context, - ISrcFmt srcType, - IDstFmt dstType, + ISrcDstFmt srcType, + ISrcDstFmt dstType, Operand src, ByteSel byteSelection, int rd, @@ -270,30 +270,29 @@ namespace Ryujinx.Graphics.Shader.Instructions bool negate, bool saturate) { - if (srcType == ISrcFmt.U64 || dstType == IDstFmt.U64) + if ((srcType & ~ISrcDstFmt.S8) > ISrcDstFmt.U32 || (dstType & ~ISrcDstFmt.S8) > ISrcDstFmt.U32) { context.Config.GpuAccessor.Log("Invalid I2I encoding."); return; } bool srcIsSignedInt = - srcType == ISrcFmt.S8 || - srcType == ISrcFmt.S16 || - srcType == ISrcFmt.S32 || - srcType == ISrcFmt.S64; + srcType == ISrcDstFmt.S8 || + srcType == ISrcDstFmt.S16 || + srcType == ISrcDstFmt.S32; bool dstIsSignedInt = - dstType == IDstFmt.S16 || - dstType == IDstFmt.S32 || - dstType == IDstFmt.S64; + dstType == ISrcDstFmt.S8 || + dstType == ISrcDstFmt.S16 || + dstType == ISrcDstFmt.S32; bool srcIsSmallInt = - srcType == ISrcFmt.U16 || - srcType == ISrcFmt.S16 || - srcType == ISrcFmt.U8 || - srcType == ISrcFmt.S8; + srcType == ISrcDstFmt.U16 || + srcType == ISrcDstFmt.S16 || + srcType == ISrcDstFmt.U8 || + srcType == ISrcDstFmt.S8; if (srcIsSmallInt) { - int size = srcType == ISrcFmt.U16 || srcType == ISrcFmt.S16 ? 16 : 8; + int size = srcType == ISrcDstFmt.U16 || srcType == ISrcDstFmt.S16 ? 16 : 8; src = srcIsSignedInt ? context.BitfieldExtractS32(src, Const((int)byteSelection * 8), Const(size))