From 934eeb0e6d82458048c94361b0d7b2db1b89f041 Mon Sep 17 00:00:00 2001 From: Takoroka <137927095+Takoroka@users.noreply.github.com> Date: Thu, 29 Oct 2026 00:27:35 -0400 Subject: nx2: poll pending channels briefly before sleeping; profile zones on the TSC - A channel waiting on a semaphore the CPU releases slept 1 ms per poll (~25 waits a second in title 1); poll for 0.5 ms first. - The GPU profile zones read the wall clock (the TSC) instead of QueryPerformanceCounter, which cost ~5% of the GPU thread when on. --- src/video_core/gpu_thread.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src/video_core/gpu_thread.cpp') diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index cf4e159806..72da1904e1 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -39,6 +39,8 @@ void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Core::Fronten auto current_context = context.Acquire(); CommandDataContainer next; + // When a pending channel last moved or a command arrived (see the polling below). + auto last_progress = std::chrono::steady_clock::now(); namespace Profile = VideoCommon::Nx2Profile; while (!stop_token.stop_requested()) { Profile::Report(); @@ -49,8 +51,16 @@ void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Core::Fronten scheduler.ResumePending(system.GPU()); } if (!state.queue.TryPop(next)) { + // The CPU usually releases the semaphore soon after: poll for half a + // millisecond before sleeping, or every wait also waits out a host sleep + // (title 1 waits ~25 times a second). Profile::Scope scope{Profile::Zone::PendingSleep}; - std::this_thread::sleep_for(std::chrono::milliseconds{1}); + if (std::chrono::steady_clock::now() - last_progress < + std::chrono::microseconds{500}) { + std::this_thread::yield(); + } else { + std::this_thread::sleep_for(std::chrono::milliseconds{1}); + } continue; } } else { @@ -60,6 +70,7 @@ void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Core::Fronten if (stop_token.stop_requested()) { break; } + last_progress = std::chrono::steady_clock::now(); if (auto* submit_list = std::get_if(&next.data)) { Profile::Scope scope{Profile::Zone::Push}; scheduler.Push(system.GPU(), submit_list->channel, std::move(submit_list->entries)); -- cgit v1.2.3