From e7cc2cea290280e519ce011049063a9e40e7cc9c Mon Sep 17 00:00:00 2001 From: Takoroka <137927095+Takoroka@users.noreply.github.com> Date: Wed, 28 Oct 2026 14:31:00 -0400 Subject: Cache rejected native shaders and log each rejection once A rejected program was lowered again (and logged) on every draw or dispatch: 1.7M log lines in 13 minutes of title 1. The shader cache keeps the first exception per address until guest memory there is written, and the error logs are deduplicated. --- src/video_core/shader_cache.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (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 1f826313a1..f92fe02068 100644 --- a/src/video_core/shader_cache.cpp +++ b/src/video_core/shader_cache.cpp @@ -5,6 +5,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include +#include #include #include #include @@ -91,7 +93,11 @@ bool ShaderCache::RefreshStages(std::array& unique_hashes) try { if (!native.native_turing) throw; native.native_execution_failed = true; last_shaders_valid = false; - LOG_ERROR(HW_GPU, "Native graphics shader rejected: {}", error.what()); + // Each rejected program is logged once (the draws that use it keep failing quietly). + static std::unordered_set logged; + if (logged.insert(error.what()).second) { + LOG_ERROR(HW_GPU, "Native graphics shader rejected: {}", error.what()); + } // Once: show what the vertex stage has bound, to find where an unbound bank's data lives. static std::vector dumped_errors; if (const std::string what{error.what()}; @@ -177,6 +183,12 @@ 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; + { + std::scoped_lock lock{rejected_mutex}; + boost::unordered::erase_if(rejected_native, [&](const auto& rejected) { + return rejected.first >= addr && rejected.first < addr_end; + }); + } const u64 page_end = (addr_end + YUZU_PAGESIZE - 1) >> YUZU_PAGEBITS; for (u64 page = addr >> YUZU_PAGEBITS; page < page_end; ++page) { auto it = invalidation_cache.find(page); @@ -262,8 +274,22 @@ ShaderCache::Entry* ShaderCache::NewEntry(VAddr addr, VAddr addr_end, ShaderInfo } const ShaderInfo* ShaderCache::MakeShaderInfo(GenericEnvironment& env, VAddr cpu_addr) { + { + std::scoped_lock lock{rejected_mutex}; + if (const auto it = rejected_native.find(cpu_addr); it != rejected_native.end()) { + std::rethrow_exception(it->second); + } + } auto info = std::make_unique(); - if (const std::optional cached_hash{env.Analyze()}) { + std::optional analyzed; + try { + analyzed = env.Analyze(); + } catch (const Shader::Exception&) { + std::scoped_lock lock{rejected_mutex}; + rejected_native.emplace(cpu_addr, std::current_exception()); + throw; + } + if (const std::optional cached_hash{analyzed}) { info->unique_hash = *cached_hash; info->size_bytes = env.CachedSizeBytes(); } else { -- cgit v1.2.3