From 72fc31f44b954f8e0ebf1a36c2c8565eec83be3a Mon Sep 17 00:00:00 2001 From: Takoroka <137927095+Takoroka@users.noreply.github.com> Date: Thu, 29 Oct 2026 15:56:45 -0400 Subject: video_core: stop resuming pending channels once the system is powered off At shutdown is_powered_on is cleared before the GPU thread is stopped. A channel suspended on a semaphore acquire that can resume then went through DispatchCalls, which returns at once when powered off, so the acquire stayed pending and ResumePending counted it as progress forever: the GPU thread never got back to its stop request and closing the game hung in ThreadManager::NotifyShutdown. --- src/video_core/control/scheduler.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/video_core/control/scheduler.cpp') diff --git a/src/video_core/control/scheduler.cpp b/src/video_core/control/scheduler.cpp index c120533c37..dc42906752 100644 --- a/src/video_core/control/scheduler.cpp +++ b/src/video_core/control/scheduler.cpp @@ -9,6 +9,7 @@ #include #include "common/assert.h" +#include "core/core.h" #include "video_core/control/channel_state.h" #include "video_core/control/scheduler.h" #include "video_core/gpu.h" @@ -59,6 +60,12 @@ void Scheduler::ResumePending(GPU& gpu) { progress = false; for (const auto& state : pending_channels) { auto& dma_pusher = state->payload->dma_pusher; + // Powered off (shutting down), DispatchCalls returns at once and the acquire stays + // pending: resuming it again counted as progress forever and the GPU thread never + // reached its stop request (closing the game hung). + if (!dma_pusher.system.IsPoweredOn()) { + return; + } if (!dma_pusher.HasPendingAcquire() || !dma_pusher.CanResumeAcquire()) { continue; } -- cgit v1.2.3