summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/glsl/emit_context.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/backend/glsl/emit_context.cpp')
-rw-r--r--src/shader_recompiler/backend/glsl/emit_context.cpp73
1 files changed, 35 insertions, 38 deletions
diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp
index fbc4b9c0f..ae5ac752d 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_context.cpp
@@ -22,9 +22,9 @@ std::string_view InterpDecorator(Interpolation interp) {
22 case Interpolation::Smooth: 22 case Interpolation::Smooth:
23 return ""; 23 return "";
24 case Interpolation::Flat: 24 case Interpolation::Flat:
25 return "flat"; 25 return "flat ";
26 case Interpolation::NoPerspective: 26 case Interpolation::NoPerspective:
27 return "noperspective"; 27 return "noperspective ";
28 } 28 }
29 throw InvalidArgument("Invalid interpolation {}", interp); 29 throw InvalidArgument("Invalid interpolation {}", interp);
30} 30}
@@ -77,7 +77,6 @@ std::string_view SamplerType(TextureType type, bool is_depth) {
77 case TextureType::ColorArrayCube: 77 case TextureType::ColorArrayCube:
78 return "samplerCubeArrayShadow"; 78 return "samplerCubeArrayShadow";
79 default: 79 default:
80 fmt::print("Texture type: {}", type);
81 throw NotImplementedException("Texture type: {}", type); 80 throw NotImplementedException("Texture type: {}", type);
82 } 81 }
83 } 82 }
@@ -191,29 +190,27 @@ void SetupOutPerVertex(EmitContext& ctx, std::string& header) {
191 if (!StoresPerVertexAttributes(ctx.stage)) { 190 if (!StoresPerVertexAttributes(ctx.stage)) {
192 return; 191 return;
193 } 192 }
194 header += "out gl_PerVertex{"; 193 header += "out gl_PerVertex{vec4 gl_Position;";
195 header += "vec4 gl_Position;";
196 if (ctx.info.stores_point_size) { 194 if (ctx.info.stores_point_size) {
197 header += "float gl_PointSize;"; 195 header += "float gl_PointSize;";
198 } 196 }
199 if (ctx.info.stores_clip_distance) { 197 if (ctx.info.stores_clip_distance) {
200 header += "float gl_ClipDistance[];"; 198 header += "float gl_ClipDistance[];";
201 } 199 }
202 if (ctx.info.stores_viewport_index && ctx.supports_viewport_layer && 200 if (ctx.info.stores_viewport_index && ctx.profile.support_gl_vertex_viewport_layer &&
203 ctx.stage != Stage::Geometry) { 201 ctx.stage != Stage::Geometry) {
204 header += "int gl_ViewportIndex;"; 202 header += "int gl_ViewportIndex;";
205 } 203 }
206 header += "};\n"; 204 header += "};";
207 if (ctx.info.stores_viewport_index && ctx.stage == Stage::Geometry) { 205 if (ctx.info.stores_viewport_index && ctx.stage == Stage::Geometry) {
208 header += "out int gl_ViewportIndex;"; 206 header += "out int gl_ViewportIndex;";
209 } 207 }
210} 208}
211} // namespace 209} // Anonymous namespace
212 210
213EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, 211EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
214 const RuntimeInfo& runtime_info_) 212 const RuntimeInfo& runtime_info_)
215 : info{program.info}, profile{profile_}, runtime_info{runtime_info_} { 213 : info{program.info}, profile{profile_}, runtime_info{runtime_info_} {
216 supports_viewport_layer = profile.support_gl_vertex_viewport_layer;
217 SetupExtensions(header); 214 SetupExtensions(header);
218 stage = program.stage; 215 stage = program.stage;
219 switch (program.stage) { 216 switch (program.stage) {
@@ -222,18 +219,18 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
222 stage_name = "vs"; 219 stage_name = "vs";
223 break; 220 break;
224 case Stage::TessellationControl: 221 case Stage::TessellationControl:
225 stage_name = "tsc"; 222 stage_name = "tcs";
226 header += fmt::format("layout(vertices={})out;\n", program.invocations); 223 header += fmt::format("layout(vertices={})out;", program.invocations);
227 break; 224 break;
228 case Stage::TessellationEval: 225 case Stage::TessellationEval:
229 stage_name = "tse"; 226 stage_name = "tes";
230 header += fmt::format("layout({},{},{})in;\n", GetTessMode(runtime_info.tess_primitive), 227 header += fmt::format("layout({},{},{})in;", GetTessMode(runtime_info.tess_primitive),
231 GetTessSpacing(runtime_info.tess_spacing), 228 GetTessSpacing(runtime_info.tess_spacing),
232 runtime_info.tess_clockwise ? "cw" : "ccw"); 229 runtime_info.tess_clockwise ? "cw" : "ccw");
233 break; 230 break;
234 case Stage::Geometry: 231 case Stage::Geometry:
235 stage_name = "gs"; 232 stage_name = "gs";
236 header += fmt::format("layout({})in;layout({},max_vertices={})out;\n", 233 header += fmt::format("layout({})in;layout({},max_vertices={})out;",
237 InputPrimitive(runtime_info.input_topology), 234 InputPrimitive(runtime_info.input_topology),
238 OutputPrimitive(program.output_topology), program.output_vertices); 235 OutputPrimitive(program.output_topology), program.output_vertices);
239 break; 236 break;
@@ -242,7 +239,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
242 break; 239 break;
243 case Stage::Compute: 240 case Stage::Compute:
244 stage_name = "cs"; 241 stage_name = "cs";
245 header += fmt::format("layout(local_size_x={},local_size_y={},local_size_z={}) in;\n", 242 header += fmt::format("layout(local_size_x={},local_size_y={},local_size_z={}) in;",
246 program.workgroup_size[0], program.workgroup_size[1], 243 program.workgroup_size[0], program.workgroup_size[1],
247 program.workgroup_size[2]); 244 program.workgroup_size[2]);
248 break; 245 break;
@@ -251,7 +248,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
251 for (size_t index = 0; index < info.input_generics.size(); ++index) { 248 for (size_t index = 0; index < info.input_generics.size(); ++index) {
252 const auto& generic{info.input_generics[index]}; 249 const auto& generic{info.input_generics[index]};
253 if (generic.used) { 250 if (generic.used) {
254 header += fmt::format("layout(location={}){} in vec4 in_attr{}{};", index, 251 header += fmt::format("layout(location={}){}in vec4 in_attr{}{};", index,
255 InterpDecorator(generic.interpolation), index, 252 InterpDecorator(generic.interpolation), index,
256 InputArrayDecorator(stage)); 253 InputArrayDecorator(stage));
257 } 254 }
@@ -260,11 +257,8 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
260 if (!info.uses_patches[index]) { 257 if (!info.uses_patches[index]) {
261 continue; 258 continue;
262 } 259 }
263 if (stage == Stage::TessellationControl) { 260 const auto qualifier{stage == Stage::TessellationControl ? "out" : "in"};
264 header += fmt::format("layout(location={})patch out vec4 patch{};", index, index); 261 header += fmt::format("layout(location={})patch {} vec4 patch{};", index, qualifier, index);
265 } else {
266 header += fmt::format("layout(location={})patch in vec4 patch{};", index, index);
267 }
268 } 262 }
269 for (size_t index = 0; index < info.stores_frag_color.size(); ++index) { 263 for (size_t index = 0; index < info.stores_frag_color.size(); ++index) {
270 if (!info.stores_frag_color[index]) { 264 if (!info.stores_frag_color[index]) {
@@ -278,18 +272,18 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
278 DefineGenericOutput(index, program.invocations); 272 DefineGenericOutput(index, program.invocations);
279 } 273 }
280 } 274 }
281 header += "\n";
282 DefineConstantBuffers(bindings); 275 DefineConstantBuffers(bindings);
283 DefineStorageBuffers(bindings); 276 DefineStorageBuffers(bindings);
284 SetupImages(bindings); 277 SetupImages(bindings);
278 SetupTextures(bindings);
285 DefineHelperFunctions(); 279 DefineHelperFunctions();
286} 280}
287 281
288void EmitContext::SetupExtensions(std::string&) { 282void EmitContext::SetupExtensions(std::string&) {
289 // TODO: track this usage 283 // TODO: track this usage
290 header += "#extension GL_ARB_sparse_texture2 : enable\n"; 284 header += "#extension GL_ARB_sparse_texture2 : enable\n"
291 header += "#extension GL_EXT_texture_shadow_lod : enable\n"; 285 "#extension GL_EXT_texture_shadow_lod : enable\n"
292 header += "#extension GL_EXT_shader_image_load_formatted : enable\n"; 286 "#extension GL_EXT_shader_image_load_formatted : enable\n";
293 if (info.uses_int64) { 287 if (info.uses_int64) {
294 header += "#extension GL_ARB_gpu_shader_int64 : enable\n"; 288 header += "#extension GL_ARB_gpu_shader_int64 : enable\n";
295 } 289 }
@@ -312,13 +306,14 @@ void EmitContext::SetupExtensions(std::string&) {
312 } 306 }
313 if (info.uses_subgroup_invocation_id || info.uses_subgroup_mask || info.uses_subgroup_vote || 307 if (info.uses_subgroup_invocation_id || info.uses_subgroup_mask || info.uses_subgroup_vote ||
314 info.uses_subgroup_shuffles || info.uses_fswzadd) { 308 info.uses_subgroup_shuffles || info.uses_fswzadd) {
315 header += "#extension GL_ARB_shader_ballot : enable\n"; 309 header += "#extension GL_ARB_shader_ballot : enable\n"
316 header += "#extension GL_ARB_shader_group_vote : enable\n"; 310 "#extension GL_ARB_shader_group_vote : enable\n";
317 if (!info.uses_int64) { 311 if (!info.uses_int64) {
318 header += "#extension GL_ARB_gpu_shader_int64 : enable\n"; 312 header += "#extension GL_ARB_gpu_shader_int64 : enable\n";
319 } 313 }
320 } 314 }
321 if (info.stores_viewport_index && supports_viewport_layer && stage != Stage::Geometry) { 315 if (info.stores_viewport_index && profile.support_gl_vertex_viewport_layer &&
316 stage != Stage::Geometry) {
322 header += "#extension GL_ARB_shader_viewport_layer_array : enable\n"; 317 header += "#extension GL_ARB_shader_viewport_layer_array : enable\n";
323 } 318 }
324} 319}
@@ -386,46 +381,45 @@ void EmitContext::DefineGenericOutput(size_t index, u32 invocations) {
386 std::fill_n(output_generics[index].begin() + element, num_components, element_info); 381 std::fill_n(output_generics[index].begin() + element, num_components, element_info);
387 element += num_components; 382 element += num_components;
388 } 383 }
389 header += "\n";
390} 384}
391 385
392void EmitContext::DefineHelperFunctions() { 386void EmitContext::DefineHelperFunctions() {
393 header += "\n#define ftoi floatBitsToInt\n#define ftou floatBitsToUint\n" 387 header += "\n#define ftoi floatBitsToInt\n#define ftou floatBitsToUint\n"
394 "#define itof intBitsToFloat\n#define utof uintBitsToFloat\n"; 388 "#define itof intBitsToFloat\n#define utof uintBitsToFloat\n";
395 if (info.uses_global_increment || info.uses_shared_increment) { 389 if (info.uses_global_increment || info.uses_shared_increment) {
396 header += "uint CasIncrement(uint op_a,uint op_b){return(op_a>=op_b)?0u:(op_a+1u);}\n"; 390 header += "uint CasIncrement(uint op_a,uint op_b){return op_a>=op_b?0u:(op_a+1u);}";
397 } 391 }
398 if (info.uses_global_decrement || info.uses_shared_decrement) { 392 if (info.uses_global_decrement || info.uses_shared_decrement) {
399 header += "uint CasDecrement(uint op_a,uint " 393 header += "uint CasDecrement(uint op_a,uint "
400 "op_b){return(op_a==0||op_a>op_b)?op_b:(op_a-1u);}\n"; 394 "op_b){return op_a==0||op_a>op_b?op_b:(op_a-1u);}";
401 } 395 }
402 if (info.uses_atomic_f32_add) { 396 if (info.uses_atomic_f32_add) {
403 header += "uint CasFloatAdd(uint op_a,float op_b){return " 397 header += "uint CasFloatAdd(uint op_a,float op_b){return "
404 "ftou(utof(op_a)+op_b);}\n"; 398 "ftou(utof(op_a)+op_b);}";
405 } 399 }
406 if (info.uses_atomic_f32x2_add) { 400 if (info.uses_atomic_f32x2_add) {
407 header += "uint CasFloatAdd32x2(uint op_a,vec2 op_b){return " 401 header += "uint CasFloatAdd32x2(uint op_a,vec2 op_b){return "
408 "packHalf2x16(unpackHalf2x16(op_a)+op_b);}\n"; 402 "packHalf2x16(unpackHalf2x16(op_a)+op_b);}";
409 } 403 }
410 if (info.uses_atomic_f32x2_min) { 404 if (info.uses_atomic_f32x2_min) {
411 header += "uint CasFloatMin32x2(uint op_a,vec2 op_b){return " 405 header += "uint CasFloatMin32x2(uint op_a,vec2 op_b){return "
412 "packHalf2x16(min(unpackHalf2x16(op_a),op_b));}\n"; 406 "packHalf2x16(min(unpackHalf2x16(op_a),op_b));}";
413 } 407 }
414 if (info.uses_atomic_f32x2_max) { 408 if (info.uses_atomic_f32x2_max) {
415 header += "uint CasFloatMax32x2(uint op_a,vec2 op_b){return " 409 header += "uint CasFloatMax32x2(uint op_a,vec2 op_b){return "
416 "packHalf2x16(max(unpackHalf2x16(op_a),op_b));}\n"; 410 "packHalf2x16(max(unpackHalf2x16(op_a),op_b));}";
417 } 411 }
418 if (info.uses_atomic_f16x2_add) { 412 if (info.uses_atomic_f16x2_add) {
419 header += "uint CasFloatAdd16x2(uint op_a,f16vec2 op_b){return " 413 header += "uint CasFloatAdd16x2(uint op_a,f16vec2 op_b){return "
420 "packFloat2x16(unpackFloat2x16(op_a)+op_b);}\n"; 414 "packFloat2x16(unpackFloat2x16(op_a)+op_b);}";
421 } 415 }
422 if (info.uses_atomic_f16x2_min) { 416 if (info.uses_atomic_f16x2_min) {
423 header += "uint CasFloatMin16x2(uint op_a,f16vec2 op_b){return " 417 header += "uint CasFloatMin16x2(uint op_a,f16vec2 op_b){return "
424 "packFloat2x16(min(unpackFloat2x16(op_a),op_b));}\n"; 418 "packFloat2x16(min(unpackFloat2x16(op_a),op_b));}";
425 } 419 }
426 if (info.uses_atomic_f16x2_max) { 420 if (info.uses_atomic_f16x2_max) {
427 header += "uint CasFloatMax16x2(uint op_a,f16vec2 op_b){return " 421 header += "uint CasFloatMax16x2(uint op_a,f16vec2 op_b){return "
428 "packFloat2x16(max(unpackFloat2x16(op_a),op_b));}\n"; 422 "packFloat2x16(max(unpackFloat2x16(op_a),op_b));}";
429 } 423 }
430 if (info.uses_atomic_s32_min) { 424 if (info.uses_atomic_s32_min) {
431 header += "uint CasMinS32(uint op_a,uint op_b){return uint(min(int(op_a),int(op_b)));}"; 425 header += "uint CasMinS32(uint op_a,uint op_b){return uint(min(int(op_a),int(op_b)));}";
@@ -534,6 +528,9 @@ void EmitContext::SetupImages(Bindings& bindings) {
534 } 528 }
535 bindings.image += desc.count; 529 bindings.image += desc.count;
536 } 530 }
531}
532
533void EmitContext::SetupTextures(Bindings& bindings) {
537 texture_buffer_bindings.reserve(info.texture_buffer_descriptors.size()); 534 texture_buffer_bindings.reserve(info.texture_buffer_descriptors.size());
538 for (const auto& desc : info.texture_buffer_descriptors) { 535 for (const auto& desc : info.texture_buffer_descriptors) {
539 texture_buffer_bindings.push_back(bindings.texture); 536 texture_buffer_bindings.push_back(bindings.texture);