From d56a30137df183de548ac49151ddeeecc1ab0f16 Mon Sep 17 00:00:00 2001 From: Takoroka <137927095+Takoroka@users.noreply.github.com> Date: Thu, 29 Oct 2026 00:45:20 -0400 Subject: nx2: memo for compute macros; one lock per inline upload; cheaper shader invalidation - Compute engine macros replay repeated calls like 3D ones (title 1's compute macro path fell from ~27% to ~14% of the GPU thread). - AccelerateInlineToMemory takes the buffer and texture cache mutexes together instead of one after the other. - ShaderCache::InvalidatePagesInRegion looks at the rejected programs only when the write can reach one (bounds kept as they are added); it ran a locked scan for every inline upload and pre-draw invalidation. Inline uploads went from ~10% to ~4% of the GPU thread. --- src/video_core/shader_cache.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/video_core/shader_cache.cpp') diff --git a/src/video_core/shader_cache.cpp b/src/video_core/shader_cache.cpp index 73a2bf6646..dfe80abac3 100644 --- a/src/video_core/shader_cache.cpp +++ b/src/video_core/shader_cache.cpp @@ -180,6 +180,10 @@ bool ShaderCache::IsRejected(VAddr addr) { void ShaderCache::RememberRejection(VAddr addr) { std::scoped_lock lock{rejected_mutex}; rejected_native.emplace(addr, std::current_exception()); + rejected_lowest.store((std::min)(rejected_lowest.load(std::memory_order_relaxed), addr), + std::memory_order_relaxed); + rejected_highest.store((std::max)(rejected_highest.load(std::memory_order_relaxed), addr), + std::memory_order_relaxed); } void ShaderCache::GetGraphicsEnvironments(GraphicsEnvironments& result, @@ -232,7 +236,10 @@ void ShaderCache::Register(std::unique_ptr data, VAddr addr, size_t void ShaderCache::InvalidatePagesInRegion(VAddr addr, size_t size) { const VAddr addr_end = addr + size; - { + // Rejected programs are few and in a few places: look at them only for writes that can + // reach them (this runs for every inline upload and pre-draw invalidation). + if (addr_end > rejected_lowest.load(std::memory_order_relaxed) && + addr <= rejected_highest.load(std::memory_order_relaxed)) { std::scoped_lock lock{rejected_mutex}; boost::unordered::erase_if(rejected_native, [&](const auto& rejected) { return rejected.first >= addr && rejected.first < addr_end; -- cgit v1.2.3