diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index 8f89d84f3..1cd6992df 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -35,6 +35,11 @@ static vk::ImageUsageFlags ImageUsageFlags(const Vulkan::Instance* instance, // flag is also used. usage |= vk::ImageUsageFlagBits::eStorage; } + } else { + // Similarly to above, we specify storage usage. This is typically not supported by + // compressed formats, but may be used for uncompressed views. In order to satisfy this, + // we will also specify the extended usage bit. + usage |= vk::ImageUsageFlagBits::eStorage; } return usage; @@ -667,13 +672,14 @@ void Image::CopyImageWithBuffer(Image& src_image, vk::Buffer buffer, u64 offset) void Image::CopyMip(Image& src_image, u32 mip, u32 slice) { const auto& src_info = src_image.info; - const auto mip_w = std::max(info.size.width >> mip, 1u); - const auto mip_h = std::max(info.size.height >> mip, 1u); - const auto mip_d = std::max(info.size.depth >> mip, 1u); - const auto [src_layers, dst_layers] = SanitizeCopyLayers(src_info, info, mip_d); + const auto src_block_dim = src_info.BlockDim(); + const auto dst_block_dim = info.BlockDim(); + const auto mip_block_w = std::max(dst_block_dim.width >> mip, 1u); + const auto mip_block_h = std::max(dst_block_dim.height >> mip, 1u); + ASSERT(mip_block_w == src_block_dim.width); + ASSERT(mip_block_h == src_block_dim.height); - ASSERT(mip_w == src_info.size.width); - ASSERT(mip_h == src_info.size.height); + const auto [src_layers, dst_layers] = SanitizeCopyLayers(src_info, info, src_info.size.depth); const vk::ImageCopy image_copy{ .srcSubresource{ @@ -688,7 +694,7 @@ void Image::CopyMip(Image& src_image, u32 mip, u32 slice) { .baseArrayLayer = slice, .layerCount = dst_layers, }, - .extent = {mip_w, mip_h, mip_d}, + .extent = {src_info.size.width, src_info.size.height, src_info.size.depth}, }; SetBackingSamples(info.num_samples); diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index b0b272e2f..85c93f532 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -6,6 +6,7 @@ #include "core/libraries/videoout/buffer.h" #include "shader_recompiler/resource.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" +#include "video_core/texture_cache/host_compatibility.h" #include "video_core/texture_cache/image_info.h" #include "video_core/texture_cache/tile.h" @@ -146,8 +147,9 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image, const Shader::ImageResource& de } bool ImageInfo::IsCompatible(const ImageInfo& info) const { - return (pixel_format == info.pixel_format && num_samples == info.num_samples && - num_bits == info.num_bits); + return (IsVulkanFormatCompatible(pixel_format, info.pixel_format) || + IsVulkanFormatCompatible(info.pixel_format, pixel_format)) && + num_samples == info.num_samples && num_bits == info.num_bits; } void ImageInfo::UpdateSize() { @@ -242,9 +244,13 @@ s32 ImageInfo::MipOf(const ImageInfo& info) const { return -1; } - const auto mip_w = std::max(info.size.width >> mip, 1u); - const auto mip_h = std::max(info.size.height >> mip, 1u); - if ((size.width != mip_w) || (size.height != mip_h)) { + const auto curr_block_dim = BlockDim(); + const auto info_block_dim = info.BlockDim(); + + // 2D block dimensions of both images should be the same. + const auto mip_w = std::max(info_block_dim.width >> mip, 1u); + const auto mip_h = std::max(info_block_dim.height >> mip, 1u); + if ((curr_block_dim.width != mip_w) || (curr_block_dim.height != mip_h)) { return -1; } @@ -273,10 +279,13 @@ s32 ImageInfo::SliceOf(const ImageInfo& info, s32 mip) const { return -1; } - // 2D dimensions of both images should be the same. - const auto mip_w = std::max(info.size.width >> mip, 1u); - const auto mip_h = std::max(info.size.height >> mip, 1u); - if ((size.width != mip_w) || (size.height != mip_h)) { + const auto curr_block_dim = BlockDim(); + const auto info_block_dim = info.BlockDim(); + + // 2D block dimensions of both images should be the same. + const auto mip_w = std::max(info_block_dim.width >> mip, 1u); + const auto mip_h = std::max(info_block_dim.height >> mip, 1u); + if ((curr_block_dim.width != mip_w) || (curr_block_dim.height != mip_h)) { return -1; }