From 2ad5390c912fed34a6ef5d0eda7c35f94e012fd0 Mon Sep 17 00:00:00 2001 From: xbzk Date: Sun, 15 Feb 2026 23:30:57 -0300 Subject: [PATCH] QueryCacheBase::CounterReport (endermag flicker fix) --- src/video_core/dma_pusher.cpp | 2 +- src/video_core/query_cache/query_cache.h | 40 +++++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp index d9c388ae41..244463e470 100644 --- a/src/video_core/dma_pusher.cpp +++ b/src/video_core/dma_pusher.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project diff --git a/src/video_core/query_cache/query_cache.h b/src/video_core/query_cache/query_cache.h index 3aeeb8dcab..98e78c18de 100644 --- a/src/video_core/query_cache/query_cache.h +++ b/src/video_core/query_cache/query_cache.h @@ -168,7 +168,9 @@ struct QueryCacheBase::QueryCacheBaseImpl { std::array(QueryType::MaxQueryTypes)> streamers; u64 streamer_mask; std::mutex flush_guard; + bool force_flush_uncommitted{}; std::deque flushes_pending; + std::deque force_flushes_pending; std::vector::QueryLocation> pending_unregister; }; @@ -246,6 +248,30 @@ void QueryCacheBase::CounterReport(GPUVAddr addr, QueryType counter_type return; } DAddr cpu_addr = *cpu_addr_opt; + + if (is_fence && counter_type == QueryType::Payload) { + u8* pointer = impl->device_memory.template GetPointer(cpu_addr); + u8* pointer_timestamp = impl->device_memory.template GetPointer(cpu_addr + 8); + std::function operation([this, has_timestamp, payload, pointer, pointer_timestamp] { + if (has_timestamp) { + const u64 timestamp = impl->gpu.GetTicks(); + const u64 value = static_cast(payload); + std::memcpy(pointer_timestamp, ×tamp, sizeof(timestamp)); + std::memcpy(pointer, &value, sizeof(value)); + } else { + std::memcpy(pointer, &payload, sizeof(payload)); + } + }); + impl->rasterizer.SyncOperation(std::move(operation)); + { + std::scoped_lock lk(impl->flush_guard); + impl->force_flush_uncommitted = true; + } + std::function noop([] {}); + impl->rasterizer.SignalFence(std::move(noop)); + return; + } + const size_t new_query_id = streamer->WriteCounter(cpu_addr, has_timestamp, payload, subreport); auto* query = streamer->GetQuery(new_query_id); if (is_fence) { @@ -473,6 +499,8 @@ void QueryCacheBase::CommitAsyncFlushes() { } }); impl->flushes_pending.push_back(mask); + impl->force_flushes_pending.push_back(impl->force_flush_uncommitted); + impl->force_flush_uncommitted = false; } std::function func([this] { UnregisterPending(); }); impl->rasterizer.SyncOperation(std::move(func)); @@ -496,6 +524,12 @@ void QueryCacheBase::CommitAsyncFlushes() { template bool QueryCacheBase::HasUncommittedFlushes() const { + { + std::scoped_lock lk(impl->flush_guard); + if (impl->force_flush_uncommitted) { + return true; + } + } bool result = false; impl->ForEachStreamer([&result](StreamerInterface* streamer) { result |= streamer->HasUnsyncedQueries(); @@ -507,7 +541,10 @@ bool QueryCacheBase::HasUncommittedFlushes() const { template bool QueryCacheBase::ShouldWaitAsyncFlushes() { std::scoped_lock lk(impl->flush_guard); - return !impl->flushes_pending.empty() && impl->flushes_pending.front() != 0ULL; + if (impl->flushes_pending.empty()) { + return false; + } + return impl->flushes_pending.front() != 0ULL || impl->force_flushes_pending.front(); } template @@ -517,6 +554,7 @@ void QueryCacheBase::PopAsyncFlushes() { std::scoped_lock lk(impl->flush_guard); mask = impl->flushes_pending.front(); impl->flushes_pending.pop_front(); + impl->force_flushes_pending.pop_front(); } if (mask == 0) { return;