diff --git a/src/core/core.cpp b/src/core/core.cpp index 305f56ff1c..56b47e671c 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 c61f446196..009c6f5748 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 b2ee454964..ecab35d3bf 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 cd59a7faf1..6b8f06f780 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 18269e51c4..d384164de2 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;