emit_context.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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/bindings.h"
  5. #include "shader_recompiler/backend/glsl/emit_context.h"
  6. #include "shader_recompiler/frontend/ir/program.h"
  7. #include "shader_recompiler/profile.h"
  8. namespace Shader::Backend::GLSL {
  9. namespace {
  10. std::string_view InterpDecorator(Interpolation interp) {
  11. switch (interp) {
  12. case Interpolation::Smooth:
  13. return "";
  14. case Interpolation::Flat:
  15. return "flat";
  16. case Interpolation::NoPerspective:
  17. return "noperspective";
  18. }
  19. throw InvalidArgument("Invalid interpolation {}", interp);
  20. }
  21. std::string_view SamplerType(TextureType type, bool is_depth) {
  22. if (is_depth) {
  23. switch (type) {
  24. case TextureType::Color1D:
  25. return "sampler1DShadow";
  26. case TextureType::ColorArray1D:
  27. return "sampler1DArrayShadow";
  28. case TextureType::Color2D:
  29. return "sampler2DShadow";
  30. case TextureType::ColorArray2D:
  31. return "sampler2DArrayShadow";
  32. case TextureType::ColorCube:
  33. return "samplerCubeShadow";
  34. case TextureType::ColorArrayCube:
  35. return "samplerCubeArrayShadow";
  36. default:
  37. fmt::print("Texture type: {}", type);
  38. throw NotImplementedException("Texture type: {}", type);
  39. }
  40. }
  41. switch (type) {
  42. case TextureType::Color1D:
  43. return "sampler1D";
  44. case TextureType::ColorArray1D:
  45. return "sampler1DArray";
  46. case TextureType::Color2D:
  47. return "sampler2D";
  48. case TextureType::ColorArray2D:
  49. return "sampler2DArray";
  50. case TextureType::Color3D:
  51. return "sampler3D";
  52. case TextureType::ColorCube:
  53. return "samplerCube";
  54. case TextureType::ColorArrayCube:
  55. return "samplerCubeArray";
  56. case TextureType::Buffer:
  57. return "samplerBuffer";
  58. default:
  59. fmt::print("Texture type: {}", type);
  60. throw NotImplementedException("Texture type: {}", type);
  61. }
  62. }
  63. } // namespace
  64. EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
  65. const RuntimeInfo& runtime_info_)
  66. : info{program.info}, profile{profile_}, runtime_info{runtime_info_} {
  67. SetupExtensions(header);
  68. stage = program.stage;
  69. switch (program.stage) {
  70. case Stage::VertexA:
  71. case Stage::VertexB:
  72. stage_name = "vs";
  73. // TODO: add only what's used by the shader
  74. header +=
  75. "out gl_PerVertex {vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];};";
  76. break;
  77. case Stage::TessellationControl:
  78. case Stage::TessellationEval:
  79. stage_name = "ts";
  80. break;
  81. case Stage::Geometry:
  82. stage_name = "gs";
  83. break;
  84. case Stage::Fragment:
  85. stage_name = "fs";
  86. break;
  87. case Stage::Compute:
  88. stage_name = "cs";
  89. header += fmt::format("layout(local_size_x={},local_size_y={},local_size_z={}) in;\n",
  90. program.workgroup_size[0], program.workgroup_size[1],
  91. program.workgroup_size[2]);
  92. break;
  93. }
  94. for (size_t index = 0; index < info.input_generics.size(); ++index) {
  95. const auto& generic{info.input_generics[index]};
  96. if (generic.used) {
  97. header += fmt::format("layout(location={}) {} in vec4 in_attr{};", index,
  98. InterpDecorator(generic.interpolation), index);
  99. }
  100. }
  101. for (size_t index = 0; index < info.stores_frag_color.size(); ++index) {
  102. if (!info.stores_frag_color[index]) {
  103. continue;
  104. }
  105. header += fmt::format("layout(location={})out vec4 frag_color{};", index, index);
  106. }
  107. for (size_t index = 0; index < info.stores_generics.size(); ++index) {
  108. if (info.stores_generics[index]) {
  109. header += fmt::format("layout(location={}) out vec4 out_attr{};", index, index);
  110. }
  111. }
  112. DefineConstantBuffers(bindings);
  113. DefineStorageBuffers(bindings);
  114. SetupImages(bindings);
  115. DefineHelperFunctions();
  116. }
  117. void EmitContext::SetupExtensions(std::string&) {
  118. header += "#extension GL_ARB_separate_shader_objects : enable\n";
  119. header += "#extension GL_ARB_sparse_texture2 : enable\n";
  120. header += "#extension GL_EXT_texture_shadow_lod : enable\n";
  121. // header += "#extension GL_ARB_texture_cube_map_array : enable\n";
  122. if (info.uses_int64) {
  123. header += "#extension GL_ARB_gpu_shader_int64 : enable\n";
  124. }
  125. if (info.uses_int64_bit_atomics) {
  126. header += "#extension GL_NV_shader_atomic_int64 : enable\n";
  127. }
  128. if (info.uses_atomic_f32_add) {
  129. header += "#extension GL_NV_shader_atomic_float : enable\n";
  130. }
  131. if (info.uses_atomic_f16x2_add || info.uses_atomic_f16x2_min || info.uses_atomic_f16x2_max) {
  132. header += "#extension NV_shader_atomic_fp16_vector : enable\n";
  133. }
  134. if (info.uses_fp16) {
  135. if (profile.support_gl_nv_gpu_shader_5) {
  136. header += "#extension GL_NV_gpu_shader5 : enable\n";
  137. }
  138. if (profile.support_gl_amd_gpu_shader_half_float) {
  139. header += "#extension GL_AMD_gpu_shader_half_float : enable\n";
  140. }
  141. }
  142. if (info.uses_subgroup_invocation_id || info.uses_subgroup_mask || info.uses_subgroup_vote ||
  143. info.uses_subgroup_shuffles || info.uses_fswzadd) {
  144. header += "#extension GL_ARB_shader_ballot : enable\n";
  145. header += "#extension GL_ARB_shader_group_vote : enable\n";
  146. }
  147. }
  148. void EmitContext::DefineConstantBuffers(Bindings& bindings) {
  149. if (info.constant_buffer_descriptors.empty()) {
  150. return;
  151. }
  152. for (const auto& desc : info.constant_buffer_descriptors) {
  153. header += fmt::format(
  154. "layout(std140,binding={}) uniform {}_cbuf_{}{{vec4 {}_cbuf{}[{}];}};",
  155. bindings.uniform_buffer, stage_name, desc.index, stage_name, desc.index, 4 * 1024);
  156. bindings.uniform_buffer += desc.count;
  157. }
  158. }
  159. void EmitContext::DefineStorageBuffers(Bindings& bindings) {
  160. if (info.storage_buffers_descriptors.empty()) {
  161. return;
  162. }
  163. for (const auto& desc : info.storage_buffers_descriptors) {
  164. header +=
  165. fmt::format("layout(std430,binding={}) buffer ssbo_{}{{uint ssbo{}[];}};",
  166. bindings.storage_buffer, bindings.storage_buffer, bindings.storage_buffer);
  167. bindings.storage_buffer += desc.count;
  168. }
  169. }
  170. void EmitContext::DefineHelperFunctions() {
  171. if (info.uses_global_increment) {
  172. header += "uint CasIncrement(uint op_a,uint op_b){return(op_a>=op_b)?0u:(op_a+1u);}\n";
  173. }
  174. if (info.uses_global_decrement) {
  175. header +=
  176. "uint CasDecrement(uint op_a,uint op_b){return(op_a==0||op_a>op_b)?op_b:(op_a-1u);}\n";
  177. }
  178. if (info.uses_atomic_f32_add) {
  179. header += "uint CasFloatAdd(uint op_a,float op_b){return "
  180. "floatBitsToUint(uintBitsToFloat(op_a)+op_b);}\n";
  181. }
  182. if (info.uses_atomic_f32x2_add) {
  183. header += "uint CasFloatAdd32x2(uint op_a,vec2 op_b){return "
  184. "packHalf2x16(unpackHalf2x16(op_a)+op_b);}\n";
  185. }
  186. if (info.uses_atomic_f32x2_min) {
  187. header += "uint CasFloatMin32x2(uint op_a,vec2 op_b){return "
  188. "packHalf2x16(min(unpackHalf2x16(op_a),op_b));}\n";
  189. }
  190. if (info.uses_atomic_f32x2_max) {
  191. header += "uint CasFloatMax32x2(uint op_a,vec2 op_b){return "
  192. "packHalf2x16(max(unpackHalf2x16(op_a),op_b));}\n";
  193. }
  194. if (info.uses_atomic_f16x2_add) {
  195. header += "uint CasFloatAdd16x2(uint op_a,f16vec2 op_b){return "
  196. "packFloat2x16(unpackFloat2x16(op_a)+op_b);}\n";
  197. }
  198. if (info.uses_atomic_f16x2_min) {
  199. header += "uint CasFloatMin16x2(uint op_a,f16vec2 op_b){return "
  200. "packFloat2x16(min(unpackFloat2x16(op_a),op_b));}\n";
  201. }
  202. if (info.uses_atomic_f16x2_max) {
  203. header += "uint CasFloatMax16x2(uint op_a,f16vec2 op_b){return "
  204. "packFloat2x16(max(unpackFloat2x16(op_a),op_b));}\n";
  205. }
  206. if (info.uses_atomic_s32_min) {
  207. header += "uint CasMinS32(uint op_a,uint op_b){return uint(min(int(op_a),int(op_b)));}";
  208. }
  209. if (info.uses_atomic_s32_max) {
  210. header += "uint CasMaxS32(uint op_a,uint op_b){return uint(max(int(op_a),int(op_b)));}";
  211. }
  212. }
  213. void EmitContext::SetupImages(Bindings& bindings) {
  214. image_buffer_bindings.reserve(info.image_buffer_descriptors.size());
  215. for (const auto& desc : info.image_buffer_descriptors) {
  216. throw NotImplementedException("image_buffer_descriptors");
  217. image_buffer_bindings.push_back(bindings.image);
  218. bindings.image += desc.count;
  219. }
  220. image_bindings.reserve(info.image_descriptors.size());
  221. for (const auto& desc : info.image_descriptors) {
  222. throw NotImplementedException("image_bindings");
  223. image_bindings.push_back(bindings.image);
  224. bindings.image += desc.count;
  225. }
  226. texture_buffer_bindings.reserve(info.texture_buffer_descriptors.size());
  227. for (const auto& desc : info.texture_buffer_descriptors) {
  228. throw NotImplementedException("TextureType::Buffer");
  229. texture_buffer_bindings.push_back(bindings.texture);
  230. bindings.texture += desc.count;
  231. }
  232. texture_bindings.reserve(info.texture_descriptors.size());
  233. for (const auto& desc : info.texture_descriptors) {
  234. const auto sampler_type{SamplerType(desc.type, desc.is_depth)};
  235. texture_bindings.push_back(bindings.texture);
  236. const auto indices{bindings.texture + desc.count};
  237. for (u32 index = bindings.texture; index < indices; ++index) {
  238. header += fmt::format("layout(binding={}) uniform {} tex{};", bindings.texture,
  239. sampler_type, index);
  240. }
  241. bindings.texture += desc.count;
  242. }
  243. }
  244. } // namespace Shader::Backend::GLSL