ShaderDecodeMem.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. using System;
  2. using static Ryujinx.Graphics.Gal.Shader.ShaderDecodeHelper;
  3. namespace Ryujinx.Graphics.Gal.Shader
  4. {
  5. static partial class ShaderDecode
  6. {
  7. private const int TempRegStart = 0x100;
  8. public static void Ld_A(ShaderIrBlock Block, long OpCode)
  9. {
  10. ShaderIrNode[] Opers = GetOperAbuf20(OpCode);
  11. int Index = 0;
  12. foreach (ShaderIrNode OperA in Opers)
  13. {
  14. ShaderIrOperGpr OperD = GetOperGpr0(OpCode);
  15. OperD.Index += Index++;
  16. Block.AddNode(GetPredNode(new ShaderIrAsg(OperD, OperA), OpCode));
  17. }
  18. }
  19. public static void Ld_C(ShaderIrBlock Block, long OpCode)
  20. {
  21. int Type = (int)(OpCode >> 48) & 7;
  22. if (Type > 5)
  23. {
  24. throw new InvalidOperationException();
  25. }
  26. int Count = Type == 5 ? 2 : 1;
  27. for (int Index = 0; Index < Count; Index++)
  28. {
  29. ShaderIrOperCbuf OperA = GetOperCbuf36(OpCode);
  30. ShaderIrOperGpr OperD = GetOperGpr0 (OpCode);
  31. OperA.Pos += Index;
  32. OperD.Index += Index;
  33. ShaderIrNode Node = OperA;
  34. if (Type < 4)
  35. {
  36. //This is a 8 or 16 bits type.
  37. bool Signed = (Type & 1) != 0;
  38. int Size = 8 << (Type >> 1);
  39. Node = ExtendTo32(Node, Signed, Size);
  40. }
  41. Block.AddNode(GetPredNode(new ShaderIrAsg(OperD, Node), OpCode));
  42. }
  43. }
  44. public static void St_A(ShaderIrBlock Block, long OpCode)
  45. {
  46. ShaderIrNode[] Opers = GetOperAbuf20(OpCode);
  47. int Index = 0;
  48. foreach (ShaderIrNode OperA in Opers)
  49. {
  50. ShaderIrOperGpr OperD = GetOperGpr0(OpCode);
  51. OperD.Index += Index++;
  52. Block.AddNode(GetPredNode(new ShaderIrAsg(OperA, OperD), OpCode));
  53. }
  54. }
  55. public static void Texq(ShaderIrBlock Block, long OpCode)
  56. {
  57. ShaderIrNode OperD = GetOperGpr0(OpCode);
  58. ShaderIrNode OperA = GetOperGpr8(OpCode);
  59. ShaderTexqInfo Info = (ShaderTexqInfo)((OpCode >> 22) & 0x1f);
  60. ShaderIrMetaTexq Meta0 = new ShaderIrMetaTexq(Info, 0);
  61. ShaderIrMetaTexq Meta1 = new ShaderIrMetaTexq(Info, 1);
  62. ShaderIrNode OperC = GetOperImm13_36(OpCode);
  63. ShaderIrOp Op0 = new ShaderIrOp(ShaderIrInst.Texq, OperA, null, OperC, Meta0);
  64. ShaderIrOp Op1 = new ShaderIrOp(ShaderIrInst.Texq, OperA, null, OperC, Meta1);
  65. Block.AddNode(GetPredNode(new ShaderIrAsg(OperD, Op0), OpCode));
  66. Block.AddNode(GetPredNode(new ShaderIrAsg(OperA, Op1), OpCode)); //Is this right?
  67. }
  68. public static void Tex(ShaderIrBlock Block, long OpCode)
  69. {
  70. //TODO: Support other formats.
  71. ShaderIrOperGpr[] Coords = new ShaderIrOperGpr[2];
  72. for (int Index = 0; Index < Coords.Length; Index++)
  73. {
  74. Coords[Index] = GetOperGpr8(OpCode);
  75. Coords[Index].Index += Index;
  76. if (Coords[Index].Index > ShaderIrOperGpr.ZRIndex)
  77. {
  78. Coords[Index].Index = ShaderIrOperGpr.ZRIndex;
  79. }
  80. }
  81. int ChMask = (int)(OpCode >> 31) & 0xf;
  82. ShaderIrNode OperC = GetOperImm13_36(OpCode);
  83. for (int Ch = 0; Ch < 4; Ch++)
  84. {
  85. ShaderIrOperGpr Dst = new ShaderIrOperGpr(TempRegStart + Ch);
  86. ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch);
  87. ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Texs, Coords[0], Coords[1], OperC, Meta);
  88. Block.AddNode(GetPredNode(new ShaderIrAsg(Dst, Op), OpCode));
  89. }
  90. int RegInc = 0;
  91. for (int Ch = 0; Ch < 4; Ch++)
  92. {
  93. if (!IsChannelUsed(ChMask, Ch))
  94. {
  95. continue;
  96. }
  97. ShaderIrOperGpr Src = new ShaderIrOperGpr(TempRegStart + Ch);
  98. ShaderIrOperGpr Dst = GetOperGpr0(OpCode);
  99. Dst.Index += RegInc++;
  100. if (Dst.Index >= ShaderIrOperGpr.ZRIndex)
  101. {
  102. continue;
  103. }
  104. Block.AddNode(GetPredNode(new ShaderIrAsg(Dst, Src), OpCode));
  105. }
  106. }
  107. public static void Texs(ShaderIrBlock Block, long OpCode)
  108. {
  109. EmitTex(Block, OpCode, ShaderIrInst.Texs);
  110. }
  111. public static void Tlds(ShaderIrBlock Block, long OpCode)
  112. {
  113. EmitTex(Block, OpCode, ShaderIrInst.Txlf);
  114. }
  115. private static void EmitTex(ShaderIrBlock Block, long OpCode, ShaderIrInst Inst)
  116. {
  117. //TODO: Support other formats.
  118. ShaderIrNode OperA = GetOperGpr8 (OpCode);
  119. ShaderIrNode OperB = GetOperGpr20 (OpCode);
  120. ShaderIrNode OperC = GetOperImm13_36(OpCode);
  121. bool TwoDests = GetOperGpr28(OpCode).Index != ShaderIrOperGpr.ZRIndex;
  122. int ChMask;
  123. switch ((OpCode >> 50) & 7)
  124. {
  125. case 0: ChMask = TwoDests ? 0x7 : 0x1; break;
  126. case 1: ChMask = TwoDests ? 0xb : 0x2; break;
  127. case 2: ChMask = TwoDests ? 0xd : 0x4; break;
  128. case 3: ChMask = TwoDests ? 0xe : 0x8; break;
  129. case 4: ChMask = TwoDests ? 0xf : 0x3; break;
  130. default: throw new InvalidOperationException();
  131. }
  132. for (int Ch = 0; Ch < 4; Ch++)
  133. {
  134. ShaderIrOperGpr Dst = new ShaderIrOperGpr(TempRegStart + Ch);
  135. ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch);
  136. ShaderIrOp Op = new ShaderIrOp(Inst, OperA, OperB, OperC, Meta);
  137. Block.AddNode(GetPredNode(new ShaderIrAsg(Dst, Op), OpCode));
  138. }
  139. int RegInc = 0;
  140. for (int Ch = 0; Ch < 4; Ch++)
  141. {
  142. if (!IsChannelUsed(ChMask, Ch))
  143. {
  144. continue;
  145. }
  146. ShaderIrOperGpr Src = new ShaderIrOperGpr(TempRegStart + Ch);
  147. ShaderIrOperGpr Dst = (RegInc >> 1) != 0
  148. ? GetOperGpr28(OpCode)
  149. : GetOperGpr0 (OpCode);
  150. Dst.Index += RegInc++ & 1;
  151. if (Dst.Index >= ShaderIrOperGpr.ZRIndex)
  152. {
  153. continue;
  154. }
  155. Block.AddNode(GetPredNode(new ShaderIrAsg(Dst, Src), OpCode));
  156. }
  157. }
  158. private static bool IsChannelUsed(int ChMask, int Ch)
  159. {
  160. return (ChMask & (1 << Ch)) != 0;
  161. }
  162. }
  163. }