From 8592f8a2b4cae1320b7e152f4d3a68ac7b39bfa3 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 29 May 2021 01:06:04 -0700 Subject: [PATCH] video_core: gpu: WaitFence: Do not block threads during shutdown. - Fixes a hang on shutdown when NVFlinger thread is waiting on a syncpoint that will never occur. - Commonly observed when stopping emulation in Super Mario Odyssey. --- src/video_core/gpu.cpp | 12 +++++++++++- src/video_core/gpu.h | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 37f7b24e14..35cc561be1 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -104,7 +104,13 @@ void GPU::WaitFence(u32 syncpoint_id, u32 value) { } MICROPROFILE_SCOPE(GPU_wait); std::unique_lock lock{sync_mutex}; - sync_cv.wait(lock, [=, this] { return syncpoints.at(syncpoint_id).load() >= value; }); + sync_cv.wait(lock, [=, this] { + if (shutting_down.load(std::memory_order_relaxed)) { + // We're shutting down, ensure no threads continue to wait for the next syncpoint + return true; + } + return syncpoints.at(syncpoint_id).load() >= value; + }); } void GPU::IncrementSyncPoint(const u32 syncpoint_id) { @@ -523,6 +529,10 @@ void GPU::TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const { } void GPU::ShutDown() { + // Signal that threads should no longer block on syncpoint fences + shutting_down.store(true, std::memory_order_relaxed); + sync_cv.notify_all(); + gpu_thread.ShutDown(); } diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 29a8678631..a8e98e51b1 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -389,6 +389,8 @@ private: std::unique_ptr kepler_memory; /// Shader build notifier std::unique_ptr shader_notify; + /// When true, we are about to shut down emulation session, so terminate outstanding tasks + std::atomic_bool shutting_down{}; std::array, Service::Nvidia::MaxSyncPoints> syncpoints{};