texture_cache: Improve handling of mips of compressed views (#4553)

* texture_cache: Improve handling of mips of compressed views

* image: Restore storage bit to compressed formats.
This commit is contained in:
squidbus 2026-06-14 03:05:50 -07:00 committed by GitHub
parent 7ea310f825
commit d3dc14ab91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 16 deletions

View File

@ -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);

View File

@ -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;
}