Просмотр исходного кода

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.
Markus Wick 5 лет назад
Родитель
Сommit
5145133a60
5 измененных файлов с 28 добавлено и 15 удалено
  1. 1 1
      src/core/core.cpp
  2. 2 2
      src/video_core/gpu.cpp
  3. 2 2
      src/video_core/gpu.h
  4. 18 8
      src/video_core/gpu_thread.cpp
  5. 5 2
      src/video_core/gpu_thread.h

+ 1 - 1
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();

+ 2 - 2
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() {

+ 2 - 2
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);

+ 18 - 8
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());
 }

+ 5 - 2
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;