From f0d1bbff79e933ffcdf466ed6286b0cba5b71dfb Mon Sep 17 00:00:00 2001 From: Takoroka <137927095+Takoroka@users.noreply.github.com> Date: Fri, 30 Oct 2026 04:39:39 -0400 Subject: vk_texture_cache: trim huge ASTC arrays harder on small GPUs A trimmed ASTC array kept up to 512 MiB on the host. On GPUs with less than 7 GiB it now keeps up to 256 MiB (one mip level less): Mario Kart World's two terrain arrays took 724 MiB of a 6 GB card next to ~1.2 GB of other sparse terrain textures. EDEN_NX2_ASTC_ARRAY_MIB= sets the limit. --- src/video_core/renderer_vulkan/vk_texture_cache.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index f5fcdd1380..b6b7e686f9 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -219,6 +219,20 @@ constexpr std::array OpaqueAstcViewFormats{VK_FORMAT_BC1_RGBA_UNORM info.size.depth == 1; } +// The most a trimmed ASTC array keeps on the host: 512 MiB, 256 MiB on GPUs with less than 7 GiB +// (title 1's two terrain arrays took 724 MiB of a 6 GB card next to ~1.2 GB of other sparse terrain +// textures). EDEN_NX2_ASTC_ARRAY_MIB= sets it. +[[nodiscard]] u64 TrimmedAstcArrayLimit(const Device& device) { + static const u64 forced = [] { + const char* value = std::getenv("EDEN_NX2_ASTC_ARRAY_MIB"); + return value != nullptr ? std::strtoull(value, nullptr, 10) << 20 : 0ULL; + }(); + if (forced != 0) { + return forced; + } + return device.GetDeviceLocalMemory() < (u64{7} << 30) ? (u64{256} << 20) : (u64{512} << 20); +} + // The host shape of an image whose decoded copy would not fit in VRAM: a GPU-decoded ASTC array // over 1 GiB as RGBA8 (title 1's 8192x8192x68 ASTC 8x8 virtual textures are 24 GB each) keeps only // its mip levels from `level_offset` on, so host mip 0 is guest mip `level_offset`. Normalized @@ -239,8 +253,9 @@ constexpr std::array OpaqueAstcViewFormats{VK_FORMAT_BC1_RGBA_UNORM if (decoded_bytes(0) <= (u64{1} << 30)) { return info; } + const u64 limit = TrimmedAstcArrayLimit(device); while (level_offset + 1 < static_cast(info.resources.levels) && - decoded_bytes(level_offset) > (u64{512} << 20)) { + decoded_bytes(level_offset) > limit) { ++level_offset; } ImageInfo host = info; -- cgit v1.2.3