emit_glsl_context_get_set.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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.var_alloc.Consume(offset)};
  27. ctx.AddU32(
  28. "{}=bitfieldExtract(floatBitsToUint({}_cbuf{}[{}/16][({}>>2)%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.var_alloc.Consume(offset)};
  41. ctx.AddU32(
  42. "{}=bitfieldExtract(floatBitsToInt({}_cbuf{}[{}/16][({}>>2)%4]),int(({}%4)*8),8);",
  43. inst, 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.var_alloc.Consume(offset)};
  55. ctx.AddU32("{}=bitfieldExtract(floatBitsToUint({}_cbuf{}[{}/16][({}>>2)%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.var_alloc.Consume(offset)};
  69. ctx.AddU32("{}=bitfieldExtract(floatBitsToInt({}_cbuf{}[{}/16][({}>>2)%4]),int((({}/"
  70. "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.var_alloc.Consume(offset)};
  81. ctx.AddU32("{}=floatBitsToUint({}_cbuf{}[{}/16][({}>>2)%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.var_alloc.Consume(offset)};
  92. ctx.AddF32("{}={}_cbuf{}[{}/16][({}>>2)%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.var_alloc.Consume(offset)};
  106. ctx.AddU32x2("{}=uvec2(floatBitsToUint({}_cbuf{}[{}/16][({}/"
  107. "4)%4]),floatBitsToUint({}_cbuf{}[({}+4)/16][(({}+4)>>2)%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::PointSpriteS:
  139. case IR::Attribute::PointSpriteT:
  140. ctx.AddF32("{}=gl_PointCoord.{};", inst, swizzle);
  141. break;
  142. case IR::Attribute::InstanceId:
  143. ctx.AddF32("{}=intBitsToFloat(gl_InstanceID);", inst);
  144. break;
  145. case IR::Attribute::VertexId:
  146. ctx.AddF32("{}=intBitsToFloat(gl_VertexID);", inst);
  147. break;
  148. case IR::Attribute::FrontFace:
  149. ctx.AddF32("{}=intBitsToFloat(gl_FrontFacing?-1:0);", inst);
  150. break;
  151. default:
  152. fmt::print("Get attribute {}", attr);
  153. throw NotImplementedException("Get attribute {}", attr);
  154. }
  155. }
  156. void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value,
  157. [[maybe_unused]] std::string_view vertex) {
  158. const u32 element{static_cast<u32>(attr) % 4};
  159. const char swizzle{"xyzw"[element]};
  160. if (IR::IsGeneric(attr)) {
  161. const u32 index{IR::GenericAttributeIndex(attr)};
  162. ctx.Add("out_attr{}.{}={};", index, swizzle, value);
  163. return;
  164. }
  165. switch (attr) {
  166. case IR::Attribute::PointSize:
  167. ctx.Add("gl_PointSize={};", value);
  168. break;
  169. case IR::Attribute::PositionX:
  170. case IR::Attribute::PositionY:
  171. case IR::Attribute::PositionZ:
  172. case IR::Attribute::PositionW:
  173. ctx.Add("gl_Position.{}={};", swizzle, value);
  174. break;
  175. case IR::Attribute::ClipDistance0:
  176. case IR::Attribute::ClipDistance1:
  177. case IR::Attribute::ClipDistance2:
  178. case IR::Attribute::ClipDistance3:
  179. case IR::Attribute::ClipDistance4:
  180. case IR::Attribute::ClipDistance5:
  181. case IR::Attribute::ClipDistance6:
  182. case IR::Attribute::ClipDistance7: {
  183. const u32 index{static_cast<u32>(attr) - static_cast<u32>(IR::Attribute::ClipDistance0)};
  184. ctx.Add("gl_ClipDistance[{}]={};", index, value);
  185. break;
  186. }
  187. default:
  188. fmt::print("Set attribute {}", attr);
  189. throw NotImplementedException("Set attribute {}", attr);
  190. }
  191. }
  192. void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value) {
  193. const char swizzle{"xyzw"[component]};
  194. ctx.Add("frag_color{}.{}={};", index, swizzle, value);
  195. }
  196. void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst) {
  197. ctx.AddU32x3("{}=gl_LocalInvocationID;", inst);
  198. }
  199. void EmitLoadLocal(EmitContext& ctx, IR::Inst& inst, std::string_view word_offset) {
  200. ctx.AddU32("{}=lmem[{}];", inst, word_offset);
  201. }
  202. void EmitWriteLocal(EmitContext& ctx, std::string_view word_offset, std::string_view value) {
  203. ctx.Add("lmem[{}]={};", word_offset, value);
  204. }
  205. } // namespace Shader::Backend::GLSL