From 8d96b2e894a6c17127f66aaa1652a1e0d4807903 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Fri, 17 Jul 2026 20:15:19 -0400 Subject: [PATCH] [TEST] Caching for texture + pages on NCE (cherry picked from commit 9c313fb787a93d59f351879ec44a80db854ce330) --- src/core/device_memory_manager.h | 5 ++++ src/core/device_memory_manager.inc | 23 +++++++++++++++++++ .../renderer_vulkan/vk_rasterizer.cpp | 5 +++- src/video_core/texture_cache/texture_cache.h | 5 ++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/core/device_memory_manager.h b/src/core/device_memory_manager.h index 3d97fdcc5c..a66ca4aaae 100644 --- a/src/core/device_memory_manager.h +++ b/src/core/device_memory_manager.h @@ -126,6 +126,10 @@ public: // New batch API to update multiple ranges with a single lock acquisition. void UpdatePagesCachedBatch(std::span> ranges, s32 delta); + void UpdateTexturePagesCount(DAddr addr, size_t size, s32 delta); + + [[nodiscard]] bool IsRegionTextureCached(DAddr addr, size_t size) const noexcept; + private: struct TranslationEntry { DAddr guest_page{}; @@ -234,6 +238,7 @@ private: (1ULL << (device_virtual_bits - page_bits)) / subentries; using CachedPages = std::array; std::unique_ptr cached_pages; + std::unique_ptr texture_cached_pages; Common::RangeMutex counter_guard; std::mutex mapping_guard; diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc index 43a480cfef..15e52b1511 100644 --- a/src/core/device_memory_manager.inc +++ b/src/core/device_memory_manager.inc @@ -177,6 +177,7 @@ DeviceMemoryManager::DeviceMemoryManager(const DeviceMemory& device_memo { impl = std::make_unique>(); cached_pages = std::make_unique(); + texture_cached_pages = std::make_unique(); const size_t total_virtual = device_as_size >> Memory::YUZU_PAGEBITS; for (size_t i = 0; i < total_virtual; i++) { @@ -625,6 +626,28 @@ void DeviceMemoryManager::UpdatePagesCachedCount(DAddr addr, size_t size UpdatePagesCachedCountNoLock(addr, size, delta); } +template +void DeviceMemoryManager::UpdateTexturePagesCount(DAddr addr, size_t size, s32 delta) { + Common::ScopedRangeLock lk(counter_guard, addr, size); + const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE); + for (size_t page = addr >> Memory::YUZU_PAGEBITS; page != page_end; ++page) { + CounterAtomicType& count = texture_cached_pages->at(page >> subentries_shift).Count(page); + count.fetch_add(static_cast(delta), std::memory_order_release); + } +} + +template +bool DeviceMemoryManager::IsRegionTextureCached(DAddr addr, size_t size) const noexcept { + const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE); + for (size_t page = addr >> Memory::YUZU_PAGEBITS; page != page_end; ++page) { + if (texture_cached_pages->at(page >> subentries_shift).Count(page).load( + std::memory_order_acquire) != 0) { + return true; + } + } + return false; +} + template void DeviceMemoryManager::UpdatePagesCachedBatch(std::span> ranges, s32 delta) { if (ranges.empty()) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 6d9eed9d2e..c5ceebf6cb 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -772,12 +772,15 @@ bool RasterizerVulkan::OnCPUWrite(DAddr addr, u64 size) { return false; } +static constexpr bool ENABLE_TEXTURE_CACHE_INVALIDATION_SKIP = true; + void RasterizerVulkan::OnCacheInvalidation(DAddr addr, u64 size) { if (addr == 0 || size == 0) { return; } - { + if (!ENABLE_TEXTURE_CACHE_INVALIDATION_SKIP || + device_memory.IsRegionTextureCached(addr, size)) { std::scoped_lock lock{texture_cache.mutex}; texture_cache.WriteMemory(addr, size); } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 2cfdb94359..1989511dd4 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -2308,6 +2308,7 @@ void TextureCache

::TrackImage(ImageBase& image, ImageId image_id) { if (False(image.flags & ImageFlagBits::Sparse)) { if (image.cpu_addr < ~(1ULL << 40)) { device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1); + device_memory.UpdateTexturePagesCount(image.cpu_addr, image.guest_size_bytes, 1); } return; } @@ -2320,12 +2321,14 @@ void TextureCache

::TrackImage(ImageBase& image, ImageId image_id) { const DAddr cpu_addr = map.cpu_addr; const std::size_t size = map.size; device_memory.UpdatePagesCachedCount(cpu_addr, size, 1); + device_memory.UpdateTexturePagesCount(cpu_addr, size, 1); } return; } ForEachSparseSegment(image, [this]([[maybe_unused]] GPUVAddr gpu_addr, DAddr cpu_addr, size_t size) { device_memory.UpdatePagesCachedCount(cpu_addr, size, 1); + device_memory.UpdateTexturePagesCount(cpu_addr, size, 1); }); } @@ -2336,6 +2339,7 @@ void TextureCache

::UntrackImage(ImageBase& image, ImageId image_id) { if (False(image.flags & ImageFlagBits::Sparse)) { if (image.cpu_addr < ~(1ULL << 40)) { device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1); + device_memory.UpdateTexturePagesCount(image.cpu_addr, image.guest_size_bytes, -1); } return; } @@ -2348,6 +2352,7 @@ void TextureCache

::UntrackImage(ImageBase& image, ImageId image_id) { const DAddr cpu_addr = map.cpu_addr; const std::size_t size = map.size; device_memory.UpdatePagesCachedCount(cpu_addr, size, -1); + device_memory.UpdateTexturePagesCount(cpu_addr, size, -1); } }