diff options
| author | 2021-04-09 01:45:39 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:26 -0400 | |
| commit | 7cb2ab358517d95ebcd35c94c72b9e91762906c3 (patch) | |
| tree | 3f75959e255026665a4dde406cb8c4cc34fb45a0 /src/shader_recompiler/backend/spirv | |
| parent | shader: Fix Windows build issues (diff) | |
| download | yuzu-7cb2ab358517d95ebcd35c94c72b9e91762906c3.tar.gz yuzu-7cb2ab358517d95ebcd35c94c72b9e91762906c3.tar.xz yuzu-7cb2ab358517d95ebcd35c94c72b9e91762906c3.zip | |
shader: Implement SULD and SUST
Diffstat (limited to 'src/shader_recompiler/backend/spirv')
5 files changed, 130 insertions, 29 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 0c114402b..32f8c4508 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -18,41 +18,70 @@ namespace { | |||
| 18 | Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { | 18 | Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { |
| 19 | const spv::ImageFormat format{spv::ImageFormat::Unknown}; | 19 | const spv::ImageFormat format{spv::ImageFormat::Unknown}; |
| 20 | const Id type{ctx.F32[1]}; | 20 | const Id type{ctx.F32[1]}; |
| 21 | const bool depth{desc.is_depth}; | ||
| 21 | switch (desc.type) { | 22 | switch (desc.type) { |
| 22 | case TextureType::Color1D: | 23 | case TextureType::Color1D: |
| 23 | return ctx.TypeImage(type, spv::Dim::Dim1D, false, false, false, 1, format); | 24 | return ctx.TypeImage(type, spv::Dim::Dim1D, depth, false, false, 1, format); |
| 24 | case TextureType::ColorArray1D: | 25 | case TextureType::ColorArray1D: |
| 25 | return ctx.TypeImage(type, spv::Dim::Dim1D, false, true, false, 1, format); | 26 | return ctx.TypeImage(type, spv::Dim::Dim1D, depth, true, false, 1, format); |
| 26 | case TextureType::Color2D: | 27 | case TextureType::Color2D: |
| 27 | return ctx.TypeImage(type, spv::Dim::Dim2D, false, false, false, 1, format); | 28 | return ctx.TypeImage(type, spv::Dim::Dim2D, depth, false, false, 1, format); |
| 28 | case TextureType::ColorArray2D: | 29 | case TextureType::ColorArray2D: |
| 29 | return ctx.TypeImage(type, spv::Dim::Dim2D, false, true, false, 1, format); | 30 | return ctx.TypeImage(type, spv::Dim::Dim2D, depth, true, false, 1, format); |
| 30 | case TextureType::Color3D: | 31 | case TextureType::Color3D: |
| 31 | return ctx.TypeImage(type, spv::Dim::Dim3D, false, false, false, 1, format); | 32 | return ctx.TypeImage(type, spv::Dim::Dim3D, depth, false, false, 1, format); |
| 32 | case TextureType::ColorCube: | 33 | case TextureType::ColorCube: |
| 33 | return ctx.TypeImage(type, spv::Dim::Cube, false, false, false, 1, format); | 34 | return ctx.TypeImage(type, spv::Dim::Cube, depth, false, false, 1, format); |
| 34 | case TextureType::ColorArrayCube: | 35 | case TextureType::ColorArrayCube: |
| 35 | return ctx.TypeImage(type, spv::Dim::Cube, false, true, false, 1, format); | 36 | return ctx.TypeImage(type, spv::Dim::Cube, depth, true, false, 1, format); |
| 36 | case TextureType::Shadow1D: | ||
| 37 | return ctx.TypeImage(type, spv::Dim::Dim1D, true, false, false, 1, format); | ||
| 38 | case TextureType::ShadowArray1D: | ||
| 39 | return ctx.TypeImage(type, spv::Dim::Dim1D, true, true, false, 1, format); | ||
| 40 | case TextureType::Shadow2D: | ||
| 41 | return ctx.TypeImage(type, spv::Dim::Dim2D, true, false, false, 1, format); | ||
| 42 | case TextureType::ShadowArray2D: | ||
| 43 | return ctx.TypeImage(type, spv::Dim::Dim2D, true, true, false, 1, format); | ||
| 44 | case TextureType::Shadow3D: | ||
| 45 | return ctx.TypeImage(type, spv::Dim::Dim3D, true, false, false, 1, format); | ||
| 46 | case TextureType::ShadowCube: | ||
| 47 | return ctx.TypeImage(type, spv::Dim::Cube, true, false, false, 1, format); | ||
| 48 | case TextureType::ShadowArrayCube: | ||
| 49 | return ctx.TypeImage(type, spv::Dim::Cube, true, true, false, 1, format); | ||
| 50 | case TextureType::Buffer: | 37 | case TextureType::Buffer: |
| 51 | break; | 38 | break; |
| 52 | } | 39 | } |
| 53 | throw InvalidArgument("Invalid texture type {}", desc.type); | 40 | throw InvalidArgument("Invalid texture type {}", desc.type); |
| 54 | } | 41 | } |
| 55 | 42 | ||
| 43 | Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) { | ||
| 44 | const spv::ImageFormat format{[&] { | ||
| 45 | switch (desc.format) { | ||
| 46 | case ImageFormat::Typeless: | ||
| 47 | return spv::ImageFormat::Unknown; | ||
| 48 | case ImageFormat::R8_UINT: | ||
| 49 | return spv::ImageFormat::R8ui; | ||
| 50 | case ImageFormat::R8_SINT: | ||
| 51 | return spv::ImageFormat::R8i; | ||
| 52 | case ImageFormat::R16_UINT: | ||
| 53 | return spv::ImageFormat::R16ui; | ||
| 54 | case ImageFormat::R16_SINT: | ||
| 55 | return spv::ImageFormat::R16i; | ||
| 56 | case ImageFormat::R32_UINT: | ||
| 57 | return spv::ImageFormat::R32ui; | ||
| 58 | case ImageFormat::R32G32_UINT: | ||
| 59 | return spv::ImageFormat::Rg32ui; | ||
| 60 | case ImageFormat::R32G32B32A32_UINT: | ||
| 61 | return spv::ImageFormat::Rgba32ui; | ||
| 62 | } | ||
| 63 | throw InvalidArgument("Invalid image format {}", desc.format); | ||
| 64 | }()}; | ||
| 65 | const Id type{ctx.U32[1]}; | ||
| 66 | switch (desc.type) { | ||
| 67 | case TextureType::Color1D: | ||
| 68 | return ctx.TypeImage(type, spv::Dim::Dim1D, false, false, false, 2, format); | ||
| 69 | case TextureType::ColorArray1D: | ||
| 70 | return ctx.TypeImage(type, spv::Dim::Dim1D, false, true, false, 2, format); | ||
| 71 | case TextureType::Color2D: | ||
| 72 | return ctx.TypeImage(type, spv::Dim::Dim2D, false, false, false, 2, format); | ||
| 73 | case TextureType::ColorArray2D: | ||
| 74 | return ctx.TypeImage(type, spv::Dim::Dim2D, false, true, false, 2, format); | ||
| 75 | case TextureType::Color3D: | ||
| 76 | return ctx.TypeImage(type, spv::Dim::Dim3D, false, false, false, 2, format); | ||
| 77 | case TextureType::Buffer: | ||
| 78 | throw NotImplementedException("Image buffer"); | ||
| 79 | default: | ||
| 80 | break; | ||
| 81 | } | ||
| 82 | throw InvalidArgument("Invalid texture type {}", desc.type); | ||
| 83 | } | ||
| 84 | |||
| 56 | Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin, | 85 | Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin, |
| 57 | spv::StorageClass storage_class) { | 86 | spv::StorageClass storage_class) { |
| 58 | const Id pointer_type{ctx.TypePointer(storage_class, type)}; | 87 | const Id pointer_type{ctx.TypePointer(storage_class, type)}; |
| @@ -134,6 +163,7 @@ EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& bin | |||
| 134 | DefineStorageBuffers(program.info, binding); | 163 | DefineStorageBuffers(program.info, binding); |
| 135 | DefineTextureBuffers(program.info, binding); | 164 | DefineTextureBuffers(program.info, binding); |
| 136 | DefineTextures(program.info, binding); | 165 | DefineTextures(program.info, binding); |
| 166 | DefineImages(program.info, binding); | ||
| 137 | DefineAttributeMemAccess(program.info); | 167 | DefineAttributeMemAccess(program.info); |
| 138 | DefineLabels(program); | 168 | DefineLabels(program); |
| 139 | } | 169 | } |
| @@ -572,6 +602,31 @@ void EmitContext::DefineTextures(const Info& info, u32& binding) { | |||
| 572 | } | 602 | } |
| 573 | } | 603 | } |
| 574 | 604 | ||
| 605 | void EmitContext::DefineImages(const Info& info, u32& binding) { | ||
| 606 | images.reserve(info.image_descriptors.size()); | ||
| 607 | for (const ImageDescriptor& desc : info.image_descriptors) { | ||
| 608 | if (desc.count != 1) { | ||
| 609 | throw NotImplementedException("Array of textures"); | ||
| 610 | } | ||
| 611 | const Id image_type{ImageType(*this, desc)}; | ||
| 612 | const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; | ||
| 613 | const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; | ||
| 614 | Decorate(id, spv::Decoration::Binding, binding); | ||
| 615 | Decorate(id, spv::Decoration::DescriptorSet, 0U); | ||
| 616 | Name(id, fmt::format("img{}_{:02x}", desc.cbuf_index, desc.cbuf_offset)); | ||
| 617 | for (u32 index = 0; index < desc.count; ++index) { | ||
| 618 | images.push_back(ImageDefinition{ | ||
| 619 | .id{id}, | ||
| 620 | .image_type{image_type}, | ||
| 621 | }); | ||
| 622 | } | ||
| 623 | if (profile.supported_spirv >= 0x00010400) { | ||
| 624 | interfaces.push_back(id); | ||
| 625 | } | ||
| 626 | binding += desc.count; | ||
| 627 | } | ||
| 628 | } | ||
| 629 | |||
| 575 | void EmitContext::DefineLabels(IR::Program& program) { | 630 | void EmitContext::DefineLabels(IR::Program& program) { |
| 576 | for (IR::Block* const block : program.blocks) { | 631 | for (IR::Block* const block : program.blocks) { |
| 577 | block->SetDefinition(OpLabel()); | 632 | block->SetDefinition(OpLabel()); |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index f1ac4430c..e70f3458c 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h | |||
| @@ -35,6 +35,11 @@ struct TextureDefinition { | |||
| 35 | Id image_type; | 35 | Id image_type; |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | struct ImageDefinition { | ||
| 39 | Id id; | ||
| 40 | Id image_type; | ||
| 41 | }; | ||
| 42 | |||
| 38 | struct UniformDefinitions { | 43 | struct UniformDefinitions { |
| 39 | Id U8{}; | 44 | Id U8{}; |
| 40 | Id S8{}; | 45 | Id S8{}; |
| @@ -95,8 +100,9 @@ public: | |||
| 95 | 100 | ||
| 96 | std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{}; | 101 | std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{}; |
| 97 | std::array<Id, Info::MAX_SSBOS> ssbos{}; | 102 | std::array<Id, Info::MAX_SSBOS> ssbos{}; |
| 98 | std::vector<TextureDefinition> textures; | ||
| 99 | std::vector<Id> texture_buffers; | 103 | std::vector<Id> texture_buffers; |
| 104 | std::vector<TextureDefinition> textures; | ||
| 105 | std::vector<ImageDefinition> images; | ||
| 100 | 106 | ||
| 101 | Id workgroup_id{}; | 107 | Id workgroup_id{}; |
| 102 | Id local_invocation_id{}; | 108 | Id local_invocation_id{}; |
| @@ -156,6 +162,7 @@ private: | |||
| 156 | void DefineStorageBuffers(const Info& info, u32& binding); | 162 | void DefineStorageBuffers(const Info& info, u32& binding); |
| 157 | void DefineTextureBuffers(const Info& info, u32& binding); | 163 | void DefineTextureBuffers(const Info& info, u32& binding); |
| 158 | void DefineTextures(const Info& info, u32& binding); | 164 | void DefineTextures(const Info& info, u32& binding); |
| 165 | void DefineImages(const Info& info, u32& binding); | ||
| 159 | void DefineAttributeMemAccess(const Info& info); | 166 | void DefineAttributeMemAccess(const Info& info); |
| 160 | void DefineLabels(IR::Program& program); | 167 | void DefineLabels(IR::Program& program); |
| 161 | 168 | ||
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 355cf0ca8..ecd0fac5c 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp | |||
| @@ -253,6 +253,7 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct | |||
| 253 | ctx.AddCapability(spv::Capability::ImageGatherExtended); | 253 | ctx.AddCapability(spv::Capability::ImageGatherExtended); |
| 254 | ctx.AddCapability(spv::Capability::ImageQuery); | 254 | ctx.AddCapability(spv::Capability::ImageQuery); |
| 255 | ctx.AddCapability(spv::Capability::SampledBuffer); | 255 | ctx.AddCapability(spv::Capability::SampledBuffer); |
| 256 | ctx.AddCapability(spv::Capability::StorageImageReadWithoutFormat); | ||
| 256 | } | 257 | } |
| 257 | 258 | ||
| 258 | Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) { | 259 | Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) { |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index 08460c94e..a39b16f1e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h | |||
| @@ -369,6 +369,8 @@ Id EmitBindlessImageFetch(EmitContext&); | |||
| 369 | Id EmitBindlessImageQueryDimensions(EmitContext&); | 369 | Id EmitBindlessImageQueryDimensions(EmitContext&); |
| 370 | Id EmitBindlessImageQueryLod(EmitContext&); | 370 | Id EmitBindlessImageQueryLod(EmitContext&); |
| 371 | Id EmitBindlessImageGradient(EmitContext&); | 371 | Id EmitBindlessImageGradient(EmitContext&); |
| 372 | Id EmitBindlessImageRead(EmitContext&); | ||
| 373 | Id EmitBindlessImageWrite(EmitContext&); | ||
| 372 | Id EmitBoundImageSampleImplicitLod(EmitContext&); | 374 | Id EmitBoundImageSampleImplicitLod(EmitContext&); |
| 373 | Id EmitBoundImageSampleExplicitLod(EmitContext&); | 375 | Id EmitBoundImageSampleExplicitLod(EmitContext&); |
| 374 | Id EmitBoundImageSampleDrefImplicitLod(EmitContext&); | 376 | Id EmitBoundImageSampleDrefImplicitLod(EmitContext&); |
| @@ -379,6 +381,8 @@ Id EmitBoundImageFetch(EmitContext&); | |||
| 379 | Id EmitBoundImageQueryDimensions(EmitContext&); | 381 | Id EmitBoundImageQueryDimensions(EmitContext&); |
| 380 | Id EmitBoundImageQueryLod(EmitContext&); | 382 | Id EmitBoundImageQueryLod(EmitContext&); |
| 381 | Id EmitBoundImageGradient(EmitContext&); | 383 | Id EmitBoundImageGradient(EmitContext&); |
| 384 | Id EmitBoundImageRead(EmitContext&); | ||
| 385 | Id EmitBoundImageWrite(EmitContext&); | ||
| 382 | Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 386 | Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 383 | Id bias_lc, Id offset); | 387 | Id bias_lc, Id offset); |
| 384 | Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 388 | Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| @@ -397,6 +401,8 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i | |||
| 397 | Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); | 401 | Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); |
| 398 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 402 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 399 | Id derivates, Id offset, Id lod_clamp); | 403 | Id derivates, Id offset, Id lod_clamp); |
| 404 | Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); | ||
| 405 | void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color); | ||
| 400 | Id EmitVoteAll(EmitContext& ctx, Id pred); | 406 | Id EmitVoteAll(EmitContext& ctx, Id pred); |
| 401 | Id EmitVoteAny(EmitContext& ctx, Id pred); | 407 | Id EmitVoteAny(EmitContext& ctx, Id pred); |
| 402 | Id EmitVoteEqual(EmitContext& ctx, Id pred); | 408 | Id EmitVoteEqual(EmitContext& ctx, Id pred); |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 6a89c0f79..dd261fd47 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | |||
| @@ -144,6 +144,18 @@ Id TextureImage(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo in | |||
| 144 | } | 144 | } |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | Id Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { | ||
| 148 | if (!index.IsImmediate()) { | ||
| 149 | throw NotImplementedException("Indirect image indexing"); | ||
| 150 | } | ||
| 151 | if (info.type == TextureType::Buffer) { | ||
| 152 | throw NotImplementedException("Image buffer"); | ||
| 153 | } else { | ||
| 154 | const ImageDefinition def{ctx.images.at(index.U32())}; | ||
| 155 | return ctx.OpLoad(def.image_type, def.id); | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 147 | Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { | 159 | Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { |
| 148 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 160 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 149 | if (info.relaxed_precision != 0) { | 161 | if (info.relaxed_precision != 0) { |
| @@ -209,6 +221,14 @@ Id EmitBindlessImageGradient(EmitContext&) { | |||
| 209 | throw LogicError("Unreachable instruction"); | 221 | throw LogicError("Unreachable instruction"); |
| 210 | } | 222 | } |
| 211 | 223 | ||
| 224 | Id EmitBindlessImageRead(EmitContext&) { | ||
| 225 | throw LogicError("Unreachable instruction"); | ||
| 226 | } | ||
| 227 | |||
| 228 | Id EmitBindlessImageWrite(EmitContext&) { | ||
| 229 | throw LogicError("Unreachable instruction"); | ||
| 230 | } | ||
| 231 | |||
| 212 | Id EmitBoundImageSampleImplicitLod(EmitContext&) { | 232 | Id EmitBoundImageSampleImplicitLod(EmitContext&) { |
| 213 | throw LogicError("Unreachable instruction"); | 233 | throw LogicError("Unreachable instruction"); |
| 214 | } | 234 | } |
| @@ -249,6 +269,14 @@ Id EmitBoundImageGradient(EmitContext&) { | |||
| 249 | throw LogicError("Unreachable instruction"); | 269 | throw LogicError("Unreachable instruction"); |
| 250 | } | 270 | } |
| 251 | 271 | ||
| 272 | Id EmitBoundImageRead(EmitContext&) { | ||
| 273 | throw LogicError("Unreachable instruction"); | ||
| 274 | } | ||
| 275 | |||
| 276 | Id EmitBoundImageWrite(EmitContext&) { | ||
| 277 | throw LogicError("Unreachable instruction"); | ||
| 278 | } | ||
| 279 | |||
| 252 | Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 280 | Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 253 | Id bias_lc, Id offset) { | 281 | Id bias_lc, Id offset) { |
| 254 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 282 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| @@ -322,23 +350,16 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i | |||
| 322 | const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; | 350 | const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; |
| 323 | switch (info.type) { | 351 | switch (info.type) { |
| 324 | case TextureType::Color1D: | 352 | case TextureType::Color1D: |
| 325 | case TextureType::Shadow1D: | ||
| 326 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[1], image, lod), | 353 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[1], image, lod), |
| 327 | zero, zero, mips()); | 354 | zero, zero, mips()); |
| 328 | case TextureType::ColorArray1D: | 355 | case TextureType::ColorArray1D: |
| 329 | case TextureType::Color2D: | 356 | case TextureType::Color2D: |
| 330 | case TextureType::ColorCube: | 357 | case TextureType::ColorCube: |
| 331 | case TextureType::ShadowArray1D: | ||
| 332 | case TextureType::Shadow2D: | ||
| 333 | case TextureType::ShadowCube: | ||
| 334 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[2], image, lod), | 358 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[2], image, lod), |
| 335 | zero, mips()); | 359 | zero, mips()); |
| 336 | case TextureType::ColorArray2D: | 360 | case TextureType::ColorArray2D: |
| 337 | case TextureType::Color3D: | 361 | case TextureType::Color3D: |
| 338 | case TextureType::ColorArrayCube: | 362 | case TextureType::ColorArrayCube: |
| 339 | case TextureType::ShadowArray2D: | ||
| 340 | case TextureType::Shadow3D: | ||
| 341 | case TextureType::ShadowArrayCube: | ||
| 342 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[3], image, lod), | 363 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[3], image, lod), |
| 343 | mips()); | 364 | mips()); |
| 344 | case TextureType::Buffer: | 365 | case TextureType::Buffer: |
| @@ -365,4 +386,15 @@ Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I | |||
| 365 | coords, operands.Mask(), operands.Span()); | 386 | coords, operands.Mask(), operands.Span()); |
| 366 | } | 387 | } |
| 367 | 388 | ||
| 389 | Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { | ||
| 390 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | ||
| 391 | return Emit(&EmitContext::OpImageSparseRead, &EmitContext::OpImageRead, ctx, inst, ctx.U32[4], | ||
| 392 | Image(ctx, index, info), coords, std::nullopt, std::span<const Id>{}); | ||
| 393 | } | ||
| 394 | |||
| 395 | void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color) { | ||
| 396 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | ||
| 397 | ctx.OpImageWrite(Image(ctx, index, info), coords, color); | ||
| 398 | } | ||
| 399 | |||
| 368 | } // namespace Shader::Backend::SPIRV | 400 | } // namespace Shader::Backend::SPIRV |