diff options
| author | 2021-04-22 16:17:59 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:28 -0400 | |
| commit | d10cf55353175b13bed4cf18791e080ecb7fd95b (patch) | |
| tree | 9e26b823d7b48f532914a0511a157c14806debf5 /src/shader_recompiler/backend | |
| parent | shader: Refactor atomic_operations_global_memory (diff) | |
| download | yuzu-d10cf55353175b13bed4cf18791e080ecb7fd95b.tar.gz yuzu-d10cf55353175b13bed4cf18791e080ecb7fd95b.tar.xz yuzu-d10cf55353175b13bed4cf18791e080ecb7fd95b.zip | |
shader: Implement indexed textures
Diffstat (limited to 'src/shader_recompiler/backend')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_context.cpp | 79 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_context.h | 11 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | 58 |
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 | |||
| 384 | template <typename Desc> | ||
| 385 | std::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 | |||
| 393 | Id 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 | ||
| 385 | void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) { | 403 | void 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 | ||
| 1008 | void EmitContext::DefineTextures(const Info& info, u32& binding) { | 1029 | void 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: | |||
| 32 | struct TextureDefinition { | 32 | struct 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 | |||
| 40 | struct TextureBufferDefinition { | ||
| 41 | Id id; | ||
| 42 | u32 count; | ||
| 36 | }; | 43 | }; |
| 37 | 44 | ||
| 38 | struct ImageBufferDefinition { | 45 | struct ImageBufferDefinition { |
| 39 | Id id; | 46 | Id id; |
| 40 | Id image_type; | 47 | Id image_type; |
| 48 | u32 count; | ||
| 41 | }; | 49 | }; |
| 42 | 50 | ||
| 43 | struct ImageDefinition { | 51 | struct ImageDefinition { |
| 44 | Id id; | 52 | Id id; |
| 45 | Id image_type; | 53 | Id image_type; |
| 54 | u32 count; | ||
| 46 | }; | 55 | }; |
| 47 | 56 | ||
| 48 | struct UniformDefinitions { | 57 | struct 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 | ||
| 150 | Id Texture(EmitContext& ctx, const IR::Value& index) { | 150 | Id 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 | ||
| 158 | Id TextureImage(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { | 160 | Id 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 | ||
| 336 | Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, | 343 | Id 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 | ||
| 346 | Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, | 353 | Id 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 | ||
| 355 | Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 362 | Id 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 | ||
| 364 | Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 371 | Id 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 | ||
| 371 | Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, | 380 | Id 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 | ||
| 382 | Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod) { | 391 | Id 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 | ||
| 408 | Id EmitImageQueryLod(EmitContext& ctx, IR::Inst*, const IR::Value& index, Id coords) { | 417 | Id 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 | ||
| 425 | Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { | 435 | Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { |