emit_glasm_warp.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "shader_recompiler/backend/glasm/emit_context.h"
  5. #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
  6. #include "shader_recompiler/frontend/ir/value.h"
  7. namespace Shader::Backend::GLASM {
  8. void EmitLaneId(EmitContext& ctx, IR::Inst& inst) {
  9. ctx.Add("MOV.S {}.x,{}.threadid;", inst, ctx.stage_name);
  10. }
  11. void EmitVoteAll(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) {
  12. ctx.Add("TGALL.S {}.x,{};", inst, pred);
  13. }
  14. void EmitVoteAny(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) {
  15. ctx.Add("TGANY.S {}.x,{};", inst, pred);
  16. }
  17. void EmitVoteEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) {
  18. ctx.Add("TGEQ.S {}.x,{};", inst, pred);
  19. }
  20. void EmitSubgroupBallot(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) {
  21. ctx.Add("TGBALLOT {}.x,{};", inst, pred);
  22. }
  23. void EmitSubgroupEqMask(EmitContext& ctx, IR::Inst& inst) {
  24. ctx.Add("MOV.U {},{}.threadeqmask;", inst, ctx.stage_name);
  25. }
  26. void EmitSubgroupLtMask(EmitContext& ctx, IR::Inst& inst) {
  27. ctx.Add("MOV.U {},{}.threadltmask;", inst, ctx.stage_name);
  28. }
  29. void EmitSubgroupLeMask(EmitContext& ctx, IR::Inst& inst) {
  30. ctx.Add("MOV.U {},{}.threadlemask;", inst, ctx.stage_name);
  31. }
  32. void EmitSubgroupGtMask(EmitContext& ctx, IR::Inst& inst) {
  33. ctx.Add("MOV.U {},{}.threadgtmask;", inst, ctx.stage_name);
  34. }
  35. void EmitSubgroupGeMask(EmitContext& ctx, IR::Inst& inst) {
  36. ctx.Add("MOV.U {},{}.threadgemask;", inst, ctx.stage_name);
  37. }
  38. static void Shuffle(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index,
  39. const IR::Value& clamp, const IR::Value& segmentation_mask,
  40. std::string_view op) {
  41. std::string mask;
  42. if (clamp.IsImmediate() && segmentation_mask.IsImmediate()) {
  43. mask = fmt::to_string(clamp.U32() | (segmentation_mask.U32() << 8));
  44. } else {
  45. mask = "RC";
  46. ctx.Add("BFI.U RC.x,{{5,8,0,0}},{},{};",
  47. ScalarU32{ctx.reg_alloc.Consume(segmentation_mask)},
  48. ScalarU32{ctx.reg_alloc.Consume(clamp)});
  49. }
  50. const Register value_ret{ctx.reg_alloc.Define(inst)};
  51. IR::Inst* const in_bounds{inst.GetAssociatedPseudoOperation(IR::Opcode::GetInBoundsFromOp)};
  52. if (in_bounds) {
  53. const Register bounds_ret{ctx.reg_alloc.Define(*in_bounds)};
  54. ctx.Add("SHF{}.U {},{},{},{};"
  55. "MOV.U {}.x,{}.y;",
  56. op, bounds_ret, value, index, mask, value_ret, bounds_ret);
  57. in_bounds->Invalidate();
  58. } else {
  59. ctx.Add("SHF{}.U {},{},{},{};"
  60. "MOV.U {}.x,{}.y;",
  61. op, value_ret, value, index, mask, value_ret, value_ret);
  62. }
  63. }
  64. void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index,
  65. const IR::Value& clamp, const IR::Value& segmentation_mask) {
  66. Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "IDX");
  67. }
  68. void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index,
  69. const IR::Value& clamp, const IR::Value& segmentation_mask) {
  70. Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "UP");
  71. }
  72. void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index,
  73. const IR::Value& clamp, const IR::Value& segmentation_mask) {
  74. Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "DOWN");
  75. }
  76. void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index,
  77. const IR::Value& clamp, const IR::Value& segmentation_mask) {
  78. Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "XOR");
  79. }
  80. void EmitFSwizzleAdd(EmitContext& ctx, IR::Inst& inst, ScalarF32 op_a, ScalarF32 op_b,
  81. ScalarU32 swizzle) {
  82. const auto ret{ctx.reg_alloc.Define(inst)};
  83. ctx.Add("AND.U RC.z,{}.threadid,3;"
  84. "SHL.U RC.z,RC.z,1;"
  85. "SHR.U RC.z,{},RC.z;"
  86. "AND.U RC.z,RC.z,3;"
  87. "MUL.F RC.x,{},FSWZA[RC.z];"
  88. "MUL.F RC.y,{},FSWZB[RC.z];"
  89. "ADD.F {}.x,RC.x,RC.y;",
  90. ctx.stage_name, swizzle, op_a, op_b, ret);
  91. }
  92. void EmitDPdxFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) {
  93. ctx.Add("DDX.FINE {}.x,{};", inst, p);
  94. }
  95. void EmitDPdyFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) {
  96. ctx.Add("DDY.FINE {}.x,{};", inst, p);
  97. }
  98. void EmitDPdxCoarse(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) {
  99. ctx.Add("DDX.COARSE {}.x,{};", inst, p);
  100. }
  101. void EmitDPdyCoarse(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) {
  102. ctx.Add("DDY.COARSE {}.x,{};", inst, p);
  103. }
  104. } // namespace Shader::Backend::GLASM