From 0d5534a2883329183ae8aa89b3fe1c7b67291ece Mon Sep 17 00:00:00 2001 From: Takoroka <137927095+Takoroka@users.noreply.github.com> Date: Wed, 28 Oct 2026 20:43:01 -0400 Subject: ASTC: decode and re-compress to BC1/BC3 on the GPU; texture cache budget - accelerate_astc=Gpu with astc_recompression=Bc1/Bc3 now decodes ASTC with the GPU decoder into a temporary RGBA8 image (dedicated memory, freed once the GPU is past it) and compresses it with a new compute shader (bc_encoder.comp: bounding-box endpoints along the colours' covariance, inset 1/16, nearest palette entry; BC3 alpha ramp; BC1 punch-through), then copies the blocks into the image. No CPU decode, so streamed textures are ready the frame they are first used instead of showing placeholders for seconds; the decode pass no longer waits for the GPU on this path. - The CPU path (CpuAsynchronous) fills a new image with zero blocks before its first decode instead of showing stale VRAM, and the transcode pool is a quarter of the hardware threads. - Switch 2 titles: collector thresholds near the device budget, re-read every 60 frames from VK_EXT_memory_budget (another game shrank it from 7.0 to 5.4 GB). - EDEN_NX2_HIDE_WINDOW=0 now leaves the window visible. --- src/video_core/vulkan_common/vulkan_device.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/video_core/vulkan_common/vulkan_device.cpp') diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index be09bca8d3..454e5d4e02 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -1612,6 +1612,20 @@ u64 Device::GetDeviceMemoryUsage() const { return result; } +u64 Device::GetDeviceMemoryBudget() const { + if (!extensions.memory_budget) { + return 0; + } + VkPhysicalDeviceMemoryBudgetPropertiesEXT budget{}; + budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT; + physical.GetMemoryProperties(&budget); + u64 result{}; + for (const size_t heap : valid_heap_memory) { + result += budget.heapBudget[heap]; + } + return result; +} + void Device::CollectPhysicalMemoryInfo() { // Calculate limits using memory budget VkPhysicalDeviceMemoryBudgetPropertiesEXT budget{}; -- cgit v1.2.3 From d294001f414944ef668f867b9e82c95ccdcb7340 Mon Sep 17 00:00:00 2001 From: Takoroka <137927095+Takoroka@users.noreply.github.com> Date: Wed, 28 Oct 2026 23:46:53 -0400 Subject: vulkan: 64 MiB VMA blocks; device memory usage without VMA block slack Title 1's texture cache deleted 1,400-2,600 textures per 600 frames and created them again: device memory sat at the collector's critical line, but ~38% of it was empty space in 256 MiB VMA blocks. Freeing an image returns that space only once its whole block is empty, so the caches kept collecting without the usage dropping (one mass purge deleted 4,300 textures). - 64 MiB blocks on discrete GPUs too (as on integrated ones). - GetDeviceMemoryUsage subtracts the unused bytes in VMA blocks, so each eviction counts at once. Now 0-224 deletions per 600 frames, ~4,400 textures resident, and driver usage 6.24 GB of a 6.97 GB budget. --- src/video_core/vulkan_common/vulkan_device.cpp | 21 ++++++++++++++++++--- src/video_core/vulkan_common/vulkan_device.h | 2 +- 2 files changed, 19 insertions(+), 4 deletions(-) (limited to 'src/video_core/vulkan_common/vulkan_device.cpp') diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 454e5d4e02..69c3ba14fa 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -5,6 +5,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include #include #include @@ -752,9 +753,10 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR .flags = flags, .physicalDevice = physical, .device = *logical, - .preferredLargeHeapBlockSize = is_integrated - ? (64u * 1024u * 1024u) - : (256u * 1024u * 1024u), + // 64 MiB blocks on discrete GPUs too: with 256 MiB ones, Switch 2 titles' mix of + // texture sizes left ~38% of the image blocks empty (2 GB of an 8 GB card in title + // 1), which the texture cache counted as used and kept evicting textures for. + .preferredLargeHeapBlockSize = 64u * 1024u * 1024u, .pAllocationCallbacks = nullptr, .pDeviceMemoryCallbacks = nullptr, .pHeapSizeLimit = nullptr, @@ -1609,6 +1611,19 @@ u64 Device::GetDeviceMemoryUsage() const { for (const size_t heap : valid_heap_memory) { result += budget.heapUsage[heap]; } + // Space in VMA's blocks that no allocation uses counts as used, but freeing an image gives + // its share back only once its whole block is empty: the caches, collecting until this drops, + // evicted thousands of textures in a row without lowering it (title 1). Count only what + // allocations use. + if (allocator != nullptr) { + std::array heap_budgets{}; + vmaGetHeapBudgets(allocator, heap_budgets.data()); + for (const size_t heap : valid_heap_memory) { + const VmaStatistics& statistics = heap_budgets[heap].statistics; + const u64 unused = statistics.blockBytes - statistics.allocationBytes; + result -= (std::min)(result, unused); + } + } return result; } diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 34ee63a275..b1fa8db183 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -1148,7 +1148,7 @@ private: private: VkInstance instance; ///< Vulkan instance. - VmaAllocator allocator; ///< VMA allocator. + VmaAllocator allocator{}; ///< VMA allocator. vk::DeviceDispatch dld; ///< Device function pointers. vk::PhysicalDevice physical; ///< Physical device. vk::Device logical; ///< Logical device. -- cgit v1.2.3