Keep huge ASTC arrays from a lower mip on the host (title 1 terrain)

Title 1's terrain virtual textures are 8192x8192x68 ASTC 8x8 sRGB arrays with
12 levels: 1.5 GB in guest memory (fully backed) but 23 GB each as the RGBA8
Eden decodes ASTC to, so they were created unbacked and the near terrain
sampled black. A GPU-decoded ASTC 2D array over 1 GiB decoded now keeps only
the levels from the first one that fits in 512 MiB (here 3: 1024x1024, 380
MiB); host mip 0 is that guest level. Uploads read each layer's tail of the
mip chain into a compact buffer and decode only those levels, views shift
their level range, and these images are never downloaded. Normalized
coordinates and derivative LOD address the smaller image correctly; the
nearest terrain is lower resolution than on the console.

Also logs how unbacked images are used (views, render targets, blits, DMA).
This commit is contained in:
Takoroka 2026-10-28 15:37:34 -04:00
commit b8a07d6d5b

View file

@ -1298,6 +1298,13 @@ void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase*
}
u32 MapSizeBytes(const ImageBase& image) {
if (True(image.flags & ImageFlagBits::AcceleratedUpload) && image.host_level_offset != 0) {
// Each layer's mip chain from host_level_offset on (see UploadImageContents).
const auto uploads = FullUploadSwizzles(image.info);
const u32 tail = image.info.layer_stride -
static_cast<u32>(uploads[image.host_level_offset].buffer_offset);
return tail * image.info.resources.layers;
}
if (True(image.flags & ImageFlagBits::AcceleratedUpload)) {
return image.guest_size_bytes;
} else if (True(image.flags & ImageFlagBits::Converted)) {