emit_glasm_context_get_set.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <string_view>
  5. #include "shader_recompiler/backend/glasm/emit_context.h"
  6. #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
  7. #include "shader_recompiler/frontend/ir/value.h"
  8. #include "shader_recompiler/profile.h"
  9. namespace Shader::Backend::GLASM {
  10. namespace {
  11. void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset,
  12. std::string_view size) {
  13. if (!binding.IsImmediate()) {
  14. throw NotImplementedException("Indirect constant buffer loading");
  15. }
  16. const Register ret{ctx.reg_alloc.Define(inst)};
  17. ctx.Add("LDC.{} {},c{}[{}];", size, ret, binding.U32(), offset);
  18. }
  19. std::string VertexIndex(EmitContext& ctx, ScalarU32 vertex) {
  20. if (ctx.stage == Stage::Geometry) {
  21. return fmt::format("[{}]", vertex);
  22. } else {
  23. return "";
  24. }
  25. }
  26. } // Anonymous namespace
  27. void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) {
  28. GetCbuf(ctx, inst, binding, offset, "U8");
  29. }
  30. void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) {
  31. GetCbuf(ctx, inst, binding, offset, "S8");
  32. }
  33. void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) {
  34. GetCbuf(ctx, inst, binding, offset, "U16");
  35. }
  36. void EmitGetCbufS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) {
  37. GetCbuf(ctx, inst, binding, offset, "S16");
  38. }
  39. void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) {
  40. GetCbuf(ctx, inst, binding, offset, "U32");
  41. }
  42. void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset) {
  43. GetCbuf(ctx, inst, binding, offset, "F32");
  44. }
  45. void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
  46. ScalarU32 offset) {
  47. GetCbuf(ctx, inst, binding, offset, "U32X2");
  48. }
  49. void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex) {
  50. const u32 element{static_cast<u32>(attr) % 4};
  51. const char swizzle{"xyzw"[element]};
  52. if (IR::IsGeneric(attr)) {
  53. const u32 index{IR::GenericAttributeIndex(attr)};
  54. ctx.Add("MOV.F {}.x,in_attr{}{}[0].{};", inst, index, VertexIndex(ctx, vertex), swizzle);
  55. return;
  56. }
  57. switch (attr) {
  58. case IR::Attribute::PositionX:
  59. case IR::Attribute::PositionY:
  60. case IR::Attribute::PositionZ:
  61. case IR::Attribute::PositionW:
  62. if (ctx.stage == Stage::Geometry) {
  63. ctx.Add("MOV.F {}.x,vertex_position{}.{};", inst, VertexIndex(ctx, vertex), swizzle);
  64. } else {
  65. ctx.Add("MOV.F {}.x,{}.position.{};", inst, ctx.attrib_name, swizzle);
  66. }
  67. break;
  68. case IR::Attribute::PointSpriteS:
  69. case IR::Attribute::PointSpriteT:
  70. ctx.Add("MOV.F {}.x,{}.pointcoord.{};", inst, ctx.attrib_name, swizzle);
  71. break;
  72. case IR::Attribute::InstanceId:
  73. ctx.Add("MOV.S {}.x,{}.instance;", inst, ctx.attrib_name);
  74. break;
  75. case IR::Attribute::VertexId:
  76. ctx.Add("MOV.S {}.x,{}.id;", inst, ctx.attrib_name);
  77. break;
  78. case IR::Attribute::FrontFace:
  79. ctx.Add("CMP.S {}.x,{}.facing.x,0,-1;", inst, ctx.attrib_name);
  80. break;
  81. default:
  82. throw NotImplementedException("Get attribute {}", attr);
  83. }
  84. }
  85. void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value,
  86. [[maybe_unused]] ScalarU32 vertex) {
  87. const u32 element{static_cast<u32>(attr) % 4};
  88. const char swizzle{"xyzw"[element]};
  89. if (IR::IsGeneric(attr)) {
  90. const u32 index{IR::GenericAttributeIndex(attr)};
  91. ctx.Add("MOV.F out_attr{}[0].{},{};", index, swizzle, value);
  92. return;
  93. }
  94. switch (attr) {
  95. case IR::Attribute::PointSize:
  96. ctx.Add("MOV.F result.pointsize.x,{};", value);
  97. break;
  98. case IR::Attribute::PositionX:
  99. case IR::Attribute::PositionY:
  100. case IR::Attribute::PositionZ:
  101. case IR::Attribute::PositionW:
  102. ctx.Add("MOV.F result.position.{},{};", swizzle, value);
  103. break;
  104. case IR::Attribute::ViewportIndex:
  105. if (ctx.stage == Stage::Geometry || ctx.profile.support_viewport_index_layer_non_geometry) {
  106. ctx.Add("MOV.F result.viewport.x,{};", value);
  107. } else {
  108. // LOG_WARNING
  109. }
  110. break;
  111. default:
  112. throw NotImplementedException("Set attribute {}", attr);
  113. }
  114. }
  115. void EmitGetAttributeIndexed([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset,
  116. [[maybe_unused]] ScalarU32 vertex) {
  117. throw NotImplementedException("GLASM instruction");
  118. }
  119. void EmitSetAttributeIndexed([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset,
  120. [[maybe_unused]] ScalarF32 value, [[maybe_unused]] ScalarU32 vertex) {
  121. throw NotImplementedException("GLASM instruction");
  122. }
  123. void EmitGetPatch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Patch patch) {
  124. throw NotImplementedException("GLASM instruction");
  125. }
  126. void EmitSetPatch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Patch patch,
  127. [[maybe_unused]] ScalarF32 value) {
  128. throw NotImplementedException("GLASM instruction");
  129. }
  130. void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, ScalarF32 value) {
  131. ctx.Add("MOV.F frag_color{}.{},{};", index, "xyzw"[component], value);
  132. }
  133. void EmitSetSampleMask(EmitContext& ctx, ScalarS32 value) {
  134. ctx.Add("MOV.S result.samplemask.x,{};", value);
  135. }
  136. void EmitSetFragDepth(EmitContext& ctx, ScalarF32 value) {
  137. ctx.Add("MOV.F result.depth.z,{};", value);
  138. }
  139. void EmitLoadLocal(EmitContext& ctx, IR::Inst& inst, ScalarU32 word_offset) {
  140. ctx.Add("MOV.U {},lmem[{}].x;", inst, word_offset);
  141. }
  142. void EmitWriteLocal(EmitContext& ctx, ScalarU32 word_offset, ScalarU32 value) {
  143. ctx.Add("MOV.U lmem[{}].x,{};", word_offset, value);
  144. }
  145. } // namespace Shader::Backend::GLASM