summaryrefslogtreecommitdiff
path: root/src/shader_recompiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler')
-rw-r--r--src/shader_recompiler/backend/glsl/emit_context.cpp48
-rw-r--r--src/shader_recompiler/backend/glsl/emit_context.h13
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_image.cpp136
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_select.cpp4
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp19
5 files changed, 109 insertions, 111 deletions
diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp
index cbcf0a1eb..ed10eca8a 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_context.cpp
@@ -559,53 +559,45 @@ std::string EmitContext::DefineGlobalMemoryFunctions() {
559} 559}
560 560
561void EmitContext::SetupImages(Bindings& bindings) { 561void EmitContext::SetupImages(Bindings& bindings) {
562 image_buffer_bindings.reserve(info.image_buffer_descriptors.size()); 562 image_buffers.reserve(info.image_buffer_descriptors.size());
563 for (const auto& desc : info.image_buffer_descriptors) { 563 for (const auto& desc : info.image_buffer_descriptors) {
564 image_buffer_bindings.push_back(bindings.image); 564 image_buffers.push_back({bindings.image, desc.count});
565 const auto indices{bindings.image + desc.count};
566 const auto format{ImageFormatString(desc.format)}; 565 const auto format{ImageFormatString(desc.format)};
567 for (u32 index = bindings.image; index < indices; ++index) { 566 const auto array_decorator{desc.count > 1 ? fmt::format("[{}]", desc.count) : ""};
568 header += fmt::format("layout(binding={}{}) uniform uimageBuffer img{};", 567 header += fmt::format("layout(binding={}{}) uniform uimageBuffer img{}{};", bindings.image,
569 bindings.image, format, index); 568 format, bindings.image, array_decorator);
570 }
571 bindings.image += desc.count; 569 bindings.image += desc.count;
572 } 570 }
573 image_bindings.reserve(info.image_descriptors.size()); 571 images.reserve(info.image_descriptors.size());
574 for (const auto& desc : info.image_descriptors) { 572 for (const auto& desc : info.image_descriptors) {
575 image_bindings.push_back(bindings.image); 573 images.push_back({bindings.image, desc.count});
576 const auto format{ImageFormatString(desc.format)}; 574 const auto format{ImageFormatString(desc.format)};
577 const auto image_type{ImageType(desc.type)}; 575 const auto image_type{ImageType(desc.type)};
578 const auto qualifier{desc.is_written ? "" : "readonly "}; 576 const auto qualifier{desc.is_written ? "" : "readonly "};
579 const auto indices{bindings.image + desc.count}; 577 const auto array_decorator{desc.count > 1 ? fmt::format("[{}]", desc.count) : ""};
580 for (u32 index = bindings.image; index < indices; ++index) { 578 header += fmt::format("layout(binding={}{})uniform {}{} img{}{};", bindings.image, format,
581 header += fmt::format("layout(binding={}{})uniform {}{} img{};", bindings.image, format, 579 qualifier, image_type, bindings.image, array_decorator);
582 qualifier, image_type, index);
583 }
584 bindings.image += desc.count; 580 bindings.image += desc.count;
585 } 581 }
586} 582}
587 583
588void EmitContext::SetupTextures(Bindings& bindings) { 584void EmitContext::SetupTextures(Bindings& bindings) {
589 texture_buffer_bindings.reserve(info.texture_buffer_descriptors.size()); 585 texture_buffers.reserve(info.texture_buffer_descriptors.size());
590 for (const auto& desc : info.texture_buffer_descriptors) { 586 for (const auto& desc : info.texture_buffer_descriptors) {
591 texture_buffer_bindings.push_back(bindings.texture); 587 texture_buffers.push_back({bindings.texture, desc.count});
592 const auto sampler_type{SamplerType(TextureType::Buffer, false)}; 588 const auto sampler_type{SamplerType(TextureType::Buffer, false)};
593 const auto indices{bindings.texture + desc.count}; 589 const auto array_decorator{desc.count > 1 ? fmt::format("[{}]", desc.count) : ""};
594 for (u32 index = bindings.texture; index < indices; ++index) { 590 header += fmt::format("layout(binding={}) uniform {} tex{}{};", bindings.texture,
595 header += fmt::format("layout(binding={}) uniform {} tex{};", bindings.texture, 591 sampler_type, bindings.texture, array_decorator);
596 sampler_type, index);
597 }
598 bindings.texture += desc.count; 592 bindings.texture += desc.count;
599 } 593 }
600 texture_bindings.reserve(info.texture_descriptors.size()); 594 textures.reserve(info.texture_descriptors.size());
601 for (const auto& desc : info.texture_descriptors) { 595 for (const auto& desc : info.texture_descriptors) {
596 textures.push_back({bindings.texture, desc.count});
602 const auto sampler_type{SamplerType(desc.type, desc.is_depth)}; 597 const auto sampler_type{SamplerType(desc.type, desc.is_depth)};
603 texture_bindings.push_back(bindings.texture); 598 const auto array_decorator{desc.count > 1 ? fmt::format("[{}]", desc.count) : ""};
604 const auto indices{bindings.texture + desc.count}; 599 header += fmt::format("layout(binding={}) uniform {} tex{}{};", bindings.texture,
605 for (u32 index = bindings.texture; index < indices; ++index) { 600 sampler_type, bindings.texture, array_decorator);
606 header += fmt::format("layout(binding={}) uniform {} tex{};", bindings.texture,
607 sampler_type, index);
608 }
609 bindings.texture += desc.count; 601 bindings.texture += desc.count;
610 } 602 }
611} 603}
diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h
index 9d8be0c9a..685f56089 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.h
+++ b/src/shader_recompiler/backend/glsl/emit_context.h
@@ -36,6 +36,11 @@ struct GenericElementInfo {
36 u32 num_components{}; 36 u32 num_components{};
37}; 37};
38 38
39struct TextureImageDefinition {
40 u32 binding;
41 u32 count;
42};
43
39class EmitContext { 44class EmitContext {
40public: 45public:
41 explicit EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, 46 explicit EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
@@ -142,10 +147,10 @@ public:
142 std::string_view stage_name = "invalid"; 147 std::string_view stage_name = "invalid";
143 std::string_view position_name = "gl_Position"; 148 std::string_view position_name = "gl_Position";
144 149
145 std::vector<u32> texture_buffer_bindings; 150 std::vector<TextureImageDefinition> texture_buffers;
146 std::vector<u32> image_buffer_bindings; 151 std::vector<TextureImageDefinition> image_buffers;
147 std::vector<u32> texture_bindings; 152 std::vector<TextureImageDefinition> textures;
148 std::vector<u32> image_bindings; 153 std::vector<TextureImageDefinition> images;
149 std::array<std::array<GenericElementInfo, 4>, 32> output_generics{}; 154 std::array<std::array<GenericElementInfo, 4>, 32> output_generics{};
150 155
151 bool uses_y_direction{}; 156 bool uses_y_direction{};
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
index 00fe288e2..6a98f7ac2 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
@@ -12,20 +12,18 @@
12 12
13namespace Shader::Backend::GLSL { 13namespace Shader::Backend::GLSL {
14namespace { 14namespace {
15std::string Texture(EmitContext& ctx, const IR::TextureInstInfo& info) { 15std::string Texture(EmitContext& ctx, const IR::TextureInstInfo& info, const IR::Value& index) {
16 if (info.type == TextureType::Buffer) { 16 const auto def{info.type == TextureType::Buffer ? ctx.texture_buffers.at(info.descriptor_index)
17 return fmt::format("tex{}", ctx.texture_buffer_bindings.at(info.descriptor_index)); 17 : ctx.textures.at(info.descriptor_index)};
18 } else { 18 const auto index_offset{def.count > 1 ? fmt::format("[{}]", ctx.var_alloc.Consume(index)) : ""};
19 return fmt::format("tex{}", ctx.texture_bindings.at(info.descriptor_index)); 19 return fmt::format("tex{}{}", def.binding, index_offset);
20 }
21} 20}
22 21
23std::string Image(EmitContext& ctx, const IR::TextureInstInfo& info) { 22std::string Image(EmitContext& ctx, const IR::TextureInstInfo& info, const IR::Value& index) {
24 if (info.type == TextureType::Buffer) { 23 const auto def{info.type == TextureType::Buffer ? ctx.image_buffers.at(info.descriptor_index)
25 return fmt::format("img{}", ctx.image_buffer_bindings.at(info.descriptor_index)); 24 : ctx.images.at(info.descriptor_index)};
26 } else { 25 const auto index_offset{def.count > 1 ? fmt::format("[{}]", ctx.var_alloc.Consume(index)) : ""};
27 return fmt::format("img{}", ctx.image_bindings.at(info.descriptor_index)); 26 return fmt::format("img{}{}", def.binding, index_offset);
28 }
29} 27}
30 28
31std::string CastToIntVec(std::string_view value, const IR::TextureInstInfo& info) { 29std::string CastToIntVec(std::string_view value, const IR::TextureInstInfo& info) {
@@ -137,14 +135,14 @@ IR::Inst* PrepareSparse(IR::Inst& inst) {
137} 135}
138} // Anonymous namespace 136} // Anonymous namespace
139 137
140void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, 138void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
141 [[maybe_unused]] const IR::Value& index, std::string_view coords, 139 std::string_view coords, std::string_view bias_lc,
142 std::string_view bias_lc, const IR::Value& offset) { 140 const IR::Value& offset) {
143 const auto info{inst.Flags<IR::TextureInstInfo>()}; 141 const auto info{inst.Flags<IR::TextureInstInfo>()};
144 if (info.has_lod_clamp) { 142 if (info.has_lod_clamp) {
145 throw NotImplementedException("EmitImageSampleImplicitLod Lod clamp samples"); 143 throw NotImplementedException("EmitImageSampleImplicitLod Lod clamp samples");
146 } 144 }
147 const auto texture{Texture(ctx, info)}; 145 const auto texture{Texture(ctx, info, index)};
148 const auto bias{info.has_bias ? fmt::format(",{}", bias_lc) : ""}; 146 const auto bias{info.has_bias ? fmt::format(",{}", bias_lc) : ""};
149 const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; 147 const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
150 const auto sparse_inst{PrepareSparse(inst)}; 148 const auto sparse_inst{PrepareSparse(inst)};
@@ -175,9 +173,9 @@ void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst,
175 } 173 }
176} 174}
177 175
178void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, 176void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
179 [[maybe_unused]] const IR::Value& index, std::string_view coords, 177 std::string_view coords, std::string_view lod_lc,
180 std::string_view lod_lc, const IR::Value& offset) { 178 const IR::Value& offset) {
181 const auto info{inst.Flags<IR::TextureInstInfo>()}; 179 const auto info{inst.Flags<IR::TextureInstInfo>()};
182 if (info.has_bias) { 180 if (info.has_bias) {
183 throw NotImplementedException("EmitImageSampleExplicitLod Bias texture samples"); 181 throw NotImplementedException("EmitImageSampleExplicitLod Bias texture samples");
@@ -185,7 +183,7 @@ void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst,
185 if (info.has_lod_clamp) { 183 if (info.has_lod_clamp) {
186 throw NotImplementedException("EmitImageSampleExplicitLod Lod clamp samples"); 184 throw NotImplementedException("EmitImageSampleExplicitLod Lod clamp samples");
187 } 185 }
188 const auto texture{Texture(ctx, info)}; 186 const auto texture{Texture(ctx, info, index)};
189 const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; 187 const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
190 const auto sparse_inst{PrepareSparse(inst)}; 188 const auto sparse_inst{PrepareSparse(inst)};
191 if (!sparse_inst) { 189 if (!sparse_inst) {
@@ -208,8 +206,7 @@ void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst,
208 } 206 }
209} 207}
210 208
211void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, 209void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
212 [[maybe_unused]] const IR::Value& index,
213 std::string_view coords, std::string_view dref, 210 std::string_view coords, std::string_view dref,
214 std::string_view bias_lc, const IR::Value& offset) { 211 std::string_view bias_lc, const IR::Value& offset) {
215 const auto info{inst.Flags<IR::TextureInstInfo>()}; 212 const auto info{inst.Flags<IR::TextureInstInfo>()};
@@ -223,7 +220,7 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst,
223 if (info.has_lod_clamp) { 220 if (info.has_lod_clamp) {
224 throw NotImplementedException("EmitImageSampleDrefImplicitLod Lod clamp samples"); 221 throw NotImplementedException("EmitImageSampleDrefImplicitLod Lod clamp samples");
225 } 222 }
226 const auto texture{Texture(ctx, info)}; 223 const auto texture{Texture(ctx, info, index)};
227 const auto bias{info.has_bias ? fmt::format(",{}", bias_lc) : ""}; 224 const auto bias{info.has_bias ? fmt::format(",{}", bias_lc) : ""};
228 const bool needs_shadow_ext{NeedsShadowLodExt(info.type)}; 225 const bool needs_shadow_ext{NeedsShadowLodExt(info.type)};
229 const auto cast{needs_shadow_ext ? "vec4" : "vec3"}; 226 const auto cast{needs_shadow_ext ? "vec4" : "vec3"};
@@ -263,8 +260,7 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst,
263 } 260 }
264} 261}
265 262
266void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, 263void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
267 [[maybe_unused]] const IR::Value& index,
268 std::string_view coords, std::string_view dref, 264 std::string_view coords, std::string_view dref,
269 std::string_view lod_lc, const IR::Value& offset) { 265 std::string_view lod_lc, const IR::Value& offset) {
270 const auto info{inst.Flags<IR::TextureInstInfo>()}; 266 const auto info{inst.Flags<IR::TextureInstInfo>()};
@@ -278,7 +274,7 @@ void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst,
278 if (info.has_lod_clamp) { 274 if (info.has_lod_clamp) {
279 throw NotImplementedException("EmitImageSampleDrefExplicitLod Lod clamp samples"); 275 throw NotImplementedException("EmitImageSampleDrefExplicitLod Lod clamp samples");
280 } 276 }
281 const auto texture{Texture(ctx, info)}; 277 const auto texture{Texture(ctx, info, index)};
282 const bool needs_shadow_ext{NeedsShadowLodExt(info.type)}; 278 const bool needs_shadow_ext{NeedsShadowLodExt(info.type)};
283 const bool use_grad{!ctx.profile.support_gl_texture_shadow_lod && needs_shadow_ext}; 279 const bool use_grad{!ctx.profile.support_gl_texture_shadow_lod && needs_shadow_ext};
284 const auto cast{needs_shadow_ext ? "vec4" : "vec3"}; 280 const auto cast{needs_shadow_ext ? "vec4" : "vec3"};
@@ -313,10 +309,10 @@ void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst,
313 } 309 }
314} 310}
315 311
316void EmitImageGather(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, 312void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
317 std::string_view coords, const IR::Value& offset, const IR::Value& offset2) { 313 std::string_view coords, const IR::Value& offset, const IR::Value& offset2) {
318 const auto info{inst.Flags<IR::TextureInstInfo>()}; 314 const auto info{inst.Flags<IR::TextureInstInfo>()};
319 const auto texture{Texture(ctx, info)}; 315 const auto texture{Texture(ctx, info, index)};
320 const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; 316 const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
321 const auto sparse_inst{PrepareSparse(inst)}; 317 const auto sparse_inst{PrepareSparse(inst)};
322 if (!sparse_inst) { 318 if (!sparse_inst) {
@@ -355,11 +351,11 @@ void EmitImageGather(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR
355 info.gather_component); 351 info.gather_component);
356} 352}
357 353
358void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, 354void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
359 std::string_view coords, const IR::Value& offset, const IR::Value& offset2, 355 std::string_view coords, const IR::Value& offset, const IR::Value& offset2,
360 std::string_view dref) { 356 std::string_view dref) {
361 const auto info{inst.Flags<IR::TextureInstInfo>()}; 357 const auto info{inst.Flags<IR::TextureInstInfo>()};
362 const auto texture{Texture(ctx, info)}; 358 const auto texture{Texture(ctx, info, index)};
363 const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; 359 const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
364 const auto sparse_inst{PrepareSparse(inst)}; 360 const auto sparse_inst{PrepareSparse(inst)};
365 if (!sparse_inst) { 361 if (!sparse_inst) {
@@ -395,7 +391,7 @@ void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] cons
395 *sparse_inst, texture, CastToIntVec(coords, info), dref, offsets, texel); 391 *sparse_inst, texture, CastToIntVec(coords, info), dref, offsets, texel);
396} 392}
397 393
398void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, 394void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
399 std::string_view coords, std::string_view offset, std::string_view lod, 395 std::string_view coords, std::string_view offset, std::string_view lod,
400 [[maybe_unused]] std::string_view ms) { 396 [[maybe_unused]] std::string_view ms) {
401 const auto info{inst.Flags<IR::TextureInstInfo>()}; 397 const auto info{inst.Flags<IR::TextureInstInfo>()};
@@ -405,7 +401,7 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR:
405 if (info.has_lod_clamp) { 401 if (info.has_lod_clamp) {
406 throw NotImplementedException("EmitImageFetch Lod clamp samples"); 402 throw NotImplementedException("EmitImageFetch Lod clamp samples");
407 } 403 }
408 const auto texture{Texture(ctx, info)}; 404 const auto texture{Texture(ctx, info, index)};
409 const auto sparse_inst{PrepareSparse(inst)}; 405 const auto sparse_inst{PrepareSparse(inst)};
410 const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; 406 const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
411 if (!sparse_inst) { 407 if (!sparse_inst) {
@@ -433,10 +429,10 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR:
433 } 429 }
434} 430}
435 431
436void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, 432void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
437 [[maybe_unused]] const IR::Value& index, std::string_view lod) { 433 std::string_view lod) {
438 const auto info{inst.Flags<IR::TextureInstInfo>()}; 434 const auto info{inst.Flags<IR::TextureInstInfo>()};
439 const auto texture{Texture(ctx, info)}; 435 const auto texture{Texture(ctx, info, index)};
440 switch (info.type) { 436 switch (info.type) {
441 case TextureType::Color1D: 437 case TextureType::Color1D:
442 return ctx.AddU32x4( 438 return ctx.AddU32x4(
@@ -460,14 +456,14 @@ void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst,
460 throw LogicError("Unspecified image type {}", info.type.Value()); 456 throw LogicError("Unspecified image type {}", info.type.Value());
461} 457}
462 458
463void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, 459void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
464 std::string_view coords) { 460 std::string_view coords) {
465 const auto info{inst.Flags<IR::TextureInstInfo>()}; 461 const auto info{inst.Flags<IR::TextureInstInfo>()};
466 const auto texture{Texture(ctx, info)}; 462 const auto texture{Texture(ctx, info, index)};
467 return ctx.AddF32x4("{}=vec4(textureQueryLod({},{}),0.0,0.0);", inst, texture, coords); 463 return ctx.AddF32x4("{}=vec4(textureQueryLod({},{}),0.0,0.0);", inst, texture, coords);
468} 464}
469 465
470void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, 466void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
471 std::string_view coords, const IR::Value& derivatives, 467 std::string_view coords, const IR::Value& derivatives,
472 const IR::Value& offset, [[maybe_unused]] const IR::Value& lod_clamp) { 468 const IR::Value& offset, [[maybe_unused]] const IR::Value& lod_clamp) {
473 const auto info{inst.Flags<IR::TextureInstInfo>()}; 469 const auto info{inst.Flags<IR::TextureInstInfo>()};
@@ -481,7 +477,7 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const
481 if (!offset.IsEmpty()) { 477 if (!offset.IsEmpty()) {
482 throw NotImplementedException("EmitImageGradient offset"); 478 throw NotImplementedException("EmitImageGradient offset");
483 } 479 }
484 const auto texture{Texture(ctx, info)}; 480 const auto texture{Texture(ctx, info, index)};
485 const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; 481 const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
486 const bool multi_component{info.num_derivates > 1 || info.has_lod_clamp}; 482 const bool multi_component{info.num_derivates > 1 || info.has_lod_clamp};
487 const auto derivatives_vec{ctx.var_alloc.Consume(derivatives)}; 483 const auto derivatives_vec{ctx.var_alloc.Consume(derivatives)};
@@ -494,65 +490,60 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const
494 } 490 }
495} 491}
496 492
497void EmitImageRead(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, 493void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
498 std::string_view coords) { 494 std::string_view coords) {
499 const auto info{inst.Flags<IR::TextureInstInfo>()}; 495 const auto info{inst.Flags<IR::TextureInstInfo>()};
500 const auto sparse_inst{PrepareSparse(inst)}; 496 const auto sparse_inst{PrepareSparse(inst)};
501 if (sparse_inst) { 497 if (sparse_inst) {
502 throw NotImplementedException("EmitImageRead Sparse"); 498 throw NotImplementedException("EmitImageRead Sparse");
503 } 499 }
504 const auto image{Image(ctx, info)}; 500 const auto image{Image(ctx, info, index)};
505 ctx.AddU32x4("{}=uvec4(imageLoad({},{}));", inst, image, TexelFetchCastToInt(coords, info)); 501 ctx.AddU32x4("{}=uvec4(imageLoad({},{}));", inst, image, TexelFetchCastToInt(coords, info));
506} 502}
507 503
508void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, 504void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
509 std::string_view coords, std::string_view color) { 505 std::string_view coords, std::string_view color) {
510 const auto info{inst.Flags<IR::TextureInstInfo>()}; 506 const auto info{inst.Flags<IR::TextureInstInfo>()};
511 const auto image{Image(ctx, info)}; 507 const auto image{Image(ctx, info, index)};
512 ctx.Add("imageStore({},{},{});", image, TexelFetchCastToInt(coords, info), color); 508 ctx.Add("imageStore({},{},{});", image, TexelFetchCastToInt(coords, info), color);
513} 509}
514 510
515void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, 511void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
516 [[maybe_unused]] const IR::Value& index, std::string_view coords, 512 std::string_view coords, std::string_view value) {
517 std::string_view value) {
518 const auto info{inst.Flags<IR::TextureInstInfo>()}; 513 const auto info{inst.Flags<IR::TextureInstInfo>()};
519 const auto image{Image(ctx, info)}; 514 const auto image{Image(ctx, info, index)};
520 ctx.AddU32("{}=imageAtomicAdd({},{},{});", inst, image, TexelFetchCastToInt(coords, info), 515 ctx.AddU32("{}=imageAtomicAdd({},{},{});", inst, image, TexelFetchCastToInt(coords, info),
521 value); 516 value);
522} 517}
523 518
524void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, 519void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
525 [[maybe_unused]] const IR::Value& index, std::string_view coords, 520 std::string_view coords, std::string_view value) {
526 std::string_view value) {
527 const auto info{inst.Flags<IR::TextureInstInfo>()}; 521 const auto info{inst.Flags<IR::TextureInstInfo>()};
528 const auto image{Image(ctx, info)}; 522 const auto image{Image(ctx, info, index)};
529 ctx.AddU32("{}=imageAtomicMin({},{},int({}));", inst, image, TexelFetchCastToInt(coords, info), 523 ctx.AddU32("{}=imageAtomicMin({},{},int({}));", inst, image, TexelFetchCastToInt(coords, info),
530 value); 524 value);
531} 525}
532 526
533void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, 527void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
534 [[maybe_unused]] const IR::Value& index, std::string_view coords, 528 std::string_view coords, std::string_view value) {
535 std::string_view value) {
536 const auto info{inst.Flags<IR::TextureInstInfo>()}; 529 const auto info{inst.Flags<IR::TextureInstInfo>()};
537 const auto image{Image(ctx, info)}; 530 const auto image{Image(ctx, info, index)};
538 ctx.AddU32("{}=imageAtomicMin({},{},uint({}));", inst, image, TexelFetchCastToInt(coords, info), 531 ctx.AddU32("{}=imageAtomicMin({},{},uint({}));", inst, image, TexelFetchCastToInt(coords, info),
539 value); 532 value);
540} 533}
541 534
542void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, 535void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
543 [[maybe_unused]] const IR::Value& index, std::string_view coords, 536 std::string_view coords, std::string_view value) {
544 std::string_view value) {
545 const auto info{inst.Flags<IR::TextureInstInfo>()}; 537 const auto info{inst.Flags<IR::TextureInstInfo>()};
546 const auto image{Image(ctx, info)}; 538 const auto image{Image(ctx, info, index)};
547 ctx.AddU32("{}=imageAtomicMax({},{},int({}));", inst, image, TexelFetchCastToInt(coords, info), 539 ctx.AddU32("{}=imageAtomicMax({},{},int({}));", inst, image, TexelFetchCastToInt(coords, info),
548 value); 540 value);
549} 541}
550 542
551void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, 543void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
552 [[maybe_unused]] const IR::Value& index, std::string_view coords, 544 std::string_view coords, std::string_view value) {
553 std::string_view value) {
554 const auto info{inst.Flags<IR::TextureInstInfo>()}; 545 const auto info{inst.Flags<IR::TextureInstInfo>()};
555 const auto image{Image(ctx, info)}; 546 const auto image{Image(ctx, info, index)};
556 ctx.AddU32("{}=imageAtomicMax({},{},uint({}));", inst, image, TexelFetchCastToInt(coords, info), 547 ctx.AddU32("{}=imageAtomicMax({},{},uint({}));", inst, image, TexelFetchCastToInt(coords, info),
557 value); 548 value);
558} 549}
@@ -567,35 +558,34 @@ void EmitImageAtomicDec32(EmitContext&, IR::Inst&, const IR::Value&, std::string
567 NotImplemented(); 558 NotImplemented();
568} 559}
569 560
570void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, 561void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
571 std::string_view coords, std::string_view value) { 562 std::string_view coords, std::string_view value) {
572 const auto info{inst.Flags<IR::TextureInstInfo>()}; 563 const auto info{inst.Flags<IR::TextureInstInfo>()};
573 const auto image{Image(ctx, info)}; 564 const auto image{Image(ctx, info, index)};
574 ctx.AddU32("{}=imageAtomicAnd({},{},{});", inst, image, TexelFetchCastToInt(coords, info), 565 ctx.AddU32("{}=imageAtomicAnd({},{},{});", inst, image, TexelFetchCastToInt(coords, info),
575 value); 566 value);
576} 567}
577 568
578void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, 569void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
579 std::string_view coords, std::string_view value) { 570 std::string_view coords, std::string_view value) {
580 const auto info{inst.Flags<IR::TextureInstInfo>()}; 571 const auto info{inst.Flags<IR::TextureInstInfo>()};
581 const auto image{Image(ctx, info)}; 572 const auto image{Image(ctx, info, index)};
582 ctx.AddU32("{}=imageAtomicOr({},{},{});", inst, image, TexelFetchCastToInt(coords, info), 573 ctx.AddU32("{}=imageAtomicOr({},{},{});", inst, image, TexelFetchCastToInt(coords, info),
583 value); 574 value);
584} 575}
585 576
586void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, 577void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
587 std::string_view coords, std::string_view value) { 578 std::string_view coords, std::string_view value) {
588 const auto info{inst.Flags<IR::TextureInstInfo>()}; 579 const auto info{inst.Flags<IR::TextureInstInfo>()};
589 const auto image{Image(ctx, info)}; 580 const auto image{Image(ctx, info, index)};
590 ctx.AddU32("{}=imageAtomicXor({},{},{});", inst, image, TexelFetchCastToInt(coords, info), 581 ctx.AddU32("{}=imageAtomicXor({},{},{});", inst, image, TexelFetchCastToInt(coords, info),
591 value); 582 value);
592} 583}
593 584
594void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, 585void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
595 [[maybe_unused]] const IR::Value& index, std::string_view coords, 586 std::string_view coords, std::string_view value) {
596 std::string_view value) {
597 const auto info{inst.Flags<IR::TextureInstInfo>()}; 587 const auto info{inst.Flags<IR::TextureInstInfo>()};
598 const auto image{Image(ctx, info)}; 588 const auto image{Image(ctx, info, index)};
599 ctx.AddU32("{}=imageAtomicExchange({},{},{});", inst, image, TexelFetchCastToInt(coords, info), 589 ctx.AddU32("{}=imageAtomicExchange({},{},{});", inst, image, TexelFetchCastToInt(coords, info),
600 value); 590 value);
601} 591}
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp
index 7aa6096e6..49fba9073 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp
@@ -28,12 +28,12 @@ void EmitSelectU16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::stri
28 28
29void EmitSelectU32(EmitContext& ctx, IR::Inst& inst, std::string_view cond, 29void EmitSelectU32(EmitContext& ctx, IR::Inst& inst, std::string_view cond,
30 std::string_view true_value, std::string_view false_value) { 30 std::string_view true_value, std::string_view false_value) {
31 ctx.AddU32("{}={}?uint({}):uint({});", inst, cond, true_value, false_value); 31 ctx.AddU32("{}={}?{}:{};", inst, cond, true_value, false_value);
32} 32}
33 33
34void EmitSelectU64(EmitContext& ctx, IR::Inst& inst, std::string_view cond, 34void EmitSelectU64(EmitContext& ctx, IR::Inst& inst, std::string_view cond,
35 std::string_view true_value, std::string_view false_value) { 35 std::string_view true_value, std::string_view false_value) {
36 ctx.AddU64("{}={}?uint64_t({}):uint64_t({});", inst, cond, true_value, false_value); 36 ctx.AddU64("{}={}?{}:{};", inst, cond, true_value, false_value);
37} 37}
38 38
39void EmitSelectF16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view cond, 39void EmitSelectF16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view cond,
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
index 7abc6575f..8a13bf617 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
@@ -9,6 +9,17 @@
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10 10
11namespace Shader::Backend::GLSL { 11namespace Shader::Backend::GLSL {
12namespace {
13constexpr char cas_loop[]{"for(;;){{uint old_value={};uint "
14 "cas_result=atomicCompSwap({},old_value,bitfieldInsert({},{},{},{}));"
15 "if(cas_result==old_value){{break;}}}}"};
16
17void SharedWriteCas(EmitContext& ctx, std::string_view offset, std::string_view value,
18 std::string_view bit_offset, u32 num_bits) {
19 const auto smem{fmt::format("smem[{}>>2]", offset)};
20 ctx.Add(cas_loop, smem, smem, smem, value, bit_offset, num_bits);
21}
22} // Anonymous namespace
12void EmitLoadSharedU8(EmitContext& ctx, IR::Inst& inst, std::string_view offset) { 23void EmitLoadSharedU8(EmitContext& ctx, IR::Inst& inst, std::string_view offset) {
13 ctx.AddU32("{}=bitfieldExtract(smem[{}>>2],int({}%4)*8,8);", inst, offset, offset); 24 ctx.AddU32("{}=bitfieldExtract(smem[{}>>2],int({}%4)*8,8);", inst, offset, offset);
14} 25}
@@ -39,13 +50,13 @@ void EmitLoadSharedU128(EmitContext& ctx, IR::Inst& inst, std::string_view offse
39} 50}
40 51
41void EmitWriteSharedU8(EmitContext& ctx, std::string_view offset, std::string_view value) { 52void EmitWriteSharedU8(EmitContext& ctx, std::string_view offset, std::string_view value) {
42 ctx.Add("smem[{}>>2]=bitfieldInsert(smem[{}>>2],{},int({}%4)*8,8);", offset, offset, value, 53 const auto bit_offset{fmt::format("int({}%4)*8", offset)};
43 offset); 54 SharedWriteCas(ctx, offset, value, bit_offset, 8);
44} 55}
45 56
46void EmitWriteSharedU16(EmitContext& ctx, std::string_view offset, std::string_view value) { 57void EmitWriteSharedU16(EmitContext& ctx, std::string_view offset, std::string_view value) {
47 ctx.Add("smem[{}>>2]=bitfieldInsert(smem[{}>>2],{},int(({}>>1)%2)*16,16);", offset, offset, 58 const auto bit_offset{fmt::format("int(({}>>1)%2)*16", offset)};
48 value, offset); 59 SharedWriteCas(ctx, offset, value, bit_offset, 16);
49} 60}
50 61
51void EmitWriteSharedU32(EmitContext& ctx, std::string_view offset, std::string_view value) { 62void EmitWriteSharedU32(EmitContext& ctx, std::string_view offset, std::string_view value) {