From 27bcaba75cd9e98f63bb470f97915776a64d00e8 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Thu, 17 Sep 2026 06:12:25 -0400 Subject: [PATCH] first intent to pinpoint performance decrease on virtual buffer table + multi-range --- .../buffer_cache/virtual_range_cache.h | 91 ++----------------- 1 file changed, 10 insertions(+), 81 deletions(-) diff --git a/src/video_core/buffer_cache/virtual_range_cache.h b/src/video_core/buffer_cache/virtual_range_cache.h index f4284d6abb..378df18656 100644 --- a/src/video_core/buffer_cache/virtual_range_cache.h +++ b/src/video_core/buffer_cache/virtual_range_cache.h @@ -5,9 +5,7 @@ #include #include -#include #include -#include #include @@ -28,23 +26,22 @@ using VirtualSegments = boost::container::small_vector; class VirtualRangeCache { public: static constexpr size_t MAX_ENTRIES = 8192; - static constexpr size_t MAX_DEFERRED = 4096; const VirtualSegments* Query(Tegra::MemoryManager& memory, GPUVAddr gpu_addr, u32 size) { - if (has_deferred.load(std::memory_order_acquire)) { - ApplyDeferred(); - } + const u64 current = generation.load(std::memory_order_acquire); if (entries.size() > MAX_ENTRIES) { entries.clear(); } const size_t as_id = memory.GetID(); const u64 key = MakeKey(as_id, gpu_addr); const auto it = entries.find(key); - if (it != entries.end() && it->second.as_id == as_id && - it->second.gpu_addr == gpu_addr && it->second.size == size) { + if (it != entries.end() && it->second.generation == current && + it->second.as_id == as_id && it->second.gpu_addr == gpu_addr && + it->second.size == size) { return &it->second.segments; } Entry entry{}; + entry.generation = current; entry.as_id = as_id; entry.gpu_addr = gpu_addr; entry.size = size; @@ -79,95 +76,27 @@ public: return &result.first->second.segments; } - void Unmap(size_t as_id, GPUVAddr gpu_addr, u64 size) { - if (size == 0) { - return; + void Unmap(size_t, GPUVAddr, u64 size) { + if (size != 0) { + generation.fetch_add(1, std::memory_order_release); } - { - std::scoped_lock lock{deferred_mutex}; - if (!deferred.empty()) { - DeferredUnmap& last = deferred.back(); - if (last.as_id == as_id && last.gpu_addr + last.size == gpu_addr) { - last.size += size; - has_deferred.store(true, std::memory_order_release); - return; - } - } - if (deferred.size() >= MAX_DEFERRED) { - deferred.clear(); - deferred_overflow = true; - } else { - deferred.push_back(DeferredUnmap{ - .as_id = as_id, - .gpu_addr = gpu_addr, - .size = size, - }); - } - } - has_deferred.store(true, std::memory_order_release); } private: struct Entry { VirtualSegments segments; + u64 generation{}; size_t as_id{}; GPUVAddr gpu_addr{}; u32 size{}; }; - struct DeferredUnmap { - size_t as_id; - GPUVAddr gpu_addr; - u64 size; - }; - static u64 MakeKey(size_t as_id, GPUVAddr gpu_addr) { return (static_cast(as_id) << 48) ^ gpu_addr; } - void ApplyDeferred() { - std::vector pending; - bool overflow = false; - { - std::scoped_lock lock{deferred_mutex}; - has_deferred.store(false, std::memory_order_release); - pending.swap(deferred); - overflow = deferred_overflow; - deferred_overflow = false; - } - if (overflow) { - entries.clear(); - return; - } - if (pending.empty() || entries.empty()) { - return; - } - for (auto it = entries.begin(); it != entries.end();) { - const Entry& entry = it->second; - const GPUVAddr entry_end = entry.gpu_addr + entry.size; - bool overlaps = false; - for (const DeferredUnmap& unmap : pending) { - if (unmap.as_id != entry.as_id) { - continue; - } - if (entry.gpu_addr < unmap.gpu_addr + unmap.size && unmap.gpu_addr < entry_end) { - overlaps = true; - break; - } - } - if (overlaps) { - it = entries.erase(it); - } else { - ++it; - } - } - } - ::Common::unordered_map entries; - std::vector deferred; - std::mutex deferred_mutex; - std::atomic has_deferred{false}; - bool deferred_overflow{}; + std::atomic generation{}; }; } // namespace VideoCommon