From a89c29c2ca90f56f18bde10fd9dd471e44961036 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:13:32 -0800 Subject: [PATCH] shader_recompiler: Rework image read/write emit. (#1819) --- .../backend/spirv/emit_spirv_image.cpp | 45 +++++++++--------- .../backend/spirv/emit_spirv_instructions.h | 7 ++- .../backend/spirv/spirv_emit_context.cpp | 7 +-- .../frontend/translate/vector_memory.cpp | 6 +-- src/shader_recompiler/info.h | 16 +++++-- src/shader_recompiler/ir/ir_emitter.cpp | 13 ++--- src/shader_recompiler/ir/ir_emitter.h | 9 ++-- src/shader_recompiler/ir/opcodes.inc | 5 +- .../ir/passes/resource_tracking_pass.cpp | 47 +++++++++---------- src/shader_recompiler/specialization.h | 5 +- .../renderer_vulkan/vk_compute_pipeline.cpp | 5 +- .../renderer_vulkan/vk_graphics_pipeline.cpp | 5 +- .../renderer_vulkan/vk_rasterizer.cpp | 2 +- src/video_core/texture_cache/image_view.cpp | 2 +- src/video_core/texture_cache/texture_cache.h | 2 +- 15 files changed, 88 insertions(+), 88 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index e5d4f307..2946edab 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -168,22 +168,6 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], texels) : texels; } -Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, - const IR::Value& offset, Id ms) { - const auto& texture = ctx.images[handle & 0xFFFF]; - const Id image = ctx.OpLoad(texture.image_type, texture.id); - const Id result_type = texture.data_types->Get(4); - ImageOperands operands; - operands.AddOffset(ctx, offset); - operands.Add(spv::ImageOperandsMask::Lod, lod); - operands.Add(spv::ImageOperandsMask::Sample, ms); - const Id texel = - texture.is_storage - ? ctx.OpImageRead(result_type, image, coords, operands.mask, operands.operands) - : ctx.OpImageFetch(result_type, image, coords, operands.mask, operands.operands); - return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], texel) : texel; -} - Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod, bool has_mips) { const auto& texture = ctx.images[handle & 0xFFFF]; const Id image = ctx.OpLoad(texture.image_type, texture.id); @@ -236,15 +220,34 @@ Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], sample) : sample; } -Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id lod) { - UNREACHABLE_MSG("SPIR-V Instruction"); -} - -void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id color) { +Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id ms) { const auto& texture = ctx.images[handle & 0xFFFF]; const Id image = ctx.OpLoad(texture.image_type, texture.id); const Id color_type = texture.data_types->Get(4); ImageOperands operands; + operands.Add(spv::ImageOperandsMask::Sample, ms); + Id texel; + if (!texture.is_storage) { + operands.Add(spv::ImageOperandsMask::Lod, lod); + texel = ctx.OpImageFetch(color_type, image, coords, operands.mask, operands.operands); + } else { + if (ctx.profile.supports_image_load_store_lod) { + operands.Add(spv::ImageOperandsMask::Lod, lod); + } else if (Sirit::ValidId(lod)) { + LOG_WARNING(Render, "Image read with LOD not supported by driver"); + } + texel = ctx.OpImageRead(color_type, image, coords, operands.mask, operands.operands); + } + return !texture.is_integer ? ctx.OpBitcast(ctx.U32[4], texel) : texel; +} + +void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id ms, + Id color) { + const auto& texture = ctx.images[handle & 0xFFFF]; + const Id image = ctx.OpLoad(texture.image_type, texture.id); + const Id color_type = texture.data_types->Get(4); + ImageOperands operands; + operands.Add(spv::ImageOperandsMask::Sample, ms); if (ctx.profile.supports_image_load_store_lod) { operands.Add(spv::ImageOperandsMask::Lod, lod); } else if (Sirit::ValidId(lod)) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index f71c61af..2f606eb4 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -395,14 +395,13 @@ Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, const IR::Value& offset); Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, const IR::Value& offset, Id dref); -Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, - const IR::Value& offset, Id ms); Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod, bool skip_mips); Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords); Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id derivatives_dx, Id derivatives_dy, const IR::Value& offset, const IR::Value& lod_clamp); -Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id lod); -void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id color); +Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id ms); +void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id ms, + Id color); Id EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); Id EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 255a3e2b..d8bafccd 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -772,7 +772,7 @@ Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) { const auto image = desc.GetSharp(ctx.info); const auto format = desc.is_atomic ? GetFormat(image) : spv::ImageFormat::Unknown; const auto type = image.GetBoundType(); - const u32 sampled = desc.is_storage ? 2 : 1; + const u32 sampled = desc.IsStorage(image) ? 2 : 1; switch (type) { case AmdGpu::ImageType::Color1D: return ctx.TypeImage(sampled_type, spv::Dim::Dim1D, false, false, false, sampled, format); @@ -800,6 +800,7 @@ void EmitContext::DefineImagesAndSamplers() { const auto sharp = image_desc.GetSharp(info); const auto nfmt = sharp.GetNumberFmt(); const bool is_integer = AmdGpu::IsInteger(nfmt); + const bool is_storage = image_desc.IsStorage(sharp); const VectorIds& data_types = GetAttributeType(*this, nfmt); const Id sampled_type = data_types[1]; const Id image_type{ImageType(*this, image_desc, sampled_type)}; @@ -811,11 +812,11 @@ void EmitContext::DefineImagesAndSamplers() { images.push_back({ .data_types = &data_types, .id = id, - .sampled_type = image_desc.is_storage ? sampled_type : TypeSampledImage(image_type), + .sampled_type = is_storage ? sampled_type : TypeSampledImage(image_type), .pointer_type = pointer_type, .image_type = image_type, .is_integer = is_integer, - .is_storage = image_desc.is_storage, + .is_storage = is_storage, }); interfaces.push_back(id); } diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index 072b1f88..48cb7961 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -420,13 +420,13 @@ void Translator::IMAGE_LOAD(bool has_mip, const GcnInst& inst) { IR::TextureInstInfo info{}; info.has_lod.Assign(has_mip); - const IR::Value texel = ir.ImageFetch(handle, body, {}, {}, {}, info); + const IR::Value texel = ir.ImageRead(handle, body, {}, {}, info); for (u32 i = 0; i < 4; i++) { if (((mimg.dmask >> i) & 1) == 0) { continue; } - IR::F32 value = IR::F32{ir.CompositeExtract(texel, i)}; + IR::U32 value = IR::U32{ir.CompositeExtract(texel, i)}; ir.SetVectorReg(dest_reg++, value); } } @@ -454,7 +454,7 @@ void Translator::IMAGE_STORE(bool has_mip, const GcnInst& inst) { comps.push_back(ir.GetVectorReg(data_reg++)); } const IR::Value value = ir.CompositeConstruct(comps[0], comps[1], comps[2], comps[3]); - ir.ImageWrite(handle, body, {}, value, info); + ir.ImageWrite(handle, body, {}, {}, value, info); } void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) { diff --git a/src/shader_recompiler/info.h b/src/shader_recompiler/info.h index dbea2af8..b6ac1278 100644 --- a/src/shader_recompiler/info.h +++ b/src/shader_recompiler/info.h @@ -49,11 +49,11 @@ struct BufferResource { u8 instance_attrib{}; bool is_written{}; - bool IsStorage(AmdGpu::Buffer buffer) const noexcept { + [[nodiscard]] bool IsStorage(const AmdGpu::Buffer& buffer) const noexcept { return buffer.GetSize() > MaxUboSize || is_written || is_gds_buffer; } - constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept; + [[nodiscard]] constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept; }; using BufferResourceList = boost::container::small_vector; @@ -61,18 +61,24 @@ struct TextureBufferResource { u32 sharp_idx; bool is_written{}; - constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept; + [[nodiscard]] constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept; }; using TextureBufferResourceList = boost::container::small_vector; struct ImageResource { u32 sharp_idx; - bool is_storage{}; bool is_depth{}; bool is_atomic{}; bool is_array{}; + bool is_read{}; + bool is_written{}; - constexpr AmdGpu::Image GetSharp(const Info& info) const noexcept; + [[nodiscard]] bool IsStorage(const AmdGpu::Image& image) const noexcept { + // Need cube as storage when used with ImageRead. + return is_written || (is_read && image.GetBoundType() == AmdGpu::ImageType::Cube); + } + + [[nodiscard]] constexpr AmdGpu::Image GetSharp(const Info& info) const noexcept; }; using ImageResourceList = boost::container::small_vector; diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index 21df5339..c241ec98 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -1630,11 +1630,6 @@ Value IREmitter::ImageGatherDref(const Value& handle, const Value& coords, const return Inst(Opcode::ImageGatherDref, Flags{info}, handle, coords, offset, dref); } -Value IREmitter::ImageFetch(const Value& handle, const Value& coords, const U32& lod, - const Value& offset, const U32& multisampling, TextureInstInfo info) { - return Inst(Opcode::ImageFetch, Flags{info}, handle, coords, lod, offset, multisampling); -} - Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod, const IR::U1& skip_mips) { return Inst(Opcode::ImageQueryDimensions, handle, lod, skip_mips); @@ -1657,13 +1652,13 @@ Value IREmitter::ImageGradient(const Value& handle, const Value& coords, } Value IREmitter::ImageRead(const Value& handle, const Value& coords, const U32& lod, - TextureInstInfo info) { - return Inst(Opcode::ImageRead, Flags{info}, handle, coords, lod); + const U32& multisampling, TextureInstInfo info) { + return Inst(Opcode::ImageRead, Flags{info}, handle, coords, lod, multisampling); } void IREmitter::ImageWrite(const Value& handle, const Value& coords, const U32& lod, - const Value& color, TextureInstInfo info) { - Inst(Opcode::ImageWrite, Flags{info}, handle, coords, lod, color); + const U32& multisampling, const Value& color, TextureInstInfo info) { + Inst(Opcode::ImageWrite, Flags{info}, handle, coords, lod, multisampling, color); } // Debug print maps to SPIRV's NonSemantic DebugPrintf instruction diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index 95713565..4cf44107 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -325,17 +325,14 @@ public: TextureInstInfo info); [[nodiscard]] Value ImageGatherDref(const Value& handle, const Value& coords, const Value& offset, const F32& dref, TextureInstInfo info); - [[nodiscard]] Value ImageFetch(const Value& handle, const Value& coords, const U32& lod, - const Value& offset, const U32& multisampling, - TextureInstInfo info); [[nodiscard]] Value ImageGradient(const Value& handle, const Value& coords, const Value& derivatives_dx, const Value& derivatives_dy, const Value& offset, const F32& lod_clamp, TextureInstInfo info); [[nodiscard]] Value ImageRead(const Value& handle, const Value& coords, const U32& lod, - TextureInstInfo info); - void ImageWrite(const Value& handle, const Value& coords, const U32& lod, const Value& color, - TextureInstInfo info); + const U32& multisampling, TextureInstInfo info); + void ImageWrite(const Value& handle, const Value& coords, const U32& lod, + const U32& multisampling, const Value& color, TextureInstInfo info); void EmitVertex(); void EmitPrimitive(); diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index 470f9fbe..aafd43ea 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -338,12 +338,11 @@ OPCODE(ImageSampleDrefImplicitLod, F32x4, Opaq OPCODE(ImageSampleDrefExplicitLod, F32x4, Opaque, Opaque, F32, F32, Opaque, ) OPCODE(ImageGather, F32x4, Opaque, Opaque, Opaque, ) OPCODE(ImageGatherDref, F32x4, Opaque, Opaque, Opaque, F32, ) -OPCODE(ImageFetch, F32x4, Opaque, Opaque, U32, Opaque, Opaque, ) OPCODE(ImageQueryDimensions, U32x4, Opaque, U32, U1, ) OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, ) OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, F32, ) -OPCODE(ImageRead, U32x4, Opaque, Opaque, U32, ) -OPCODE(ImageWrite, Void, Opaque, Opaque, U32, U32x4, ) +OPCODE(ImageRead, U32x4, Opaque, Opaque, U32, U32, ) +OPCODE(ImageWrite, Void, Opaque, Opaque, U32, U32, U32x4, ) // Image atomic operations OPCODE(ImageAtomicIAdd32, U32, Opaque, Opaque, U32, ) diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index a5939895..db1a2edd 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -115,25 +115,16 @@ bool IsImageAtomicInstruction(const IR::Inst& inst) { } } -bool IsImageStorageInstruction(const IR::Inst& inst) { - switch (inst.GetOpcode()) { - case IR::Opcode::ImageWrite: - case IR::Opcode::ImageRead: - return true; - default: - return IsImageAtomicInstruction(inst); - } -} - bool IsImageInstruction(const IR::Inst& inst) { switch (inst.GetOpcode()) { - case IR::Opcode::ImageFetch: + case IR::Opcode::ImageRead: + case IR::Opcode::ImageWrite: case IR::Opcode::ImageQueryDimensions: case IR::Opcode::ImageQueryLod: case IR::Opcode::ImageSampleRaw: return true; default: - return IsImageStorageInstruction(inst); + return IsImageAtomicInstruction(inst); } } @@ -201,7 +192,8 @@ public: return desc.sharp_idx == existing.sharp_idx; })}; auto& image = image_resources[index]; - image.is_storage |= desc.is_storage; + image.is_read |= desc.is_read; + image.is_written |= desc.is_written; return index; } @@ -429,9 +421,9 @@ void PatchTextureBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info, } IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value& t, - const IR::Value& z, bool is_storage, bool is_array) { + const IR::Value& z, bool is_written, bool is_array) { // When cubemap is written with imageStore it is treated like 2DArray. - if (is_storage) { + if (is_written) { return ir.CompositeConstruct(s, t, z); } @@ -684,15 +676,16 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip image = AmdGpu::Image::Null(); } ASSERT(image.GetType() != AmdGpu::ImageType::Invalid); - const bool is_storage = IsImageStorageInstruction(inst); + const bool is_read = inst.GetOpcode() == IR::Opcode::ImageRead; + const bool is_written = inst.GetOpcode() == IR::Opcode::ImageWrite; // Patch image instruction if image is FMask. if (image.IsFmask()) { - ASSERT_MSG(!is_storage, "FMask storage instructions are not supported"); + ASSERT_MSG(!is_written, "FMask storage instructions are not supported"); IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; switch (inst.GetOpcode()) { - case IR::Opcode::ImageFetch: + case IR::Opcode::ImageRead: case IR::Opcode::ImageSampleRaw: { IR::F32 fmaskx = ir.BitCast(ir.Imm32(0x76543210)); IR::F32 fmasky = ir.BitCast(ir.Imm32(0xfedcba98)); @@ -721,10 +714,11 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip u32 image_binding = descriptors.Add(ImageResource{ .sharp_idx = tsharp, - .is_storage = is_storage, .is_depth = bool(inst_info.is_depth), .is_atomic = IsImageAtomicInstruction(inst), .is_array = bool(inst_info.is_array), + .is_read = is_read, + .is_written = is_written, }); // Sample instructions must be resolved into a new instruction using address register data. @@ -762,7 +756,7 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip case AmdGpu::ImageType::Color3D: // x, y, z, [lod] return {ir.CompositeConstruct(body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)}; case AmdGpu::ImageType::Cube: // x, y, face, [lod] - return {PatchCubeCoord(ir, body->Arg(0), body->Arg(1), body->Arg(2), is_storage, + return {PatchCubeCoord(ir, body->Arg(0), body->Arg(1), body->Arg(2), is_written, inst_info.is_array), body->Arg(3)}; default: @@ -772,19 +766,20 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip inst.SetArg(1, coords); if (inst.GetOpcode() == IR::Opcode::ImageWrite) { - inst.SetArg(3, SwizzleVector(ir, image, inst.Arg(3))); + inst.SetArg(4, SwizzleVector(ir, image, inst.Arg(4))); } if (inst_info.has_lod) { - ASSERT(inst.GetOpcode() == IR::Opcode::ImageFetch || - inst.GetOpcode() == IR::Opcode::ImageRead || + ASSERT(inst.GetOpcode() == IR::Opcode::ImageRead || inst.GetOpcode() == IR::Opcode::ImageWrite); ASSERT(image.GetType() != AmdGpu::ImageType::Color2DMsaa && image.GetType() != AmdGpu::ImageType::Color2DMsaaArray); inst.SetArg(2, arg); - } else if (image.GetType() == AmdGpu::ImageType::Color2DMsaa || - image.GetType() == AmdGpu::ImageType::Color2DMsaaArray) { - inst.SetArg(4, arg); + } else if ((image.GetType() == AmdGpu::ImageType::Color2DMsaa || + image.GetType() == AmdGpu::ImageType::Color2DMsaaArray) && + (inst.GetOpcode() == IR::Opcode::ImageRead || + inst.GetOpcode() == IR::Opcode::ImageWrite)) { + inst.SetArg(3, arg); } } diff --git a/src/shader_recompiler/specialization.h b/src/shader_recompiler/specialization.h index 5799c4c9..5bf97ee5 100644 --- a/src/shader_recompiler/specialization.h +++ b/src/shader_recompiler/specialization.h @@ -39,10 +39,12 @@ struct TextureBufferSpecialization { struct ImageSpecialization { AmdGpu::ImageType type = AmdGpu::ImageType::Color2D; bool is_integer = false; + bool is_storage = false; u32 dst_select = 0; bool operator==(const ImageSpecialization& other) const { return type == other.type && is_integer == other.is_integer && + is_storage == other.is_storage && (dst_select != 0 ? dst_select == other.dst_select : true); } }; @@ -114,7 +116,8 @@ struct StageSpecialization { [](auto& spec, const auto& desc, AmdGpu::Image sharp) { spec.type = sharp.GetBoundType(); spec.is_integer = AmdGpu::IsInteger(sharp.GetNumberFmt()); - if (desc.is_storage) { + spec.is_storage = desc.IsStorage(sharp); + if (spec.is_storage) { spec.dst_select = sharp.DstSelect(); } }); diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index a39b1837..71659c06 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -58,8 +58,9 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler for (const auto& image : info->images) { bindings.push_back({ .binding = binding++, - .descriptorType = image.is_storage ? vk::DescriptorType::eStorageImage - : vk::DescriptorType::eSampledImage, + .descriptorType = image.IsStorage(image.GetSharp(*info)) + ? vk::DescriptorType::eStorageImage + : vk::DescriptorType::eSampledImage, .descriptorCount = 1, .stageFlags = vk::ShaderStageFlagBits::eCompute, }); diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 265c7bd3..c01d4cbe 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -378,8 +378,9 @@ void GraphicsPipeline::BuildDescSetLayout() { for (const auto& image : stage->images) { bindings.push_back({ .binding = binding++, - .descriptorType = image.is_storage ? vk::DescriptorType::eStorageImage - : vk::DescriptorType::eSampledImage, + .descriptorType = image.IsStorage(image.GetSharp(*stage)) + ? vk::DescriptorType::eStorageImage + : vk::DescriptorType::eSampledImage, .descriptorCount = 1, .stageFlags = gp_stage_flags, }); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 55f86101..1e698bf6 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -655,7 +655,7 @@ void Rasterizer::BindTextures(const Shader::Info& stage, Shader::Backend::Bindin if (image->binding.is_bound) { // The image is already bound. In case if it is about to be used as storage we need // to force general layout on it. - image->binding.force_general |= image_desc.is_storage; + image->binding.force_general |= image_desc.IsStorage(tsharp); } if (image->binding.is_target) { // The image is already bound as target. Since we read and output to it need to force diff --git a/src/video_core/texture_cache/image_view.cpp b/src/video_core/texture_cache/image_view.cpp index ec1fda0d..9e67b7f7 100644 --- a/src/video_core/texture_cache/image_view.cpp +++ b/src/video_core/texture_cache/image_view.cpp @@ -51,7 +51,7 @@ vk::ComponentSwizzle ConvertComponentSwizzle(u32 dst_sel) { } ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept - : is_storage{desc.is_storage} { + : is_storage{desc.IsStorage(image)} { const auto dfmt = image.GetDataFmt(); auto nfmt = image.GetNumberFmt(); if (is_storage && nfmt == AmdGpu::NumberFormat::Srgb) { diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 430415ed..944f021d 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -65,7 +65,7 @@ public: struct TextureDesc : public BaseDesc { TextureDesc() = default; TextureDesc(const AmdGpu::Image& image, const Shader::ImageResource& desc) - : BaseDesc{desc.is_storage ? BindingType::Storage : BindingType::Texture, + : BaseDesc{desc.IsStorage(image) ? BindingType::Storage : BindingType::Texture, ImageInfo{image, desc}, ImageViewInfo{image, desc}} {} };