From 5145133a604f626c05f832465ac22019b003c32a Mon Sep 17 00:00:00 2001 From: Markus Wick Date: Wed, 7 Apr 2021 08:42:54 +0200 Subject: 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. --- src/video_core/gpu_thread.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/video_core/gpu_thread.h') 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; -- cgit v1.2.3 From e6fb49fa4bb2864702abcefc14f6bb62eaba7a7e Mon Sep 17 00:00:00 2001 From: Markus Wick Date: Wed, 7 Apr 2021 13:57:49 +0200 Subject: video_core/gpu_thread: Keep the write lock for allocating the fence. Else the fence might get submited out-of-order into the queue, which makes testing them pointless. Overhead should be tiny as the mutex is just moved from the queue to the writing code. --- src/video_core/gpu_thread.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/video_core/gpu_thread.h') diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index d384164de..cb901c22a 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h @@ -101,7 +101,8 @@ struct CommandDataContainer { struct SynchState final { std::atomic_bool is_running{true}; - using CommandQueue = Common::MPSCQueue; + using CommandQueue = Common::SPSCQueue; + std::mutex write_lock; CommandQueue queue; u64 last_fence{}; std::atomic signaled_fence{}; -- cgit v1.2.3 From e8bd9aed8bf0f60455d0ae6a8f6f3abf92dd8305 Mon Sep 17 00:00:00 2001 From: Markus Wick Date: Wed, 7 Apr 2021 11:41:31 +0200 Subject: video_core: Use a CV for blocking commands. There is no need for a busy loop here. Let's just use a condition variable to save some power. --- src/video_core/gpu_thread.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/video_core/gpu_thread.h') diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index cb901c22a..11a648f38 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h @@ -90,11 +90,12 @@ using CommandData = struct CommandDataContainer { CommandDataContainer() = default; - explicit CommandDataContainer(CommandData&& data_, u64 next_fence_) - : data{std::move(data_)}, fence{next_fence_} {} + explicit CommandDataContainer(CommandData&& data_, u64 next_fence_, bool block_) + : data{std::move(data_)}, fence{next_fence_}, block(block_) {} CommandData data; u64 fence{}; + bool block{}; }; /// Struct used to synchronize the GPU thread @@ -106,6 +107,7 @@ struct SynchState final { CommandQueue queue; u64 last_fence{}; std::atomic signaled_fence{}; + std::condition_variable cv; }; /// Class used to manage the GPU thread @@ -140,10 +142,7 @@ public: 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; + u64 PushCommand(CommandData&& command_data, bool block = false); Core::System& system; const bool is_async; -- cgit v1.2.3