From 08878385e1c024af7ffddf5a22037d24a7984fd8 Mon Sep 17 00:00:00 2001 From: TheTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Sat, 4 Oct 2025 23:09:40 +0300 Subject: [PATCH] image_info: Fix guest size calculation for linear render targets (#3700) --- src/video_core/texture_cache/image_info.cpp | 25 +++++++++++++------ .../texture_cache/texture_cache.cpp | 3 +++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 0e1f10bfe..9d5801440 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -72,9 +72,15 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, meta_info.fmask_addr = buffer.info.compression ? buffer.FmaskAddress() : 0; guest_address = buffer.Address(); - const auto color_slice_sz = buffer.GetColorSliceSize(); - guest_size = color_slice_sz * buffer.NumSlices(); - mips_layout.emplace_back(guest_size, pitch, buffer.Height(), 0); + if (props.is_tiled) { + guest_size = buffer.GetColorSliceSize() * resources.layers; + mips_layout.emplace_back(guest_size, pitch, buffer.Height(), 0); + } else { + std::tie(std::ignore, std::ignore, guest_size) = + ImageSizeLinearAligned(pitch, size.height, num_bits, num_samples); + guest_size *= resources.layers; + mips_layout.emplace_back(guest_size, pitch, size.height, 0); + } alt_tile = Libraries::Kernel::sceKernelIsNeoMode() && buffer.info.alt_tile_mode; } @@ -102,9 +108,15 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, u32 num_slice stencil_size = pitch * size.height * sizeof(u8); guest_address = write_buffer ? buffer.DepthWriteAddress() : buffer.DepthAddress(); - const auto depth_slice_sz = buffer.GetDepthSliceSize(); - guest_size = depth_slice_sz * num_slices; - mips_layout.emplace_back(guest_size, pitch, buffer.Height(), 0); + if (props.is_tiled) { + guest_size = buffer.GetDepthSliceSize() * resources.layers; + mips_layout.emplace_back(guest_size, pitch, buffer.Height(), 0); + } else { + std::tie(std::ignore, std::ignore, guest_size) = + ImageSizeLinearAligned(pitch, size.height, num_bits, num_samples); + guest_size *= resources.layers; + mips_layout.emplace_back(guest_size, pitch, size.height, 0); + } } ImageInfo::ImageInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept { @@ -164,7 +176,6 @@ void ImageInfo::UpdateSize() { } switch (array_mode) { - case AmdGpu::ArrayMode::ArrayLinearGeneral: case AmdGpu::ArrayMode::ArrayLinearAligned: { std::tie(mip_info.pitch, mip_info.height, mip_info.size) = ImageSizeLinearAligned(mip_w, mip_h, num_bits, num_samples); diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 41c1ea09a..a878352a8 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -575,6 +575,9 @@ ImageView& TextureCache::FindTexture(ImageId image_id, const BaseDesc& desc) { ImageView& TextureCache::FindRenderTarget(ImageId image_id, const BaseDesc& desc) { Image& image = slot_images[image_id]; image.flags |= ImageFlagBits::GpuModified; + if (Config::readbackLinearImages() && !image.info.props.is_tiled) { + download_images.emplace(image_id); + } image.usage.render_target = 1u; UpdateImage(image_id);