emit_glsl_context_get_set.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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/glsl/emit_context.h"
  6. #include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
  7. #include "shader_recompiler/frontend/ir/value.h"
  8. namespace Shader::Backend::GLSL {
  9. namespace {
  10. static constexpr std::string_view SWIZZLE{"xyzw"};
  11. u32 CbufIndex(u32 offset) {
  12. return (offset / 4) % 4;
  13. }
  14. char OffsetSwizzle(u32 offset) {
  15. return SWIZZLE[CbufIndex(offset)];
  16. }
  17. } // namespace
  18. void EmitGetCbufU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  19. [[maybe_unused]] const IR::Value& binding,
  20. [[maybe_unused]] const IR::Value& offset) {
  21. if (offset.IsImmediate()) {
  22. ctx.AddU32("{}=bitfieldExtract(floatBitsToUint({}_cbuf{}[{}].{}),int({}),8);", inst,
  23. ctx.stage_name, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
  24. (offset.U32() % 4) * 8);
  25. } else {
  26. const auto offset_var{ctx.reg_alloc.Consume(offset)};
  27. ctx.AddU32(
  28. "{}=bitfieldExtract(floatBitsToUint({}_cbuf{}[{}/16][({}/4)%4]),int(({}%4)*8),8);",
  29. inst, ctx.stage_name, binding.U32(), offset_var, offset_var, offset_var);
  30. }
  31. }
  32. void EmitGetCbufS8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  33. [[maybe_unused]] const IR::Value& binding,
  34. [[maybe_unused]] const IR::Value& offset) {
  35. if (offset.IsImmediate()) {
  36. ctx.AddU32("{}=bitfieldExtract(floatBitsToInt({}_cbuf{}[{}].{}),int({}),8);", inst,
  37. ctx.stage_name, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
  38. (offset.U32() % 4) * 8);
  39. } else {
  40. const auto offset_var{ctx.reg_alloc.Consume(offset)};
  41. ctx.AddU32(
  42. "{}=bitfieldExtract(floatBitsToInt({}_cbuf{}[{}/16][({}/4)%4]),int(({}%4)*8),8);", inst,
  43. ctx.stage_name, binding.U32(), offset_var, offset_var, offset_var);
  44. }
  45. }
  46. void EmitGetCbufU16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  47. [[maybe_unused]] const IR::Value& binding,
  48. [[maybe_unused]] const IR::Value& offset) {
  49. if (offset.IsImmediate()) {
  50. ctx.AddU32("{}=bitfieldExtract(floatBitsToUint({}_cbuf{}[{}].{}),int({}),16);", inst,
  51. ctx.stage_name, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
  52. ((offset.U32() / 2) % 2) * 16);
  53. } else {
  54. const auto offset_var{ctx.reg_alloc.Consume(offset)};
  55. ctx.AddU32("{}=bitfieldExtract(floatBitsToUint({}_cbuf{}[{}/16][({}/4)%4]),int((({}/"
  56. "2)%2)*16),16);",
  57. inst, ctx.stage_name, binding.U32(), offset_var, offset_var, offset_var);
  58. }
  59. }
  60. void EmitGetCbufS16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  61. [[maybe_unused]] const IR::Value& binding,
  62. [[maybe_unused]] const IR::Value& offset) {
  63. if (offset.IsImmediate()) {
  64. ctx.AddU32("{}=bitfieldExtract(floatBitsToInt({}_cbuf{}[{}].{}),int({}),16);", inst,
  65. ctx.stage_name, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
  66. ((offset.U32() / 2) % 2) * 16);
  67. } else {
  68. const auto offset_var{ctx.reg_alloc.Consume(offset)};
  69. ctx.AddU32(
  70. "{}=bitfieldExtract(floatBitsToInt({}_cbuf{}[{}/16][({}/4)%4]),int((({}/2)%2)*16),16);",
  71. inst, ctx.stage_name, binding.U32(), offset_var, offset_var, offset_var);
  72. }
  73. }
  74. void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
  75. const IR::Value& offset) {
  76. if (offset.IsImmediate()) {
  77. ctx.AddU32("{}=floatBitsToUint({}_cbuf{}[{}].{});", inst, ctx.stage_name, binding.U32(),
  78. offset.U32() / 16, OffsetSwizzle(offset.U32()));
  79. } else {
  80. const auto offset_var{ctx.reg_alloc.Consume(offset)};
  81. ctx.AddU32("{}=floatBitsToUint({}_cbuf{}[{}/16][({}/4)%4]);", inst, ctx.stage_name,
  82. binding.U32(), offset_var, offset_var);
  83. }
  84. }
  85. void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
  86. const IR::Value& offset) {
  87. if (offset.IsImmediate()) {
  88. ctx.AddF32("{}={}_cbuf{}[{}].{};", inst, ctx.stage_name, binding.U32(), offset.U32() / 16,
  89. OffsetSwizzle(offset.U32()));
  90. } else {
  91. const auto offset_var{ctx.reg_alloc.Consume(offset)};
  92. ctx.AddF32("{}={}_cbuf{}[{}/16][({}/4)%4];", inst, ctx.stage_name, binding.U32(),
  93. offset_var, offset_var);
  94. }
  95. }
  96. void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
  97. const IR::Value& offset) {
  98. if (offset.IsImmediate()) {
  99. ctx.AddU32x2(
  100. "{}=uvec2(floatBitsToUint({}_cbuf{}[{}].{}),floatBitsToUint({}_cbuf{}[{}].{}));", inst,
  101. ctx.stage_name, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
  102. ctx.stage_name, binding.U32(), (offset.U32() + 4) / 16,
  103. OffsetSwizzle(offset.U32() + 4));
  104. } else {
  105. const auto offset_var{ctx.reg_alloc.Consume(offset)};
  106. ctx.AddU32x2("{}=uvec2(floatBitsToUint({}_cbuf{}[{}/16][({}/"
  107. "4)%4]),floatBitsToUint({}_cbuf{}[({}+4)/16][(({}+4)/4)%4]));",
  108. inst, ctx.stage_name, binding.U32(), offset_var, offset_var, ctx.stage_name,
  109. binding.U32(), offset_var, offset_var);
  110. }
  111. }
  112. void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
  113. [[maybe_unused]] std::string_view vertex) {
  114. const u32 element{static_cast<u32>(attr) % 4};
  115. const char swizzle{"xyzw"[element]};
  116. if (IR::IsGeneric(attr)) {
  117. const u32 index{IR::GenericAttributeIndex(attr)};
  118. ctx.AddF32("{}=in_attr{}.{};", inst, index, swizzle);
  119. return;
  120. }
  121. switch (attr) {
  122. case IR::Attribute::PositionX:
  123. case IR::Attribute::PositionY:
  124. case IR::Attribute::PositionZ:
  125. case IR::Attribute::PositionW:
  126. switch (ctx.stage) {
  127. case Stage::VertexA:
  128. case Stage::VertexB:
  129. ctx.AddF32("{}=gl_Position.{};", inst, swizzle);
  130. break;
  131. case Stage::Fragment:
  132. ctx.AddF32("{}=gl_FragCoord.{};", inst, swizzle);
  133. break;
  134. default:
  135. throw NotImplementedException("Get Position for stage {}", ctx.stage);
  136. }
  137. break;
  138. case IR::Attribute::InstanceId:
  139. ctx.AddS32("{}=gl_InstanceID;", inst);
  140. break;
  141. case IR::Attribute::VertexId:
  142. ctx.AddS32("{}=gl_VertexID;", inst);
  143. break;
  144. case IR::Attribute::FrontFace:
  145. ctx.AddS32("{}=gl_FrontFacing?-1:0;", inst);
  146. break;
  147. default:
  148. fmt::print("Get attribute {}", attr);
  149. throw NotImplementedException("Get attribute {}", attr);
  150. }
  151. }
  152. void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value,
  153. [[maybe_unused]] std::string_view vertex) {
  154. const u32 element{static_cast<u32>(attr) % 4};
  155. const char swizzle{"xyzw"[element]};
  156. if (IR::IsGeneric(attr)) {
  157. const u32 index{IR::GenericAttributeIndex(attr)};
  158. ctx.Add("out_attr{}.{}={};", index, swizzle, value);
  159. return;
  160. }
  161. switch (attr) {
  162. case IR::Attribute::PointSize:
  163. ctx.Add("gl_Pointsize={};", value);
  164. break;
  165. case IR::Attribute::PositionX:
  166. case IR::Attribute::PositionY:
  167. case IR::Attribute::PositionZ:
  168. case IR::Attribute::PositionW:
  169. ctx.Add("gl_Position.{}={};", swizzle, value);
  170. break;
  171. default:
  172. fmt::print("Set attribute {}", attr);
  173. throw NotImplementedException("Set attribute {}", attr);
  174. }
  175. }
  176. void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value) {
  177. const char swizzle{"xyzw"[component]};
  178. ctx.Add("frag_color{}.{}={};", index, swizzle, value);
  179. }
  180. void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst) {
  181. ctx.AddU32x3("{}=gl_LocalInvocationID;", inst);
  182. }
  183. } // namespace Shader::Backend::GLSL