diff options
author | Markus Wick <[email protected]> | 2021-04-07 08:42:54 +0200 |
---|---|---|
committer | Markus Wick <[email protected]> | 2021-04-07 22:38:52 +0200 |
commit | 5145133a604f626c05f832465ac22019b003c32a (patch) | |
tree | 81aa729ab6897cadeb1251f6adcafaeab1010f0d /src | |
parent | 4aec060f6de410698d5b0a5bffd42d4327b258e4 (diff) | |
download | yuzu-mainline-5145133a604f626c05f832465ac22019b003c32a.tar.gz yuzu-mainline-5145133a604f626c05f832465ac22019b003c32a.zip |
video_core/gpu_thread: Implement a ShutDown method.
This was implicitly done by `is_powered_on = false`, however the explicit method allows us to block until the GPU is actually gone.
This should fix a race condition while removing the other subsystems while the GPU is still active.
Diffstat (limited to 'src')
-rw-r--r-- | src/core/core.cpp | 2 | ||||
-rw-r--r-- | src/video_core/gpu.cpp | 4 | ||||
-rw-r--r-- | src/video_core/gpu.h | 4 | ||||
-rw-r--r-- | src/video_core/gpu_thread.cpp | 26 | ||||
-rw-r--r-- | src/video_core/gpu_thread.h | 7 |
5 files changed, 28 insertions, 15 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 305f56ff1..56b47e671 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -296,7 +296,7 @@ struct System::Impl { exit_lock = false; if (gpu_core) { - gpu_core->WaitIdle(); + gpu_core->ShutDown(); } services.reset(); diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index c61f44619..009c6f574 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -517,8 +517,8 @@ void GPU::TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const { interrupt_manager.GPUInterruptSyncpt(syncpoint_id, value); } -void GPU::WaitIdle() const { - gpu_thread.WaitIdle(); +void GPU::ShutDown() { + gpu_thread.ShutDown(); } void GPU::OnCommandListEnd() { diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index b2ee45496..ecab35d3b 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -219,8 +219,8 @@ public: return *shader_notify; } - // Waits for the GPU to finish working - void WaitIdle() const; + // Stops the GPU execution and waits for the GPU to finish working + void ShutDown(); /// Allows the CPU/NvFlinger to wait on the GPU before presenting a frame. void WaitFence(u32 syncpoint_id, u32 value); diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index cd59a7faf..6b8f06f78 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -68,13 +68,7 @@ ThreadManager::ThreadManager(Core::System& system_, bool is_async_) : system{system_}, is_async{is_async_} {} ThreadManager::~ThreadManager() { - if (!thread.joinable()) { - return; - } - - // Notify GPU thread that a shutdown is pending - PushCommand(EndProcessingCommand()); - thread.join(); + ShutDown(); } void ThreadManager::StartThread(VideoCore::RendererBase& renderer, @@ -132,10 +126,26 @@ void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) { void ThreadManager::WaitIdle() const { while (state.last_fence > state.signaled_fence.load(std::memory_order_relaxed) && - system.IsPoweredOn()) { + state.is_running) { } } +void ThreadManager::ShutDown() { + if (!state.is_running) { + return; + } + + state.is_running = false; + + if (!thread.joinable()) { + return; + } + + // Notify GPU thread that a shutdown is pending + PushCommand(EndProcessingCommand()); + thread.join(); +} + void ThreadManager::OnCommandListEnd() { PushCommand(OnCommandListEndCommand()); } diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 18269e51c..d384164de 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h @@ -132,8 +132,8 @@ public: /// Notify rasterizer that any caches of the specified region should be flushed and invalidated void FlushAndInvalidateRegion(VAddr addr, u64 size); - // Wait until the gpu thread is idle. - void WaitIdle() const; + // Stops the GPU execution and waits for the GPU to finish working + void ShutDown(); void OnCommandListEnd(); @@ -141,6 +141,9 @@ private: /// Pushes a command to be executed by the GPU thread u64 PushCommand(CommandData&& command_data); + // Wait until the gpu thread is idle. + void WaitIdle() const; + Core::System& system; const bool is_async; VideoCore::RasterizerInterface* rasterizer = nullptr; |