| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- using System;
- using static Ryujinx.Graphics.Gal.Shader.ShaderDecodeHelper;
- namespace Ryujinx.Graphics.Gal.Shader
- {
- static partial class ShaderDecode
- {
- private enum IntType
- {
- U8 = 0,
- U16 = 1,
- U32 = 2,
- U64 = 3,
- S8 = 4,
- S16 = 5,
- S32 = 6,
- S64 = 7
- }
- private enum FloatType
- {
- F16 = 1,
- F32 = 2,
- F64 = 3
- }
- public static void F2f_C(ShaderIrBlock block, long opCode, int position)
- {
- EmitF2F(block, opCode, ShaderOper.Cr);
- }
- public static void F2f_I(ShaderIrBlock block, long opCode, int position)
- {
- EmitF2F(block, opCode, ShaderOper.Immf);
- }
- public static void F2f_R(ShaderIrBlock block, long opCode, int position)
- {
- EmitF2F(block, opCode, ShaderOper.Rr);
- }
- public static void F2i_C(ShaderIrBlock block, long opCode, int position)
- {
- EmitF2I(block, opCode, ShaderOper.Cr);
- }
- public static void F2i_I(ShaderIrBlock block, long opCode, int position)
- {
- EmitF2I(block, opCode, ShaderOper.Immf);
- }
- public static void F2i_R(ShaderIrBlock block, long opCode, int position)
- {
- EmitF2I(block, opCode, ShaderOper.Rr);
- }
- public static void I2f_C(ShaderIrBlock block, long opCode, int position)
- {
- EmitI2F(block, opCode, ShaderOper.Cr);
- }
- public static void I2f_I(ShaderIrBlock block, long opCode, int position)
- {
- EmitI2F(block, opCode, ShaderOper.Imm);
- }
- public static void I2f_R(ShaderIrBlock block, long opCode, int position)
- {
- EmitI2F(block, opCode, ShaderOper.Rr);
- }
- public static void I2i_C(ShaderIrBlock block, long opCode, int position)
- {
- EmitI2I(block, opCode, ShaderOper.Cr);
- }
- public static void I2i_I(ShaderIrBlock block, long opCode, int position)
- {
- EmitI2I(block, opCode, ShaderOper.Imm);
- }
- public static void I2i_R(ShaderIrBlock block, long opCode, int position)
- {
- EmitI2I(block, opCode, ShaderOper.Rr);
- }
- public static void Isberd(ShaderIrBlock block, long opCode, int position)
- {
- //This instruction seems to be used to translate from an address to a vertex index in a GS
- //Stub it as such
- block.AddNode(new ShaderIrCmnt("Stubbed."));
- block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), opCode.Gpr8())));
- }
- public static void Mov_C(ShaderIrBlock block, long opCode, int position)
- {
- ShaderIrOperCbuf cbuf = opCode.Cbuf34();
- block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), cbuf)));
- }
- public static void Mov_I(ShaderIrBlock block, long opCode, int position)
- {
- ShaderIrOperImm imm = opCode.Imm19_20();
- block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), imm)));
- }
- public static void Mov_I32(ShaderIrBlock block, long opCode, int position)
- {
- ShaderIrOperImm imm = opCode.Imm32_20();
- block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), imm)));
- }
- public static void Mov_R(ShaderIrBlock block, long opCode, int position)
- {
- ShaderIrOperGpr gpr = opCode.Gpr20();
- block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), gpr)));
- }
- public static void Sel_C(ShaderIrBlock block, long opCode, int position)
- {
- EmitSel(block, opCode, ShaderOper.Cr);
- }
- public static void Sel_I(ShaderIrBlock block, long opCode, int position)
- {
- EmitSel(block, opCode, ShaderOper.Imm);
- }
- public static void Sel_R(ShaderIrBlock block, long opCode, int position)
- {
- EmitSel(block, opCode, ShaderOper.Rr);
- }
- public static void Mov_S(ShaderIrBlock block, long opCode, int position)
- {
- block.AddNode(new ShaderIrCmnt("Stubbed."));
- //Zero is used as a special number to get a valid "0 * 0 + VertexIndex" in a GS
- ShaderIrNode source = new ShaderIrOperImm(0);
- block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), source)));
- }
- private static void EmitF2F(ShaderIrBlock block, long opCode, ShaderOper oper)
- {
- bool negA = opCode.Read(45);
- bool absA = opCode.Read(49);
- ShaderIrNode operA;
- switch (oper)
- {
- case ShaderOper.Cr: operA = opCode.Cbuf34(); break;
- case ShaderOper.Immf: operA = opCode.Immf19_20(); break;
- case ShaderOper.Rr: operA = opCode.Gpr20(); break;
- default: throw new ArgumentException(nameof(oper));
- }
- operA = GetAluFabsFneg(operA, absA, negA);
- ShaderIrInst roundInst = GetRoundInst(opCode);
- if (roundInst != ShaderIrInst.Invalid)
- {
- operA = new ShaderIrOp(roundInst, operA);
- }
- block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), operA)));
- }
- private static void EmitF2I(ShaderIrBlock block, long opCode, ShaderOper oper)
- {
- IntType type = GetIntType(opCode);
- if (type == IntType.U64 ||
- type == IntType.S64)
- {
- //TODO: 64-bits support.
- //Note: GLSL doesn't support 64-bits integers.
- throw new NotImplementedException();
- }
- bool negA = opCode.Read(45);
- bool absA = opCode.Read(49);
- ShaderIrNode operA;
- switch (oper)
- {
- case ShaderOper.Cr: operA = opCode.Cbuf34(); break;
- case ShaderOper.Immf: operA = opCode.Immf19_20(); break;
- case ShaderOper.Rr: operA = opCode.Gpr20(); break;
- default: throw new ArgumentException(nameof(oper));
- }
- operA = GetAluFabsFneg(operA, absA, negA);
- ShaderIrInst roundInst = GetRoundInst(opCode);
- if (roundInst != ShaderIrInst.Invalid)
- {
- operA = new ShaderIrOp(roundInst, operA);
- }
- bool signed = type >= IntType.S8;
- int size = 8 << ((int)type & 3);
- if (size < 32)
- {
- uint mask = uint.MaxValue >> (32 - size);
- float cMin = 0;
- float cMax = mask;
- if (signed)
- {
- uint halfMask = mask >> 1;
- cMin -= halfMask + 1;
- cMax = halfMask;
- }
- ShaderIrOperImmf min = new ShaderIrOperImmf(cMin);
- ShaderIrOperImmf max = new ShaderIrOperImmf(cMax);
- operA = new ShaderIrOp(ShaderIrInst.Fclamp, operA, min, max);
- }
- ShaderIrInst inst = signed
- ? ShaderIrInst.Ftos
- : ShaderIrInst.Ftou;
- ShaderIrNode op = new ShaderIrOp(inst, operA);
- block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op)));
- }
- private static void EmitI2F(ShaderIrBlock block, long opCode, ShaderOper oper)
- {
- IntType type = GetIntType(opCode);
- if (type == IntType.U64 ||
- type == IntType.S64)
- {
- //TODO: 64-bits support.
- //Note: GLSL doesn't support 64-bits integers.
- throw new NotImplementedException();
- }
- int sel = opCode.Read(41, 3);
- bool negA = opCode.Read(45);
- bool absA = opCode.Read(49);
- ShaderIrNode operA;
- switch (oper)
- {
- case ShaderOper.Cr: operA = opCode.Cbuf34(); break;
- case ShaderOper.Imm: operA = opCode.Imm19_20(); break;
- case ShaderOper.Rr: operA = opCode.Gpr20(); break;
- default: throw new ArgumentException(nameof(oper));
- }
- operA = GetAluIabsIneg(operA, absA, negA);
- bool signed = type >= IntType.S8;
- int shift = sel * 8;
- int size = 8 << ((int)type & 3);
- if (shift != 0)
- {
- operA = new ShaderIrOp(ShaderIrInst.Asr, operA, new ShaderIrOperImm(shift));
- }
- if (size < 32)
- {
- operA = ExtendTo32(operA, signed, size);
- }
- ShaderIrInst inst = signed
- ? ShaderIrInst.Stof
- : ShaderIrInst.Utof;
- ShaderIrNode op = new ShaderIrOp(inst, operA);
- block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op)));
- }
- private static void EmitI2I(ShaderIrBlock block, long opCode, ShaderOper oper)
- {
- IntType type = GetIntType(opCode);
- if (type == IntType.U64 ||
- type == IntType.S64)
- {
- //TODO: 64-bits support.
- //Note: GLSL doesn't support 64-bits integers.
- throw new NotImplementedException();
- }
- int sel = opCode.Read(41, 3);
- bool negA = opCode.Read(45);
- bool absA = opCode.Read(49);
- bool satA = opCode.Read(50);
- ShaderIrNode operA;
- switch (oper)
- {
- case ShaderOper.Cr: operA = opCode.Cbuf34(); break;
- case ShaderOper.Immf: operA = opCode.Immf19_20(); break;
- case ShaderOper.Rr: operA = opCode.Gpr20(); break;
- default: throw new ArgumentException(nameof(oper));
- }
- operA = GetAluIabsIneg(operA, absA, negA);
- bool signed = type >= IntType.S8;
- int shift = sel * 8;
- int size = 8 << ((int)type & 3);
- if (shift != 0)
- {
- operA = new ShaderIrOp(ShaderIrInst.Asr, operA, new ShaderIrOperImm(shift));
- }
- if (size < 32)
- {
- uint mask = uint.MaxValue >> (32 - size);
- if (satA)
- {
- uint cMin = 0;
- uint cMax = mask;
- if (signed)
- {
- uint halfMask = mask >> 1;
- cMin -= halfMask + 1;
- cMax = halfMask;
- }
- ShaderIrOperImm min = new ShaderIrOperImm((int)cMin);
- ShaderIrOperImm max = new ShaderIrOperImm((int)cMax);
- operA = new ShaderIrOp(signed
- ? ShaderIrInst.Clamps
- : ShaderIrInst.Clampu, operA, min, max);
- }
- else
- {
- operA = ExtendTo32(operA, signed, size);
- }
- }
- block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), operA)));
- }
- private static void EmitSel(ShaderIrBlock block, long opCode, ShaderOper oper)
- {
- ShaderIrOperGpr dst = opCode.Gpr0();
- ShaderIrNode pred = opCode.Pred39N();
- ShaderIrNode resultA = opCode.Gpr8();
- ShaderIrNode resultB;
- switch (oper)
- {
- case ShaderOper.Cr: resultB = opCode.Cbuf34(); break;
- case ShaderOper.Imm: resultB = opCode.Imm19_20(); break;
- case ShaderOper.Rr: resultB = opCode.Gpr20(); break;
- default: throw new ArgumentException(nameof(oper));
- }
- block.AddNode(opCode.PredNode(new ShaderIrCond(pred, new ShaderIrAsg(dst, resultA), false)));
- block.AddNode(opCode.PredNode(new ShaderIrCond(pred, new ShaderIrAsg(dst, resultB), true)));
- }
- private static IntType GetIntType(long opCode)
- {
- bool signed = opCode.Read(13);
- IntType type = (IntType)(opCode.Read(10, 3));
- if (signed)
- {
- type += (int)IntType.S8;
- }
- return type;
- }
- private static FloatType GetFloatType(long opCode)
- {
- return (FloatType)(opCode.Read(8, 3));
- }
- private static ShaderIrInst GetRoundInst(long opCode)
- {
- switch (opCode.Read(39, 3))
- {
- case 1: return ShaderIrInst.Floor;
- case 2: return ShaderIrInst.Ceil;
- case 3: return ShaderIrInst.Trunc;
- }
- return ShaderIrInst.Invalid;
- }
- }
- }
|