/ src / Ryujinx.Graphics.Shader / StructuredIr / InstructionInfo.cs
InstructionInfo.cs
  1  using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  2  using Ryujinx.Graphics.Shader.Translation;
  3  using System;
  4  
  5  namespace Ryujinx.Graphics.Shader.StructuredIr
  6  {
  7      static class InstructionInfo
  8      {
  9          private readonly struct InstInfo
 10          {
 11              public AggregateType DestType { get; }
 12  
 13              public AggregateType[] SrcTypes { get; }
 14  
 15              public InstInfo(AggregateType destType, params AggregateType[] srcTypes)
 16              {
 17                  DestType = destType;
 18                  SrcTypes = srcTypes;
 19              }
 20          }
 21  
 22          private static readonly InstInfo[] _infoTbl;
 23  
 24          static InstructionInfo()
 25          {
 26              _infoTbl = new InstInfo[(int)Instruction.Count];
 27  
 28  #pragma warning disable IDE0055 // Disable formatting
 29              //  Inst                                  Destination type      Source 1 type          Source 2 type          Source 3 type          Source 4 type
 30              Add(Instruction.AtomicAdd,                AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
 31              Add(Instruction.AtomicAnd,                AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
 32              Add(Instruction.AtomicCompareAndSwap,     AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32,     AggregateType.U32);
 33              Add(Instruction.AtomicMaxS32,             AggregateType.S32,    AggregateType.S32,     AggregateType.S32,     AggregateType.S32);
 34              Add(Instruction.AtomicMaxU32,             AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
 35              Add(Instruction.AtomicMinS32,             AggregateType.S32,    AggregateType.S32,     AggregateType.S32,     AggregateType.S32);
 36              Add(Instruction.AtomicMinU32,             AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
 37              Add(Instruction.AtomicOr,                 AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
 38              Add(Instruction.AtomicSwap,               AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
 39              Add(Instruction.AtomicXor,                AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
 40              Add(Instruction.Absolute,                 AggregateType.Scalar, AggregateType.Scalar);
 41              Add(Instruction.Add,                      AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
 42              Add(Instruction.Ballot,                   AggregateType.U32,    AggregateType.Bool);
 43              Add(Instruction.BitCount,                 AggregateType.S32,    AggregateType.S32);
 44              Add(Instruction.BitfieldExtractS32,       AggregateType.S32,    AggregateType.S32,     AggregateType.S32,     AggregateType.S32);
 45              Add(Instruction.BitfieldExtractU32,       AggregateType.U32,    AggregateType.U32,     AggregateType.S32,     AggregateType.S32);
 46              Add(Instruction.BitfieldInsert,           AggregateType.S32,    AggregateType.S32,     AggregateType.S32,     AggregateType.S32,     AggregateType.S32);
 47              Add(Instruction.BitfieldReverse,          AggregateType.S32,    AggregateType.S32);
 48              Add(Instruction.BitwiseAnd,               AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
 49              Add(Instruction.BitwiseExclusiveOr,       AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
 50              Add(Instruction.BitwiseNot,               AggregateType.S32,    AggregateType.S32);
 51              Add(Instruction.BitwiseOr,                AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
 52              Add(Instruction.BranchIfTrue,             AggregateType.Void,   AggregateType.Bool);
 53              Add(Instruction.BranchIfFalse,            AggregateType.Void,   AggregateType.Bool);
 54              Add(Instruction.Call,                     AggregateType.Scalar);
 55              Add(Instruction.Ceiling,                  AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
 56              Add(Instruction.Clamp,                    AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar,  AggregateType.Scalar);
 57              Add(Instruction.ClampU32,                 AggregateType.U32,    AggregateType.U32,     AggregateType.U32,     AggregateType.U32);
 58              Add(Instruction.CompareEqual,             AggregateType.Bool,   AggregateType.Scalar,  AggregateType.Scalar);
 59              Add(Instruction.CompareGreater,           AggregateType.Bool,   AggregateType.Scalar,  AggregateType.Scalar);
 60              Add(Instruction.CompareGreaterOrEqual,    AggregateType.Bool,   AggregateType.Scalar,  AggregateType.Scalar);
 61              Add(Instruction.CompareGreaterOrEqualU32, AggregateType.Bool,   AggregateType.U32,     AggregateType.U32);
 62              Add(Instruction.CompareGreaterU32,        AggregateType.Bool,   AggregateType.U32,     AggregateType.U32);
 63              Add(Instruction.CompareLess,              AggregateType.Bool,   AggregateType.Scalar,  AggregateType.Scalar);
 64              Add(Instruction.CompareLessOrEqual,       AggregateType.Bool,   AggregateType.Scalar,  AggregateType.Scalar);
 65              Add(Instruction.CompareLessOrEqualU32,    AggregateType.Bool,   AggregateType.U32,     AggregateType.U32);
 66              Add(Instruction.CompareLessU32,           AggregateType.Bool,   AggregateType.U32,     AggregateType.U32);
 67              Add(Instruction.CompareNotEqual,          AggregateType.Bool,   AggregateType.Scalar,  AggregateType.Scalar);
 68              Add(Instruction.ConditionalSelect,        AggregateType.Scalar, AggregateType.Bool,    AggregateType.Scalar,  AggregateType.Scalar);
 69              Add(Instruction.ConvertFP32ToFP64,        AggregateType.FP64,   AggregateType.FP32);
 70              Add(Instruction.ConvertFP64ToFP32,        AggregateType.FP32,   AggregateType.FP64);
 71              Add(Instruction.ConvertFP32ToS32,         AggregateType.S32,    AggregateType.FP32);
 72              Add(Instruction.ConvertFP32ToU32,         AggregateType.U32,    AggregateType.FP32);
 73              Add(Instruction.ConvertFP64ToS32,         AggregateType.S32,    AggregateType.FP64);
 74              Add(Instruction.ConvertFP64ToU32,         AggregateType.U32,    AggregateType.FP64);
 75              Add(Instruction.ConvertS32ToFP32,         AggregateType.FP32,   AggregateType.S32);
 76              Add(Instruction.ConvertS32ToFP64,         AggregateType.FP64,   AggregateType.S32);
 77              Add(Instruction.ConvertU32ToFP32,         AggregateType.FP32,   AggregateType.U32);
 78              Add(Instruction.ConvertU32ToFP64,         AggregateType.FP64,   AggregateType.U32);
 79              Add(Instruction.Cosine,                   AggregateType.Scalar, AggregateType.Scalar);
 80              Add(Instruction.Ddx,                      AggregateType.FP32,   AggregateType.FP32);
 81              Add(Instruction.Ddy,                      AggregateType.FP32,   AggregateType.FP32);
 82              Add(Instruction.Divide,                   AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
 83              Add(Instruction.ExponentB2,               AggregateType.Scalar, AggregateType.Scalar);
 84              Add(Instruction.FindLSB,                  AggregateType.S32,    AggregateType.S32);
 85              Add(Instruction.FindMSBS32,               AggregateType.S32,    AggregateType.S32);
 86              Add(Instruction.FindMSBU32,               AggregateType.S32,    AggregateType.U32);
 87              Add(Instruction.Floor,                    AggregateType.Scalar, AggregateType.Scalar);
 88              Add(Instruction.FusedMultiplyAdd,         AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar,  AggregateType.Scalar);
 89              Add(Instruction.ImageLoad,                AggregateType.FP32);
 90              Add(Instruction.ImageStore,               AggregateType.Void);
 91              Add(Instruction.ImageAtomic,              AggregateType.S32);
 92              Add(Instruction.IsNan,                    AggregateType.Bool,   AggregateType.Scalar);
 93              Add(Instruction.Load,                     AggregateType.FP32);
 94              Add(Instruction.Lod,                      AggregateType.FP32);
 95              Add(Instruction.LogarithmB2,              AggregateType.Scalar, AggregateType.Scalar);
 96              Add(Instruction.LogicalAnd,               AggregateType.Bool,   AggregateType.Bool,    AggregateType.Bool);
 97              Add(Instruction.LogicalExclusiveOr,       AggregateType.Bool,   AggregateType.Bool,    AggregateType.Bool);
 98              Add(Instruction.LogicalNot,               AggregateType.Bool,   AggregateType.Bool);
 99              Add(Instruction.LogicalOr,                AggregateType.Bool,   AggregateType.Bool,    AggregateType.Bool);
100              Add(Instruction.Maximum,                  AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
101              Add(Instruction.MaximumU32,               AggregateType.U32,    AggregateType.U32,     AggregateType.U32);
102              Add(Instruction.Minimum,                  AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
103              Add(Instruction.MinimumU32,               AggregateType.U32,    AggregateType.U32,     AggregateType.U32);
104              Add(Instruction.Modulo,                   AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
105              Add(Instruction.Multiply,                 AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
106              Add(Instruction.MultiplyHighS32,          AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
107              Add(Instruction.MultiplyHighU32,          AggregateType.U32,    AggregateType.U32,     AggregateType.U32);
108              Add(Instruction.Negate,                   AggregateType.Scalar, AggregateType.Scalar);
109              Add(Instruction.PackDouble2x32,           AggregateType.FP64,   AggregateType.U32,     AggregateType.U32);
110              Add(Instruction.PackHalf2x16,             AggregateType.U32,    AggregateType.FP32,    AggregateType.FP32);
111              Add(Instruction.ReciprocalSquareRoot,     AggregateType.Scalar, AggregateType.Scalar);
112              Add(Instruction.Return,                   AggregateType.Void,   AggregateType.U32);
113              Add(Instruction.Round,                    AggregateType.Scalar, AggregateType.Scalar);
114              Add(Instruction.ShiftLeft,                AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
115              Add(Instruction.ShiftRightS32,            AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
116              Add(Instruction.ShiftRightU32,            AggregateType.U32,    AggregateType.U32,     AggregateType.S32);
117              Add(Instruction.Shuffle,                  AggregateType.FP32,   AggregateType.FP32,    AggregateType.U32);
118              Add(Instruction.ShuffleDown,              AggregateType.FP32,   AggregateType.FP32,    AggregateType.U32);
119              Add(Instruction.ShuffleUp,                AggregateType.FP32,   AggregateType.FP32,    AggregateType.U32);
120              Add(Instruction.ShuffleXor,               AggregateType.FP32,   AggregateType.FP32,    AggregateType.U32);
121              Add(Instruction.Sine,                     AggregateType.Scalar, AggregateType.Scalar);
122              Add(Instruction.SquareRoot,               AggregateType.Scalar, AggregateType.Scalar);
123              Add(Instruction.Store,                    AggregateType.Void);
124              Add(Instruction.Subtract,                 AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
125              Add(Instruction.SwizzleAdd,               AggregateType.FP32,   AggregateType.FP32,    AggregateType.FP32,    AggregateType.S32);
126              Add(Instruction.TextureSample,            AggregateType.FP32);
127              Add(Instruction.TextureQuerySamples,      AggregateType.S32,    AggregateType.S32);
128              Add(Instruction.TextureQuerySize,         AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
129              Add(Instruction.Truncate,                 AggregateType.Scalar, AggregateType.Scalar);
130              Add(Instruction.UnpackDouble2x32,         AggregateType.U32,    AggregateType.FP64);
131              Add(Instruction.UnpackHalf2x16,           AggregateType.FP32,   AggregateType.U32);
132              Add(Instruction.VectorExtract,            AggregateType.Scalar, AggregateType.Vector4, AggregateType.S32);
133              Add(Instruction.VoteAll,                  AggregateType.Bool,   AggregateType.Bool);
134              Add(Instruction.VoteAllEqual,             AggregateType.Bool,   AggregateType.Bool);
135              Add(Instruction.VoteAny,                  AggregateType.Bool,   AggregateType.Bool);
136  #pragma warning restore IDE0055
137          }
138  
139          private static void Add(Instruction inst, AggregateType destType, params AggregateType[] srcTypes)
140          {
141              _infoTbl[(int)inst] = new InstInfo(destType, srcTypes);
142          }
143  
144          public static AggregateType GetDestVarType(Instruction inst)
145          {
146              return GetFinalVarType(_infoTbl[(int)(inst & Instruction.Mask)].DestType, inst);
147          }
148  
149          public static AggregateType GetSrcVarType(Instruction inst, int index)
150          {
151              // TODO: Return correct type depending on source index,
152              // that can improve the decompiler output.
153              if (inst == Instruction.ImageLoad ||
154                  inst == Instruction.ImageStore ||
155                  inst == Instruction.ImageAtomic ||
156                  inst == Instruction.Lod ||
157                  inst == Instruction.TextureSample)
158              {
159                  return AggregateType.FP32;
160              }
161              else if (inst == Instruction.Call || inst == Instruction.Load || inst == Instruction.Store || inst.IsAtomic())
162              {
163                  return AggregateType.S32;
164              }
165  
166              return GetFinalVarType(_infoTbl[(int)(inst & Instruction.Mask)].SrcTypes[index], inst);
167          }
168  
169          private static AggregateType GetFinalVarType(AggregateType type, Instruction inst)
170          {
171              if (type == AggregateType.Scalar)
172              {
173                  if ((inst & Instruction.FP32) != 0)
174                  {
175                      return AggregateType.FP32;
176                  }
177                  else if ((inst & Instruction.FP64) != 0)
178                  {
179                      return AggregateType.FP64;
180                  }
181                  else
182                  {
183                      return AggregateType.S32;
184                  }
185              }
186              else if (type == AggregateType.Void)
187              {
188                  throw new ArgumentException($"Invalid operand for instruction \"{inst}\".");
189              }
190  
191              return type;
192          }
193  
194          public static bool IsUnary(Instruction inst)
195          {
196              if (inst == Instruction.Copy)
197              {
198                  return true;
199              }
200              else if (inst == Instruction.TextureSample)
201              {
202                  return false;
203              }
204  
205              return _infoTbl[(int)(inst & Instruction.Mask)].SrcTypes.Length == 1;
206          }
207      }
208  }