Compare commits

...

1 Commits

Author SHA1 Message Date
lizzie c95ad020fb [gpu] Fix infinite hangup/freezes at shutdown/reset (#4395)
Thread may be destroyed at dtor(), but it hasn't fully shut down, so before notify shutdown, request immediate stop (effective immediately).

Like the issue was that the thread didn't want to stop running, thus it would hang, it would also reference objects which were being destroyed without waiting for them to actually be destroyed
So it would reference invalid data
This PR tells the thread: "hey, STOP now, and DESTROY yourself"
So all of that should be avoided

Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4395
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-09-11 15:29:52 +02:00
3 changed files with 14 additions and 4 deletions
+5 -4
View File
@@ -55,8 +55,8 @@ constexpr u64 GpuClockMultiplier(Settings::GpuClock clock) {
struct GPU::Impl { struct GPU::Impl {
explicit Impl(Core::System& system_, bool is_async_, bool use_nvdec_) explicit Impl(Core::System& system_, bool is_async_, bool use_nvdec_)
: gpu_thread{system_} : system{system_}
, system{system_} , gpu_thread{system_}
, use_nvdec{use_nvdec_} , use_nvdec{use_nvdec_}
, shader_notify() , shader_notify()
, is_async{is_async_} , is_async{is_async_}
@@ -182,6 +182,7 @@ struct GPU::Impl {
} }
void NotifyShutdown() { void NotifyShutdown() {
gpu_thread.NotifyShutdown();
std::unique_lock lk{sync_mutex}; std::unique_lock lk{sync_mutex};
shutting_down.store(true, std::memory_order::relaxed); shutting_down.store(true, std::memory_order::relaxed);
sync_cv.notify_all(); sync_cv.notify_all();
@@ -301,12 +302,12 @@ struct GPU::Impl {
return out; return out;
} }
Core::System& system;
// Destruction of thread must be done before all (non trivial) // Destruction of thread must be done before all (non trivial)
// previous members has been destroyed // previous members has been destroyed
VideoCommon::GPUThread::ThreadManager gpu_thread; VideoCommon::GPUThread::ThreadManager gpu_thread;
Core::System& system;
std::unique_ptr<VideoCore::RendererBase> renderer; std::unique_ptr<VideoCore::RendererBase> renderer;
const bool use_nvdec; const bool use_nvdec;
+7
View File
@@ -114,4 +114,11 @@ u64 ThreadManager::PushCommand(CommandData&& command_data, bool block, bool is_a
return fence; return fence;
} }
void ThreadManager::NotifyShutdown() {
if (thread.joinable()) {
thread.request_stop();
thread.join();
}
}
} // namespace VideoCommon::GPUThread } // namespace VideoCommon::GPUThread
+2
View File
@@ -125,6 +125,8 @@ public:
void TickGPU(bool is_async); void TickGPU(bool is_async);
void NotifyShutdown();
private: private:
/// Pushes a command to be executed by the GPU thread /// Pushes a command to be executed by the GPU thread
u64 PushCommand(CommandData&& command_data, bool block, bool is_async); u64 PushCommand(CommandData&& command_data, bool block, bool is_async);