summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/backend')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp79
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.h11
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp58
3 files changed, 92 insertions, 56 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index 7f16cb0dc..8e625f8fb 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -380,6 +380,24 @@ Id CasLoop(EmitContext& ctx, Operation operation, Id array_pointer, Id element_p
380 ctx.OpFunctionEnd(); 380 ctx.OpFunctionEnd();
381 return func; 381 return func;
382} 382}
383
384template <typename Desc>
385std::string NameOf(const Desc& desc, std::string_view prefix) {
386 if (desc.count > 1) {
387 return fmt::format("{}{}_{:02x}x{}", prefix, desc.cbuf_index, desc.cbuf_offset, desc.count);
388 } else {
389 return fmt::format("{}{}_{:02x}", prefix, desc.cbuf_index, desc.cbuf_offset);
390 }
391}
392
393Id DescType(EmitContext& ctx, Id sampled_type, Id pointer_type, u32 count) {
394 if (count > 1) {
395 const Id array_type{ctx.TypeArray(sampled_type, ctx.Const(count))};
396 return ctx.TypePointer(spv::StorageClass::UniformConstant, array_type);
397 } else {
398 return pointer_type;
399 }
400}
383} // Anonymous namespace 401} // Anonymous namespace
384 402
385void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) { 403void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) {
@@ -971,12 +989,15 @@ void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) {
971 const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)}; 989 const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)};
972 Decorate(id, spv::Decoration::Binding, binding); 990 Decorate(id, spv::Decoration::Binding, binding);
973 Decorate(id, spv::Decoration::DescriptorSet, 0U); 991 Decorate(id, spv::Decoration::DescriptorSet, 0U);
974 Name(id, fmt::format("texbuf{}_{:02x}", desc.cbuf_index, desc.cbuf_offset)); 992 Name(id, NameOf(desc, "texbuf"));
975 texture_buffers.insert(texture_buffers.end(), desc.count, id); 993 texture_buffers.push_back({
994 .id = id,
995 .count = desc.count,
996 });
976 if (profile.supported_spirv >= 0x00010400) { 997 if (profile.supported_spirv >= 0x00010400) {
977 interfaces.push_back(id); 998 interfaces.push_back(id);
978 } 999 }
979 binding += desc.count; 1000 ++binding;
980 } 1001 }
981} 1002}
982 1003
@@ -992,44 +1013,41 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) {
992 const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; 1013 const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
993 Decorate(id, spv::Decoration::Binding, binding); 1014 Decorate(id, spv::Decoration::Binding, binding);
994 Decorate(id, spv::Decoration::DescriptorSet, 0U); 1015 Decorate(id, spv::Decoration::DescriptorSet, 0U);
995 Name(id, fmt::format("imgbuf{}_{:02x}", desc.cbuf_index, desc.cbuf_offset)); 1016 Name(id, NameOf(desc, "imgbuf"));
996 const ImageBufferDefinition def{ 1017 image_buffers.push_back({
997 .id = id, 1018 .id = id,
998 .image_type = image_type, 1019 .image_type = image_type,
999 }; 1020 .count = desc.count,
1000 image_buffers.insert(image_buffers.end(), desc.count, def); 1021 });
1001 if (profile.supported_spirv >= 0x00010400) { 1022 if (profile.supported_spirv >= 0x00010400) {
1002 interfaces.push_back(id); 1023 interfaces.push_back(id);
1003 } 1024 }
1004 binding += desc.count; 1025 ++binding;
1005 } 1026 }
1006} 1027}
1007 1028
1008void EmitContext::DefineTextures(const Info& info, u32& binding) { 1029void EmitContext::DefineTextures(const Info& info, u32& binding) {
1009 textures.reserve(info.texture_descriptors.size()); 1030 textures.reserve(info.texture_descriptors.size());
1010 for (const TextureDescriptor& desc : info.texture_descriptors) { 1031 for (const TextureDescriptor& desc : info.texture_descriptors) {
1011 if (desc.count != 1) {
1012 throw NotImplementedException("Array of textures");
1013 }
1014 const Id image_type{ImageType(*this, desc)}; 1032 const Id image_type{ImageType(*this, desc)};
1015 const Id sampled_type{TypeSampledImage(image_type)}; 1033 const Id sampled_type{TypeSampledImage(image_type)};
1016 const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, sampled_type)}; 1034 const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, sampled_type)};
1017 const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; 1035 const Id desc_type{DescType(*this, sampled_type, pointer_type, desc.count)};
1036 const Id id{AddGlobalVariable(desc_type, spv::StorageClass::UniformConstant)};
1018 Decorate(id, spv::Decoration::Binding, binding); 1037 Decorate(id, spv::Decoration::Binding, binding);
1019 Decorate(id, spv::Decoration::DescriptorSet, 0U); 1038 Decorate(id, spv::Decoration::DescriptorSet, 0U);
1020 Name(id, fmt::format("tex{}_{:02x}", desc.cbuf_index, desc.cbuf_offset)); 1039 Name(id, NameOf(desc, "tex"));
1021 for (u32 index = 0; index < desc.count; ++index) { 1040 textures.push_back({
1022 // TODO: Pass count info 1041 .id = id,
1023 textures.push_back(TextureDefinition{ 1042 .sampled_type = sampled_type,
1024 .id{id}, 1043 .pointer_type = pointer_type,
1025 .sampled_type{sampled_type}, 1044 .image_type = image_type,
1026 .image_type{image_type}, 1045 .count = desc.count,
1027 }); 1046 });
1028 }
1029 if (profile.supported_spirv >= 0x00010400) { 1047 if (profile.supported_spirv >= 0x00010400) {
1030 interfaces.push_back(id); 1048 interfaces.push_back(id);
1031 } 1049 }
1032 binding += desc.count; 1050 ++binding;
1033 } 1051 }
1034} 1052}
1035 1053
@@ -1037,24 +1055,23 @@ void EmitContext::DefineImages(const Info& info, u32& binding) {
1037 images.reserve(info.image_descriptors.size()); 1055 images.reserve(info.image_descriptors.size());
1038 for (const ImageDescriptor& desc : info.image_descriptors) { 1056 for (const ImageDescriptor& desc : info.image_descriptors) {
1039 if (desc.count != 1) { 1057 if (desc.count != 1) {
1040 throw NotImplementedException("Array of textures"); 1058 throw NotImplementedException("Array of images");
1041 } 1059 }
1042 const Id image_type{ImageType(*this, desc)}; 1060 const Id image_type{ImageType(*this, desc)};
1043 const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; 1061 const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
1044 const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; 1062 const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
1045 Decorate(id, spv::Decoration::Binding, binding); 1063 Decorate(id, spv::Decoration::Binding, binding);
1046 Decorate(id, spv::Decoration::DescriptorSet, 0U); 1064 Decorate(id, spv::Decoration::DescriptorSet, 0U);
1047 Name(id, fmt::format("img{}_{:02x}", desc.cbuf_index, desc.cbuf_offset)); 1065 Name(id, NameOf(desc, "img"));
1048 for (u32 index = 0; index < desc.count; ++index) { 1066 images.push_back({
1049 images.push_back(ImageDefinition{ 1067 .id = id,
1050 .id{id}, 1068 .image_type = image_type,
1051 .image_type{image_type}, 1069 .count = desc.count,
1052 }); 1070 });
1053 }
1054 if (profile.supported_spirv >= 0x00010400) { 1071 if (profile.supported_spirv >= 0x00010400) {
1055 interfaces.push_back(id); 1072 interfaces.push_back(id);
1056 } 1073 }
1057 binding += desc.count; 1074 ++binding;
1058 } 1075 }
1059} 1076}
1060 1077
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h
index a4503c7ab..c52544fb7 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.h
+++ b/src/shader_recompiler/backend/spirv/emit_context.h
@@ -32,17 +32,26 @@ private:
32struct TextureDefinition { 32struct TextureDefinition {
33 Id id; 33 Id id;
34 Id sampled_type; 34 Id sampled_type;
35 Id pointer_type;
35 Id image_type; 36 Id image_type;
37 u32 count;
38};
39
40struct TextureBufferDefinition {
41 Id id;
42 u32 count;
36}; 43};
37 44
38struct ImageBufferDefinition { 45struct ImageBufferDefinition {
39 Id id; 46 Id id;
40 Id image_type; 47 Id image_type;
48 u32 count;
41}; 49};
42 50
43struct ImageDefinition { 51struct ImageDefinition {
44 Id id; 52 Id id;
45 Id image_type; 53 Id image_type;
54 u32 count;
46}; 55};
47 56
48struct UniformDefinitions { 57struct UniformDefinitions {
@@ -162,7 +171,7 @@ public:
162 171
163 std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{}; 172 std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{};
164 std::array<StorageDefinitions, Info::MAX_SSBOS> ssbos{}; 173 std::array<StorageDefinitions, Info::MAX_SSBOS> ssbos{};
165 std::vector<Id> texture_buffers; 174 std::vector<TextureBufferDefinition> texture_buffers;
166 std::vector<ImageBufferDefinition> image_buffers; 175 std::vector<ImageBufferDefinition> image_buffers;
167 std::vector<TextureDefinition> textures; 176 std::vector<TextureDefinition> textures;
168 std::vector<ImageDefinition> images; 177 std::vector<ImageDefinition> images;
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index 90817f161..6008980af 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -147,24 +147,31 @@ private:
147 spv::ImageOperandsMask mask{}; 147 spv::ImageOperandsMask mask{};
148}; 148};
149 149
150Id Texture(EmitContext& ctx, const IR::Value& index) { 150Id Texture(EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR::Value& index) {
151 if (index.IsImmediate()) { 151 const TextureDefinition& def{ctx.textures.at(info.descriptor_index)};
152 const TextureDefinition def{ctx.textures.at(index.U32())}; 152 if (def.count > 1) {
153 const Id pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))};
154 return ctx.OpLoad(def.sampled_type, pointer);
155 } else {
153 return ctx.OpLoad(def.sampled_type, def.id); 156 return ctx.OpLoad(def.sampled_type, def.id);
154 } 157 }
155 throw NotImplementedException("Indirect texture sample");
156} 158}
157 159
158Id TextureImage(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { 160Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info,
159 if (!index.IsImmediate()) { 161 [[maybe_unused]] const IR::Value& index) {
160 throw NotImplementedException("Indirect texture sample");
161 }
162 if (info.type == TextureType::Buffer) { 162 if (info.type == TextureType::Buffer) {
163 const Id sampler_id{ctx.texture_buffers.at(index.U32())}; 163 const TextureBufferDefinition& def{ctx.texture_buffers.at(info.descriptor_index)};
164 if (def.count > 1) {
165 throw NotImplementedException("Indirect texture sample");
166 }
167 const Id sampler_id{def.id};
164 const Id id{ctx.OpLoad(ctx.sampled_texture_buffer_type, sampler_id)}; 168 const Id id{ctx.OpLoad(ctx.sampled_texture_buffer_type, sampler_id)};
165 return ctx.OpImage(ctx.image_buffer_type, id); 169 return ctx.OpImage(ctx.image_buffer_type, id);
166 } else { 170 } else {
167 const TextureDefinition def{ctx.textures.at(index.U32())}; 171 const TextureDefinition& def{ctx.textures.at(info.descriptor_index)};
172 if (def.count > 1) {
173 throw NotImplementedException("Indirect texture sample");
174 }
168 return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); 175 return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id));
169 } 176 }
170} 177}
@@ -311,7 +318,7 @@ Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value&
311 bias_lc, offset); 318 bias_lc, offset);
312 return Emit(&EmitContext::OpImageSparseSampleImplicitLod, 319 return Emit(&EmitContext::OpImageSparseSampleImplicitLod,
313 &EmitContext::OpImageSampleImplicitLod, ctx, inst, ctx.F32[4], 320 &EmitContext::OpImageSampleImplicitLod, ctx, inst, ctx.F32[4],
314 Texture(ctx, index), coords, operands.Mask(), operands.Span()); 321 Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
315 } else { 322 } else {
316 // We can't use implicit lods on non-fragment stages on SPIR-V. Maxwell hardware behaves as 323 // We can't use implicit lods on non-fragment stages on SPIR-V. Maxwell hardware behaves as
317 // if the lod was explicitly zero. This may change on Turing with implicit compute 324 // if the lod was explicitly zero. This may change on Turing with implicit compute
@@ -320,7 +327,7 @@ Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value&
320 const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod, offset); 327 const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod, offset);
321 return Emit(&EmitContext::OpImageSparseSampleExplicitLod, 328 return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
322 &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], 329 &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],
323 Texture(ctx, index), coords, operands.Mask(), operands.Span()); 330 Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
324 } 331 }
325} 332}
326 333
@@ -329,8 +336,8 @@ Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value&
329 const auto info{inst->Flags<IR::TextureInstInfo>()}; 336 const auto info{inst->Flags<IR::TextureInstInfo>()};
330 const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset); 337 const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset);
331 return Emit(&EmitContext::OpImageSparseSampleExplicitLod, 338 return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
332 &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, index), 339 &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],
333 coords, operands.Mask(), operands.Span()); 340 Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
334} 341}
335 342
336Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, 343Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
@@ -340,7 +347,7 @@ Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Va
340 offset); 347 offset);
341 return Emit(&EmitContext::OpImageSparseSampleDrefImplicitLod, 348 return Emit(&EmitContext::OpImageSparseSampleDrefImplicitLod,
342 &EmitContext::OpImageSampleDrefImplicitLod, ctx, inst, ctx.F32[1], 349 &EmitContext::OpImageSampleDrefImplicitLod, ctx, inst, ctx.F32[1],
343 Texture(ctx, index), coords, dref, operands.Mask(), operands.Span()); 350 Texture(ctx, info, index), coords, dref, operands.Mask(), operands.Span());
344} 351}
345 352
346Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, 353Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
@@ -349,7 +356,7 @@ Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Va
349 const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset); 356 const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset);
350 return Emit(&EmitContext::OpImageSparseSampleDrefExplicitLod, 357 return Emit(&EmitContext::OpImageSparseSampleDrefExplicitLod,
351 &EmitContext::OpImageSampleDrefExplicitLod, ctx, inst, ctx.F32[1], 358 &EmitContext::OpImageSampleDrefExplicitLod, ctx, inst, ctx.F32[1],
352 Texture(ctx, index), coords, dref, operands.Mask(), operands.Span()); 359 Texture(ctx, info, index), coords, dref, operands.Mask(), operands.Span());
353} 360}
354 361
355Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 362Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
@@ -357,15 +364,17 @@ Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id
357 const auto info{inst->Flags<IR::TextureInstInfo>()}; 364 const auto info{inst->Flags<IR::TextureInstInfo>()};
358 const ImageOperands operands(ctx, offset, offset2); 365 const ImageOperands operands(ctx, offset, offset2);
359 return Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst, 366 return Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst,
360 ctx.F32[4], Texture(ctx, index), coords, ctx.Const(info.gather_component), 367 ctx.F32[4], Texture(ctx, info, index), coords, ctx.Const(info.gather_component),
361 operands.Mask(), operands.Span()); 368 operands.Mask(), operands.Span());
362} 369}
363 370
364Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 371Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
365 const IR::Value& offset, const IR::Value& offset2, Id dref) { 372 const IR::Value& offset, const IR::Value& offset2, Id dref) {
373 const auto info{inst->Flags<IR::TextureInstInfo>()};
366 const ImageOperands operands(ctx, offset, offset2); 374 const ImageOperands operands(ctx, offset, offset2);
367 return Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather, ctx, inst, 375 return Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather, ctx, inst,
368 ctx.F32[4], Texture(ctx, index), coords, dref, operands.Mask(), operands.Span()); 376 ctx.F32[4], Texture(ctx, info, index), coords, dref, operands.Mask(),
377 operands.Span());
369} 378}
370 379
371Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, 380Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset,
@@ -376,12 +385,12 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c
376 } 385 }
377 const ImageOperands operands(offset, lod, ms); 386 const ImageOperands operands(offset, lod, ms);
378 return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], 387 return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4],
379 TextureImage(ctx, index, info), coords, operands.Mask(), operands.Span()); 388 TextureImage(ctx, info, index), coords, operands.Mask(), operands.Span());
380} 389}
381 390
382Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod) { 391Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod) {
383 const auto info{inst->Flags<IR::TextureInstInfo>()}; 392 const auto info{inst->Flags<IR::TextureInstInfo>()};
384 const Id image{TextureImage(ctx, index, info)}; 393 const Id image{TextureImage(ctx, info, index)};
385 const Id zero{ctx.u32_zero_value}; 394 const Id zero{ctx.u32_zero_value};
386 const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; 395 const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }};
387 switch (info.type) { 396 switch (info.type) {
@@ -405,9 +414,10 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i
405 throw LogicError("Unspecified image type {}", info.type.Value()); 414 throw LogicError("Unspecified image type {}", info.type.Value());
406} 415}
407 416
408Id EmitImageQueryLod(EmitContext& ctx, IR::Inst*, const IR::Value& index, Id coords) { 417Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) {
418 const auto info{inst->Flags<IR::TextureInstInfo>()};
409 const Id zero{ctx.f32_zero_value}; 419 const Id zero{ctx.f32_zero_value};
410 const Id sampler{Texture(ctx, index)}; 420 const Id sampler{Texture(ctx, info, index)};
411 return ctx.OpCompositeConstruct(ctx.F32[4], ctx.OpImageQueryLod(ctx.F32[2], sampler, coords), 421 return ctx.OpCompositeConstruct(ctx.F32[4], ctx.OpImageQueryLod(ctx.F32[2], sampler, coords),
412 zero, zero); 422 zero, zero);
413} 423}
@@ -418,8 +428,8 @@ Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I
418 const ImageOperands operands(ctx, info.has_lod_clamp != 0, derivates, info.num_derivates, 428 const ImageOperands operands(ctx, info.has_lod_clamp != 0, derivates, info.num_derivates,
419 offset, lod_clamp); 429 offset, lod_clamp);
420 return Emit(&EmitContext::OpImageSparseSampleExplicitLod, 430 return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
421 &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, index), 431 &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],
422 coords, operands.Mask(), operands.Span()); 432 Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
423} 433}
424 434
425Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { 435Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) {