|  |  |  | @@ -12,20 +12,18 @@ | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | namespace Shader::Backend::GLSL { | 
		
	
		
			
				|  |  |  |  | namespace { | 
		
	
		
			
				|  |  |  |  | std::string Texture(EmitContext& ctx, const IR::TextureInstInfo& info) { | 
		
	
		
			
				|  |  |  |  |     if (info.type == TextureType::Buffer) { | 
		
	
		
			
				|  |  |  |  |         return fmt::format("tex{}", ctx.texture_buffer_bindings.at(info.descriptor_index)); | 
		
	
		
			
				|  |  |  |  |     } else { | 
		
	
		
			
				|  |  |  |  |         return fmt::format("tex{}", ctx.texture_bindings.at(info.descriptor_index)); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | std::string Texture(EmitContext& ctx, const IR::TextureInstInfo& info, const IR::Value& index) { | 
		
	
		
			
				|  |  |  |  |     const auto def{info.type == TextureType::Buffer ? ctx.texture_buffers.at(info.descriptor_index) | 
		
	
		
			
				|  |  |  |  |                                                     : ctx.textures.at(info.descriptor_index)}; | 
		
	
		
			
				|  |  |  |  |     const auto index_offset{def.count > 1 ? fmt::format("[{}]", ctx.var_alloc.Consume(index)) : ""}; | 
		
	
		
			
				|  |  |  |  |     return fmt::format("tex{}{}", def.binding, index_offset); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | std::string Image(EmitContext& ctx, const IR::TextureInstInfo& info) { | 
		
	
		
			
				|  |  |  |  |     if (info.type == TextureType::Buffer) { | 
		
	
		
			
				|  |  |  |  |         return fmt::format("img{}", ctx.image_buffer_bindings.at(info.descriptor_index)); | 
		
	
		
			
				|  |  |  |  |     } else { | 
		
	
		
			
				|  |  |  |  |         return fmt::format("img{}", ctx.image_bindings.at(info.descriptor_index)); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | std::string Image(EmitContext& ctx, const IR::TextureInstInfo& info, const IR::Value& index) { | 
		
	
		
			
				|  |  |  |  |     const auto def{info.type == TextureType::Buffer ? ctx.image_buffers.at(info.descriptor_index) | 
		
	
		
			
				|  |  |  |  |                                                     : ctx.images.at(info.descriptor_index)}; | 
		
	
		
			
				|  |  |  |  |     const auto index_offset{def.count > 1 ? fmt::format("[{}]", ctx.var_alloc.Consume(index)) : ""}; | 
		
	
		
			
				|  |  |  |  |     return fmt::format("img{}{}", def.binding, index_offset); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | std::string CastToIntVec(std::string_view value, const IR::TextureInstInfo& info) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -137,14 +135,14 @@ IR::Inst* PrepareSparse(IR::Inst& inst) { | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | } // Anonymous namespace | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |                                 [[maybe_unused]] const IR::Value& index, std::string_view coords, | 
		
	
		
			
				|  |  |  |  |                                 std::string_view bias_lc, const IR::Value& offset) { | 
		
	
		
			
				|  |  |  |  | void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                                 std::string_view coords, std::string_view bias_lc, | 
		
	
		
			
				|  |  |  |  |                                 const IR::Value& offset) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     if (info.has_lod_clamp) { | 
		
	
		
			
				|  |  |  |  |         throw NotImplementedException("EmitImageSampleImplicitLod Lod clamp samples"); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     const auto bias{info.has_bias ? fmt::format(",{}", bias_lc) : ""}; | 
		
	
		
			
				|  |  |  |  |     const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; | 
		
	
		
			
				|  |  |  |  |     const auto sparse_inst{PrepareSparse(inst)}; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -175,9 +173,9 @@ void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |                                 [[maybe_unused]] const IR::Value& index, std::string_view coords, | 
		
	
		
			
				|  |  |  |  |                                 std::string_view lod_lc, const IR::Value& offset) { | 
		
	
		
			
				|  |  |  |  | void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                                 std::string_view coords, std::string_view lod_lc, | 
		
	
		
			
				|  |  |  |  |                                 const IR::Value& offset) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     if (info.has_bias) { | 
		
	
		
			
				|  |  |  |  |         throw NotImplementedException("EmitImageSampleExplicitLod Bias texture samples"); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -185,7 +183,7 @@ void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |     if (info.has_lod_clamp) { | 
		
	
		
			
				|  |  |  |  |         throw NotImplementedException("EmitImageSampleExplicitLod Lod clamp samples"); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; | 
		
	
		
			
				|  |  |  |  |     const auto sparse_inst{PrepareSparse(inst)}; | 
		
	
		
			
				|  |  |  |  |     if (!sparse_inst) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -208,8 +206,7 @@ void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |                                     [[maybe_unused]] const IR::Value& index, | 
		
	
		
			
				|  |  |  |  | void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                                     std::string_view coords, std::string_view dref, | 
		
	
		
			
				|  |  |  |  |                                     std::string_view bias_lc, const IR::Value& offset) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -223,7 +220,7 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |     if (info.has_lod_clamp) { | 
		
	
		
			
				|  |  |  |  |         throw NotImplementedException("EmitImageSampleDrefImplicitLod Lod clamp samples"); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     const auto bias{info.has_bias ? fmt::format(",{}", bias_lc) : ""}; | 
		
	
		
			
				|  |  |  |  |     const bool needs_shadow_ext{NeedsShadowLodExt(info.type)}; | 
		
	
		
			
				|  |  |  |  |     const auto cast{needs_shadow_ext ? "vec4" : "vec3"}; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -263,8 +260,7 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |                                     [[maybe_unused]] const IR::Value& index, | 
		
	
		
			
				|  |  |  |  | void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                                     std::string_view coords, std::string_view dref, | 
		
	
		
			
				|  |  |  |  |                                     std::string_view lod_lc, const IR::Value& offset) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -278,7 +274,7 @@ void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |     if (info.has_lod_clamp) { | 
		
	
		
			
				|  |  |  |  |         throw NotImplementedException("EmitImageSampleDrefExplicitLod Lod clamp samples"); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     const bool needs_shadow_ext{NeedsShadowLodExt(info.type)}; | 
		
	
		
			
				|  |  |  |  |     const bool use_grad{!ctx.profile.support_gl_texture_shadow_lod && needs_shadow_ext}; | 
		
	
		
			
				|  |  |  |  |     const auto cast{needs_shadow_ext ? "vec4" : "vec3"}; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -313,10 +309,10 @@ void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageGather(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, | 
		
	
		
			
				|  |  |  |  | void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                      std::string_view coords, const IR::Value& offset, const IR::Value& offset2) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; | 
		
	
		
			
				|  |  |  |  |     const auto sparse_inst{PrepareSparse(inst)}; | 
		
	
		
			
				|  |  |  |  |     if (!sparse_inst) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -355,11 +351,11 @@ void EmitImageGather(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR | 
		
	
		
			
				|  |  |  |  |               info.gather_component); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, | 
		
	
		
			
				|  |  |  |  | void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                          std::string_view coords, const IR::Value& offset, const IR::Value& offset2, | 
		
	
		
			
				|  |  |  |  |                          std::string_view dref) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; | 
		
	
		
			
				|  |  |  |  |     const auto sparse_inst{PrepareSparse(inst)}; | 
		
	
		
			
				|  |  |  |  |     if (!sparse_inst) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -395,7 +391,7 @@ void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] cons | 
		
	
		
			
				|  |  |  |  |               *sparse_inst, texture, CastToIntVec(coords, info), dref, offsets, texel); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, | 
		
	
		
			
				|  |  |  |  | void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                     std::string_view coords, std::string_view offset, std::string_view lod, | 
		
	
		
			
				|  |  |  |  |                     [[maybe_unused]] std::string_view ms) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -405,7 +401,7 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR: | 
		
	
		
			
				|  |  |  |  |     if (info.has_lod_clamp) { | 
		
	
		
			
				|  |  |  |  |         throw NotImplementedException("EmitImageFetch Lod clamp samples"); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     const auto sparse_inst{PrepareSparse(inst)}; | 
		
	
		
			
				|  |  |  |  |     const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; | 
		
	
		
			
				|  |  |  |  |     if (!sparse_inst) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -433,10 +429,10 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR: | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |                               [[maybe_unused]] const IR::Value& index, std::string_view lod) { | 
		
	
		
			
				|  |  |  |  | void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                               std::string_view lod) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     switch (info.type) { | 
		
	
		
			
				|  |  |  |  |     case TextureType::Color1D: | 
		
	
		
			
				|  |  |  |  |         return ctx.AddU32x4( | 
		
	
	
		
			
				
					
					|  |  |  | @@ -460,14 +456,14 @@ void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |     throw LogicError("Unspecified image type {}", info.type.Value()); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, | 
		
	
		
			
				|  |  |  |  | void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                        std::string_view coords) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     return ctx.AddF32x4("{}=vec4(textureQueryLod({},{}),0.0,0.0);", inst, texture, coords); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, | 
		
	
		
			
				|  |  |  |  | void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                        std::string_view coords, const IR::Value& derivatives, | 
		
	
		
			
				|  |  |  |  |                        const IR::Value& offset, [[maybe_unused]] const IR::Value& lod_clamp) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -481,7 +477,7 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const | 
		
	
		
			
				|  |  |  |  |     if (!offset.IsEmpty()) { | 
		
	
		
			
				|  |  |  |  |         throw NotImplementedException("EmitImageGradient offset"); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto texture{Texture(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)}; | 
		
	
		
			
				|  |  |  |  |     const bool multi_component{info.num_derivates > 1 || info.has_lod_clamp}; | 
		
	
		
			
				|  |  |  |  |     const auto derivatives_vec{ctx.var_alloc.Consume(derivatives)}; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -494,65 +490,60 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageRead(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, | 
		
	
		
			
				|  |  |  |  | void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                    std::string_view coords) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto sparse_inst{PrepareSparse(inst)}; | 
		
	
		
			
				|  |  |  |  |     if (sparse_inst) { | 
		
	
		
			
				|  |  |  |  |         throw NotImplementedException("EmitImageRead Sparse"); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     ctx.AddU32x4("{}=uvec4(imageLoad({},{}));", inst, image, TexelFetchCastToInt(coords, info)); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, | 
		
	
		
			
				|  |  |  |  | void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                     std::string_view coords, std::string_view color) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     ctx.Add("imageStore({},{},{});", image, TexelFetchCastToInt(coords, info), color); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |                            [[maybe_unused]] const IR::Value& index, std::string_view coords, | 
		
	
		
			
				|  |  |  |  |                            std::string_view value) { | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                            std::string_view coords, std::string_view value) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     ctx.AddU32("{}=imageAtomicAdd({},{},{});", inst, image, TexelFetchCastToInt(coords, info), | 
		
	
		
			
				|  |  |  |  |                value); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |                            [[maybe_unused]] const IR::Value& index, std::string_view coords, | 
		
	
		
			
				|  |  |  |  |                            std::string_view value) { | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                            std::string_view coords, std::string_view value) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     ctx.AddU32("{}=imageAtomicMin({},{},int({}));", inst, image, TexelFetchCastToInt(coords, info), | 
		
	
		
			
				|  |  |  |  |                value); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |                            [[maybe_unused]] const IR::Value& index, std::string_view coords, | 
		
	
		
			
				|  |  |  |  |                            std::string_view value) { | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                            std::string_view coords, std::string_view value) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     ctx.AddU32("{}=imageAtomicMin({},{},uint({}));", inst, image, TexelFetchCastToInt(coords, info), | 
		
	
		
			
				|  |  |  |  |                value); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |                            [[maybe_unused]] const IR::Value& index, std::string_view coords, | 
		
	
		
			
				|  |  |  |  |                            std::string_view value) { | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                            std::string_view coords, std::string_view value) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     ctx.AddU32("{}=imageAtomicMax({},{},int({}));", inst, image, TexelFetchCastToInt(coords, info), | 
		
	
		
			
				|  |  |  |  |                value); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |                            [[maybe_unused]] const IR::Value& index, std::string_view coords, | 
		
	
		
			
				|  |  |  |  |                            std::string_view value) { | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                            std::string_view coords, std::string_view value) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     ctx.AddU32("{}=imageAtomicMax({},{},uint({}));", inst, image, TexelFetchCastToInt(coords, info), | 
		
	
		
			
				|  |  |  |  |                value); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -567,35 +558,34 @@ void EmitImageAtomicDec32(EmitContext&, IR::Inst&, const IR::Value&, std::string | 
		
	
		
			
				|  |  |  |  |     NotImplemented(); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                           std::string_view coords, std::string_view value) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     ctx.AddU32("{}=imageAtomicAnd({},{},{});", inst, image, TexelFetchCastToInt(coords, info), | 
		
	
		
			
				|  |  |  |  |                value); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                          std::string_view coords, std::string_view value) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     ctx.AddU32("{}=imageAtomicOr({},{},{});", inst, image, TexelFetchCastToInt(coords, info), | 
		
	
		
			
				|  |  |  |  |                value); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, [[maybe_unused]] const IR::Value& index, | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                           std::string_view coords, std::string_view value) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     ctx.AddU32("{}=imageAtomicXor({},{},{});", inst, image, TexelFetchCastToInt(coords, info), | 
		
	
		
			
				|  |  |  |  |                value); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, | 
		
	
		
			
				|  |  |  |  |                                [[maybe_unused]] const IR::Value& index, std::string_view coords, | 
		
	
		
			
				|  |  |  |  |                                std::string_view value) { | 
		
	
		
			
				|  |  |  |  | void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 
		
	
		
			
				|  |  |  |  |                                std::string_view coords, std::string_view value) { | 
		
	
		
			
				|  |  |  |  |     const auto info{inst.Flags<IR::TextureInstInfo>()}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info)}; | 
		
	
		
			
				|  |  |  |  |     const auto image{Image(ctx, info, index)}; | 
		
	
		
			
				|  |  |  |  |     ctx.AddU32("{}=imageAtomicExchange({},{},{});", inst, image, TexelFetchCastToInt(coords, info), | 
		
	
		
			
				|  |  |  |  |                value); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  |   |