InstGen.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  2. using Ryujinx.Graphics.Shader.StructuredIr;
  3. using System;
  4. using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
  5. using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenMemory;
  6. using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenPacking;
  7. using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
  8. namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
  9. {
  10. static class InstGen
  11. {
  12. public static string GetExpression(CodeGenContext context, IAstNode node)
  13. {
  14. if (node is AstOperation operation)
  15. {
  16. return GetExpression(context, operation);
  17. }
  18. else if (node is AstOperand operand)
  19. {
  20. return context.OperandManager.GetExpression(operand, context.Config);
  21. }
  22. throw new ArgumentException($"Invalid node type \"{node?.GetType().Name ?? "null"}\".");
  23. }
  24. private static string GetExpression(CodeGenContext context, AstOperation operation)
  25. {
  26. Instruction inst = operation.Inst;
  27. InstInfo info = GetInstructionInfo(inst);
  28. if ((info.Type & InstType.Call) != 0)
  29. {
  30. bool atomic = (info.Type & InstType.Atomic) != 0;
  31. int arity = (int)(info.Type & InstType.ArityMask);
  32. string args = string.Empty;
  33. for (int argIndex = 0; argIndex < arity; argIndex++)
  34. {
  35. if (argIndex != 0)
  36. {
  37. args += ", ";
  38. }
  39. VariableType dstType = GetSrcVarType(inst, argIndex);
  40. if (argIndex == 0 && atomic)
  41. {
  42. Instruction memRegion = inst & Instruction.MrMask;
  43. switch (memRegion)
  44. {
  45. case Instruction.MrShared: args += LoadShared (context, operation); break;
  46. case Instruction.MrStorage: args += LoadStorage(context, operation); break;
  47. default: throw new InvalidOperationException($"Invalid memory region \"{memRegion}\".");
  48. }
  49. // We use the first 2 operands above.
  50. argIndex++;
  51. }
  52. else
  53. {
  54. args += GetSoureExpr(context, operation.GetSource(argIndex), dstType);
  55. }
  56. }
  57. if (inst == Instruction.Ballot)
  58. {
  59. return $"unpackUint2x32({info.OpName}({args})).x";
  60. }
  61. else
  62. {
  63. return info.OpName + "(" + args + ")";
  64. }
  65. }
  66. else if ((info.Type & InstType.Op) != 0)
  67. {
  68. string op = info.OpName;
  69. int arity = (int)(info.Type & InstType.ArityMask);
  70. string[] expr = new string[arity];
  71. for (int index = 0; index < arity; index++)
  72. {
  73. IAstNode src = operation.GetSource(index);
  74. string srcExpr = GetSoureExpr(context, src, GetSrcVarType(inst, index));
  75. bool isLhs = arity == 2 && index == 0;
  76. expr[index] = Enclose(srcExpr, src, inst, info, isLhs);
  77. }
  78. switch (arity)
  79. {
  80. case 0:
  81. return op;
  82. case 1:
  83. return op + expr[0];
  84. case 2:
  85. return $"{expr[0]} {op} {expr[1]}";
  86. case 3:
  87. return $"{expr[0]} {op[0]} {expr[1]} {op[1]} {expr[2]}";
  88. }
  89. }
  90. else if ((info.Type & InstType.Special) != 0)
  91. {
  92. switch (inst)
  93. {
  94. case Instruction.ImageLoad:
  95. return ImageLoadOrStore(context, operation);
  96. case Instruction.ImageStore:
  97. return ImageLoadOrStore(context, operation);
  98. case Instruction.LoadAttribute:
  99. return LoadAttribute(context, operation);
  100. case Instruction.LoadConstant:
  101. return LoadConstant(context, operation);
  102. case Instruction.LoadLocal:
  103. return LoadLocal(context, operation);
  104. case Instruction.LoadShared:
  105. return LoadShared(context, operation);
  106. case Instruction.LoadStorage:
  107. return LoadStorage(context, operation);
  108. case Instruction.Lod:
  109. return Lod(context, operation);
  110. case Instruction.PackDouble2x32:
  111. return PackDouble2x32(context, operation);
  112. case Instruction.PackHalf2x16:
  113. return PackHalf2x16(context, operation);
  114. case Instruction.StoreLocal:
  115. return StoreLocal(context, operation);
  116. case Instruction.StoreShared:
  117. return StoreShared(context, operation);
  118. case Instruction.StoreStorage:
  119. return StoreStorage(context, operation);
  120. case Instruction.TextureSample:
  121. return TextureSample(context, operation);
  122. case Instruction.TextureSize:
  123. return TextureSize(context, operation);
  124. case Instruction.UnpackDouble2x32:
  125. return UnpackDouble2x32(context, operation);
  126. case Instruction.UnpackHalf2x16:
  127. return UnpackHalf2x16(context, operation);
  128. }
  129. }
  130. throw new InvalidOperationException($"Unexpected instruction type \"{info.Type}\".");
  131. }
  132. }
  133. }