emit_glasm_composite.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
  4. #include "shader_recompiler/backend/glasm/glasm_emit_context.h"
  5. #include "shader_recompiler/frontend/ir/value.h"
  6. namespace Shader::Backend::GLASM {
  7. namespace {
  8. template <auto read_imm, char type, typename... Values>
  9. void CompositeConstruct(EmitContext& ctx, IR::Inst& inst, Values&&... elements) {
  10. const Register ret{ctx.reg_alloc.Define(inst)};
  11. if (std::ranges::any_of(std::array{elements...},
  12. [](const IR::Value& value) { return value.IsImmediate(); })) {
  13. using Type = std::invoke_result_t<decltype(read_imm), IR::Value>;
  14. const std::array<Type, 4> values{(elements.IsImmediate() ? (elements.*read_imm)() : 0)...};
  15. ctx.Add("MOV.{} {},{{{},{},{},{}}};", type, ret, fmt::to_string(values[0]),
  16. fmt::to_string(values[1]), fmt::to_string(values[2]), fmt::to_string(values[3]));
  17. }
  18. size_t index{};
  19. for (const IR::Value& element : {elements...}) {
  20. if (!element.IsImmediate()) {
  21. const ScalarU32 value{ctx.reg_alloc.Consume(element)};
  22. ctx.Add("MOV.{} {}.{},{};", type, ret, "xyzw"[index], value);
  23. }
  24. ++index;
  25. }
  26. }
  27. void CompositeExtract(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index, char type) {
  28. const Register ret{ctx.reg_alloc.Define(inst)};
  29. if (ret == composite && index == 0) {
  30. // No need to do anything here, the source and destination are the same register
  31. return;
  32. }
  33. ctx.Add("MOV.{} {}.x,{}.{};", type, ret, composite, "xyzw"[index]);
  34. }
  35. template <typename ObjectType>
  36. void CompositeInsert(EmitContext& ctx, IR::Inst& inst, Register composite, ObjectType object,
  37. u32 index, char type) {
  38. const Register ret{ctx.reg_alloc.Define(inst)};
  39. const char swizzle{"xyzw"[index]};
  40. if (ret != composite && ret == object) {
  41. // The object is aliased with the return value, so we have to use a temporary to insert
  42. ctx.Add("MOV.{} RC,{};"
  43. "MOV.{} RC.{},{};"
  44. "MOV.{} {},RC;",
  45. type, composite, type, swizzle, object, type, ret);
  46. } else if (ret != composite) {
  47. // The input composite is not aliased with the return value so we have to copy it before
  48. // hand. But the insert object is not aliased with the return value, so we don't have to
  49. // worry about that
  50. ctx.Add("MOV.{} {},{};"
  51. "MOV.{} {}.{},{};",
  52. type, ret, composite, type, ret, swizzle, object);
  53. } else {
  54. // The return value is aliased so we can just insert the object, it doesn't matter if it's
  55. // aliased
  56. ctx.Add("MOV.{} {}.{},{};", type, ret, swizzle, object);
  57. }
  58. }
  59. } // Anonymous namespace
  60. void EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1,
  61. const IR::Value& e2) {
  62. CompositeConstruct<&IR::Value::U32, 'U'>(ctx, inst, e1, e2);
  63. }
  64. void EmitCompositeConstructU32x3(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1,
  65. const IR::Value& e2, const IR::Value& e3) {
  66. CompositeConstruct<&IR::Value::U32, 'U'>(ctx, inst, e1, e2, e3);
  67. }
  68. void EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1,
  69. const IR::Value& e2, const IR::Value& e3, const IR::Value& e4) {
  70. CompositeConstruct<&IR::Value::U32, 'U'>(ctx, inst, e1, e2, e3, e4);
  71. }
  72. void EmitCompositeExtractU32x2(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) {
  73. CompositeExtract(ctx, inst, composite, index, 'U');
  74. }
  75. void EmitCompositeExtractU32x3(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) {
  76. CompositeExtract(ctx, inst, composite, index, 'U');
  77. }
  78. void EmitCompositeExtractU32x4(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) {
  79. CompositeExtract(ctx, inst, composite, index, 'U');
  80. }
  81. void EmitCompositeInsertU32x2([[maybe_unused]] EmitContext& ctx,
  82. [[maybe_unused]] Register composite,
  83. [[maybe_unused]] ScalarU32 object, [[maybe_unused]] u32 index) {
  84. throw NotImplementedException("GLASM instruction");
  85. }
  86. void EmitCompositeInsertU32x3([[maybe_unused]] EmitContext& ctx,
  87. [[maybe_unused]] Register composite,
  88. [[maybe_unused]] ScalarU32 object, [[maybe_unused]] u32 index) {
  89. throw NotImplementedException("GLASM instruction");
  90. }
  91. void EmitCompositeInsertU32x4([[maybe_unused]] EmitContext& ctx,
  92. [[maybe_unused]] Register composite,
  93. [[maybe_unused]] ScalarU32 object, [[maybe_unused]] u32 index) {
  94. throw NotImplementedException("GLASM instruction");
  95. }
  96. void EmitCompositeConstructF16x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register e1,
  97. [[maybe_unused]] Register e2) {
  98. throw NotImplementedException("GLASM instruction");
  99. }
  100. void EmitCompositeConstructF16x3([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register e1,
  101. [[maybe_unused]] Register e2, [[maybe_unused]] Register e3) {
  102. throw NotImplementedException("GLASM instruction");
  103. }
  104. void EmitCompositeConstructF16x4([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register e1,
  105. [[maybe_unused]] Register e2, [[maybe_unused]] Register e3,
  106. [[maybe_unused]] Register e4) {
  107. throw NotImplementedException("GLASM instruction");
  108. }
  109. void EmitCompositeExtractF16x2([[maybe_unused]] EmitContext& ctx,
  110. [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) {
  111. throw NotImplementedException("GLASM instruction");
  112. }
  113. void EmitCompositeExtractF16x3([[maybe_unused]] EmitContext& ctx,
  114. [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) {
  115. throw NotImplementedException("GLASM instruction");
  116. }
  117. void EmitCompositeExtractF16x4([[maybe_unused]] EmitContext& ctx,
  118. [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) {
  119. throw NotImplementedException("GLASM instruction");
  120. }
  121. void EmitCompositeInsertF16x2([[maybe_unused]] EmitContext& ctx,
  122. [[maybe_unused]] Register composite, [[maybe_unused]] Register object,
  123. [[maybe_unused]] u32 index) {
  124. throw NotImplementedException("GLASM instruction");
  125. }
  126. void EmitCompositeInsertF16x3([[maybe_unused]] EmitContext& ctx,
  127. [[maybe_unused]] Register composite, [[maybe_unused]] Register object,
  128. [[maybe_unused]] u32 index) {
  129. throw NotImplementedException("GLASM instruction");
  130. }
  131. void EmitCompositeInsertF16x4([[maybe_unused]] EmitContext& ctx,
  132. [[maybe_unused]] Register composite, [[maybe_unused]] Register object,
  133. [[maybe_unused]] u32 index) {
  134. throw NotImplementedException("GLASM instruction");
  135. }
  136. void EmitCompositeConstructF32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1,
  137. const IR::Value& e2) {
  138. CompositeConstruct<&IR::Value::F32, 'F'>(ctx, inst, e1, e2);
  139. }
  140. void EmitCompositeConstructF32x3(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1,
  141. const IR::Value& e2, const IR::Value& e3) {
  142. CompositeConstruct<&IR::Value::F32, 'F'>(ctx, inst, e1, e2, e3);
  143. }
  144. void EmitCompositeConstructF32x4(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1,
  145. const IR::Value& e2, const IR::Value& e3, const IR::Value& e4) {
  146. CompositeConstruct<&IR::Value::F32, 'F'>(ctx, inst, e1, e2, e3, e4);
  147. }
  148. void EmitCompositeExtractF32x2(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) {
  149. CompositeExtract(ctx, inst, composite, index, 'F');
  150. }
  151. void EmitCompositeExtractF32x3(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) {
  152. CompositeExtract(ctx, inst, composite, index, 'F');
  153. }
  154. void EmitCompositeExtractF32x4(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) {
  155. CompositeExtract(ctx, inst, composite, index, 'F');
  156. }
  157. void EmitCompositeInsertF32x2(EmitContext& ctx, IR::Inst& inst, Register composite,
  158. ScalarF32 object, u32 index) {
  159. CompositeInsert(ctx, inst, composite, object, index, 'F');
  160. }
  161. void EmitCompositeInsertF32x3(EmitContext& ctx, IR::Inst& inst, Register composite,
  162. ScalarF32 object, u32 index) {
  163. CompositeInsert(ctx, inst, composite, object, index, 'F');
  164. }
  165. void EmitCompositeInsertF32x4(EmitContext& ctx, IR::Inst& inst, Register composite,
  166. ScalarF32 object, u32 index) {
  167. CompositeInsert(ctx, inst, composite, object, index, 'F');
  168. }
  169. void EmitCompositeConstructF64x2([[maybe_unused]] EmitContext& ctx) {
  170. throw NotImplementedException("GLASM instruction");
  171. }
  172. void EmitCompositeConstructF64x3([[maybe_unused]] EmitContext& ctx) {
  173. throw NotImplementedException("GLASM instruction");
  174. }
  175. void EmitCompositeConstructF64x4([[maybe_unused]] EmitContext& ctx) {
  176. throw NotImplementedException("GLASM instruction");
  177. }
  178. void EmitCompositeExtractF64x2([[maybe_unused]] EmitContext& ctx) {
  179. throw NotImplementedException("GLASM instruction");
  180. }
  181. void EmitCompositeExtractF64x3([[maybe_unused]] EmitContext& ctx) {
  182. throw NotImplementedException("GLASM instruction");
  183. }
  184. void EmitCompositeExtractF64x4([[maybe_unused]] EmitContext& ctx) {
  185. throw NotImplementedException("GLASM instruction");
  186. }
  187. void EmitCompositeInsertF64x2([[maybe_unused]] EmitContext& ctx,
  188. [[maybe_unused]] Register composite, [[maybe_unused]] Register object,
  189. [[maybe_unused]] u32 index) {
  190. throw NotImplementedException("GLASM instruction");
  191. }
  192. void EmitCompositeInsertF64x3([[maybe_unused]] EmitContext& ctx,
  193. [[maybe_unused]] Register composite, [[maybe_unused]] Register object,
  194. [[maybe_unused]] u32 index) {
  195. throw NotImplementedException("GLASM instruction");
  196. }
  197. void EmitCompositeInsertF64x4([[maybe_unused]] EmitContext& ctx,
  198. [[maybe_unused]] Register composite, [[maybe_unused]] Register object,
  199. [[maybe_unused]] u32 index) {
  200. throw NotImplementedException("GLASM instruction");
  201. }
  202. } // namespace Shader::Backend::GLASM