aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/query_cache/query_cache.h
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 05:41:45 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 05:41:45 -0400
commitcff4add442d78e088d13005c4c6fdd436b47eecd (patch)
treec4bcb200d58b5c1f70ebcd9449597a987ad2e6e8 /src/video_core/query_cache/query_cache.h
parent5c4e642c286279f3e44d476550736ed6bff400ab (diff)
nx2: semaphore releases latch the acquires they satisfy
Switch 2 channels that wait for an exact semaphore value poll on the console and see every release. Eden resumes a waiting channel only between command lists and writes releases when fences signal, often several back to back, so an acquire-equal could miss its value and wait forever. Title 4's 3D queue ticks a counter that two other queues wait on value by value; under the loading after the post-customization save one of them missed a tick and the game froze (channel 4 waiting for 0x5293 with the counter at 0x5310). Pending acquires now register with Nx2SemaphoreWaiters before fences run, and every query-cache payload write and QMD add/max release latches the waiters it meets at the moment it is written.
Diffstat (limited to 'src/video_core/query_cache/query_cache.h')
-rw-r--r--src/video_core/query_cache/query_cache.h5
1 files changed, 4 insertions, 1 deletions
diff --git a/src/video_core/query_cache/query_cache.h b/src/video_core/query_cache/query_cache.h
index f94407b026..245ab1996c 100644
--- a/src/video_core/query_cache/query_cache.h
+++ b/src/video_core/query_cache/query_cache.h
@@ -23,6 +23,7 @@
#include "video_core/gpu.h"
#include "video_core/host1x/gpu_device_memory_manager.h"
#include "video_core/memory_manager.h"
+#include "video_core/nx2.h"
#include "video_core/query_cache/bank_base.h"
#include "video_core/query_cache/query_base.h"
#include "video_core/query_cache/query_cache_base.h"
@@ -273,7 +274,7 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
u8* pointer_timestamp = impl->device_memory.template GetPointer<u8>(cpu_addr + 8);
bool is_synced = (Settings::IsGPUFenceBehaviorDefault() ? !Settings::IsGPULevelHigh() : !Settings::IsGPUFenceBehaviorBalanced() && !Settings::IsGPUFenceBehaviorAccurate()) && is_fence;
std::function<void()> operation([this, is_synced, streamer, query_base = query, query_location,
- pointer, pointer_timestamp] {
+ pointer, pointer_timestamp, cpu_addr] {
if (True(query_base->flags & QueryFlagBits::IsInvalidated)) {
if (!is_synced) [[likely]] {
impl->pending_unregister.push_back(query_location);
@@ -298,6 +299,7 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
u32 value = static_cast<u32>(query_base->value);
std::memcpy(pointer, &value, sizeof(value));
}
+ Tegra::Nx2SemaphoreWaiters::Get().OnWrite(cpu_addr, static_cast<u32>(query_base->value));
if (!is_synced) [[likely]] {
impl->pending_unregister.push_back(query_location);
}
@@ -314,6 +316,7 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
} else {
std::memcpy(pointer, &payload, sizeof(payload));
}
+ Tegra::Nx2SemaphoreWaiters::Get().OnWrite(cpu_addr, payload);
streamer->Free(new_query_id);
return;
}