diff --git a/Source/Core/VideoCommon/AsyncShaderCompiler.cpp b/Source/Core/VideoCommon/AsyncShaderCompiler.cpp index c69354628d2..83eaa2e23e8 100644 --- a/Source/Core/VideoCommon/AsyncShaderCompiler.cpp +++ b/Source/Core/VideoCommon/AsyncShaderCompiler.cpp @@ -35,7 +35,7 @@ void AsyncShaderCompiler::QueueWorkItem(WorkItemPtr item, u32 priority) } else { - std::lock_guard guard(m_pending_work_lock); + std::lock_guard guard(m_pending_work_lock); m_pending_work.emplace(priority, std::move(item)); m_worker_thread_wake.notify_one(); } @@ -45,7 +45,7 @@ void AsyncShaderCompiler::RetrieveWorkItems() { std::deque completed_work; { - std::lock_guard guard(m_completed_work_lock); + std::lock_guard guard(m_completed_work_lock); m_completed_work.swap(completed_work); } @@ -58,16 +58,29 @@ void AsyncShaderCompiler::RetrieveWorkItems() bool AsyncShaderCompiler::HasPendingWork() { - std::lock_guard guard(m_pending_work_lock); + std::lock_guard guard(m_pending_work_lock); return !m_pending_work.empty() || m_busy_workers.load() != 0; } bool AsyncShaderCompiler::HasCompletedWork() { - std::lock_guard guard(m_completed_work_lock); + std::lock_guard guard(m_completed_work_lock); return !m_completed_work.empty(); } +void AsyncShaderCompiler::ClearAllWork() +{ + { + std::lock_guard guard(m_pending_work_lock); + m_pending_work.clear(); + } + + { + std::lock_guard guard(m_completed_work_lock); + m_completed_work.clear(); + } +} + bool AsyncShaderCompiler::WaitUntilCompletion( const std::function& progress_callback) { @@ -89,8 +102,8 @@ bool AsyncShaderCompiler::WaitUntilCompletion( size_t total_items; { // Safe to hold both locks here, since nowhere else does. - std::lock_guard pending_guard(m_pending_work_lock); - std::lock_guard completed_guard(m_completed_work_lock); + std::lock_guard pending_guard(m_pending_work_lock); + std::lock_guard completed_guard(m_completed_work_lock); total_items = m_completed_work.size() + m_pending_work.size() + m_busy_workers.load() + 1; } @@ -99,7 +112,7 @@ bool AsyncShaderCompiler::WaitUntilCompletion( { size_t remaining_items; { - std::lock_guard pending_guard(m_pending_work_lock); + std::lock_guard pending_guard(m_pending_work_lock); if (m_pending_work.empty() && !m_busy_workers.load()) return true; remaining_items = m_pending_work.size(); @@ -164,7 +177,7 @@ void AsyncShaderCompiler::StopWorkerThreads() // Signal worker threads to stop, and wake all of them. { - std::lock_guard guard(m_pending_work_lock); + std::lock_guard guard(m_pending_work_lock); m_exit_flag.Set(); m_worker_thread_wake.notify_all(); } @@ -213,7 +226,7 @@ void AsyncShaderCompiler::WorkerThreadEntryPoint(void* param) void AsyncShaderCompiler::WorkerThreadRun() { - std::unique_lock pending_lock(m_pending_work_lock); + std::unique_lock pending_lock(m_pending_work_lock); while (!m_exit_flag.IsSet()) { m_worker_thread_wake.wait(pending_lock); @@ -228,7 +241,7 @@ void AsyncShaderCompiler::WorkerThreadRun() if (item->Compile()) { - std::lock_guard completed_guard(m_completed_work_lock); + std::lock_guard completed_guard(m_completed_work_lock); m_completed_work.push_back(std::move(item)); } diff --git a/Source/Core/VideoCommon/AsyncShaderCompiler.h b/Source/Core/VideoCommon/AsyncShaderCompiler.h index 8773891d619..ffcca0c4ec1 100644 --- a/Source/Core/VideoCommon/AsyncShaderCompiler.h +++ b/Source/Core/VideoCommon/AsyncShaderCompiler.h @@ -49,6 +49,9 @@ public: bool HasPendingWork(); bool HasCompletedWork(); + // Clears both pending and completed work + void ClearAllWork(); + // Calls progress_callback periodically, with completed_items, and total_items. // Returns false if interrupted. bool WaitUntilCompletion(const std::function& progress_callback); diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.cpp b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.cpp index a3c98ee9d7c..0c4cf432271 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.cpp +++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.cpp @@ -24,10 +24,16 @@ CustomShaderCache::CustomShaderCache() CustomShaderCache::~CustomShaderCache() { if (m_async_shader_compiler) + { m_async_shader_compiler->StopWorkerThreads(); + m_async_shader_compiler->ClearAllWork(); + } if (m_async_uber_shader_compiler) + { m_async_uber_shader_compiler->StopWorkerThreads(); + m_async_uber_shader_compiler->ClearAllWork(); + } } void CustomShaderCache::RetrieveAsyncShaders() diff --git a/Source/Core/VideoCommon/ShaderCache.cpp b/Source/Core/VideoCommon/ShaderCache.cpp index a3d07368f60..03dc21c9374 100644 --- a/Source/Core/VideoCommon/ShaderCache.cpp +++ b/Source/Core/VideoCommon/ShaderCache.cpp @@ -109,7 +109,10 @@ void ShaderCache::Shutdown() // This may leave shaders uncommitted to the cache, but it's better than blocking shutdown // until everything has finished compiling. if (m_async_shader_compiler) + { m_async_shader_compiler->StopWorkerThreads(); + m_async_shader_compiler->ClearAllWork(); + } ClosePipelineUIDCache(); }