diff options
| author | 2021-05-29 01:06:04 -0700 | |
|---|---|---|
| committer | 2021-05-29 01:06:04 -0700 | |
| commit | 8592f8a2b4cae1320b7e152f4d3a68ac7b39bfa3 (patch) | |
| tree | 0e7ef0aa4ff134d53a46c0f1748a140c95db44fe /src | |
| parent | Merge pull request #6373 from bunnei/use-slabheap-tls (diff) | |
| download | yuzu-8592f8a2b4cae1320b7e152f4d3a68ac7b39bfa3.tar.gz yuzu-8592f8a2b4cae1320b7e152f4d3a68ac7b39bfa3.tar.xz yuzu-8592f8a2b4cae1320b7e152f4d3a68ac7b39bfa3.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/gpu.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/gpu.h | 2 |
2 files changed, 13 insertions, 1 deletions
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 37f7b24e1..35cc561be 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) { | |||
| 104 | } | 104 | } |
| 105 | MICROPROFILE_SCOPE(GPU_wait); | 105 | MICROPROFILE_SCOPE(GPU_wait); |
| 106 | std::unique_lock lock{sync_mutex}; | 106 | std::unique_lock lock{sync_mutex}; |
| 107 | sync_cv.wait(lock, [=, this] { return syncpoints.at(syncpoint_id).load() >= value; }); | 107 | sync_cv.wait(lock, [=, this] { |
| 108 | if (shutting_down.load(std::memory_order_relaxed)) { | ||
| 109 | // We're shutting down, ensure no threads continue to wait for the next syncpoint | ||
| 110 | return true; | ||
| 111 | } | ||
| 112 | return syncpoints.at(syncpoint_id).load() >= value; | ||
| 113 | }); | ||
| 108 | } | 114 | } |
| 109 | 115 | ||
| 110 | void GPU::IncrementSyncPoint(const u32 syncpoint_id) { | 116 | void GPU::IncrementSyncPoint(const u32 syncpoint_id) { |
| @@ -523,6 +529,10 @@ void GPU::TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const { | |||
| 523 | } | 529 | } |
| 524 | 530 | ||
| 525 | void GPU::ShutDown() { | 531 | void GPU::ShutDown() { |
| 532 | // Signal that threads should no longer block on syncpoint fences | ||
| 533 | shutting_down.store(true, std::memory_order_relaxed); | ||
| 534 | sync_cv.notify_all(); | ||
| 535 | |||
| 526 | gpu_thread.ShutDown(); | 536 | gpu_thread.ShutDown(); |
| 527 | } | 537 | } |
| 528 | 538 | ||
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 29a867863..a8e98e51b 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -389,6 +389,8 @@ private: | |||
| 389 | std::unique_ptr<Engines::KeplerMemory> kepler_memory; | 389 | std::unique_ptr<Engines::KeplerMemory> kepler_memory; |
| 390 | /// Shader build notifier | 390 | /// Shader build notifier |
| 391 | std::unique_ptr<VideoCore::ShaderNotify> shader_notify; | 391 | std::unique_ptr<VideoCore::ShaderNotify> shader_notify; |
| 392 | /// When true, we are about to shut down emulation session, so terminate outstanding tasks | ||
| 393 | std::atomic_bool shutting_down{}; | ||
| 392 | 394 | ||
| 393 | std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{}; | 395 | std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{}; |
| 394 | 396 | ||