From 9186050daaa3cd85eabee5c5fe677f39b2a5cbe5 Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Sat, 7 Jan 2023 23:52:36 +0100 Subject: [PATCH 1/3] VideoBackends:Vulkan: Clean up submission thread BlockingLoop usage --- .../Vulkan/CommandBufferManager.cpp | 47 +++++++------------ .../Vulkan/CommandBufferManager.h | 2 - 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp index 80bbd7e5b5..9c460905f7 100644 --- a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp +++ b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp @@ -226,33 +226,25 @@ bool CommandBufferManager::CreateSubmitThread() Common::SetCurrentThreadName("Vulkan CommandBufferManager SubmitThread"); m_submit_loop->Run([this]() { - PendingCommandBufferSubmit submit; + while (true) { - std::lock_guard guard(m_pending_submit_lock); - if (m_pending_submits.empty()) + PendingCommandBufferSubmit submit; { - m_submit_loop->AllowSleep(); - m_submit_worker_idle = true; - m_submit_worker_condvar.notify_all(); - return; + std::lock_guard guard(m_pending_submit_lock); + if (m_pending_submits.empty()) + { + m_submit_loop->AllowSleep(); + return; + } + + submit = m_pending_submits.front(); + m_pending_submits.pop_front(); } - submit = m_pending_submits.front(); - m_pending_submits.pop_front(); - } - - SubmitCommandBuffer(submit.command_buffer_index, submit.present_swap_chain, - submit.present_image_index); - CmdBufferResources& resources = m_command_buffers[submit.command_buffer_index]; - resources.waiting_for_submit.store(false, std::memory_order_release); - - { - std::lock_guard guard(m_pending_submit_lock); - if (m_pending_submits.empty()) - { - m_submit_worker_idle = true; - m_submit_worker_condvar.notify_all(); - } + SubmitCommandBuffer(submit.command_buffer_index, submit.present_swap_chain, + submit.present_image_index); + CmdBufferResources& resources = m_command_buffers[submit.command_buffer_index]; + resources.waiting_for_submit.store(false, std::memory_order_release); } }); }); @@ -265,8 +257,7 @@ void CommandBufferManager::WaitForWorkerThreadIdle() if (!m_use_threaded_submission) return; - std::unique_lock lock{m_pending_submit_lock}; - m_submit_worker_condvar.wait(lock, [&] { return m_submit_worker_idle; }); + m_submit_loop->Wait(); } void CommandBufferManager::WaitForFenceCounter(u64 fence_counter) @@ -354,12 +345,10 @@ void CommandBufferManager::SubmitCommandBuffer(bool submit_on_worker_thread, // Push to the pending submit queue. { std::lock_guard guard(m_pending_submit_lock); - m_submit_worker_idle = false; m_pending_submits.push_back({present_swap_chain, present_image_index, m_current_cmd_buffer}); + // Wake up the worker thread for a single iteration. + m_submit_loop->Wakeup(); } - - // Wake up the worker thread for a single iteration. - m_submit_loop->Wakeup(); } else { diff --git a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h index 7b4772760a..398f56e4ce 100644 --- a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h +++ b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h @@ -157,8 +157,6 @@ private: VkSemaphore m_present_semaphore = VK_NULL_HANDLE; std::deque m_pending_submits; std::mutex m_pending_submit_lock; - std::condition_variable m_submit_worker_condvar; - bool m_submit_worker_idle = true; Common::Flag m_last_present_failed; Common::Flag m_last_present_done; VkResult m_last_present_result = VK_SUCCESS; From 9d422d14d501df6ca3876ac500056dad923f4537 Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Mon, 20 Mar 2023 16:31:40 +0100 Subject: [PATCH 2/3] WorkQueueThread: Fix WaitForCompletion --- Source/Core/Common/WorkQueueThread.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Common/WorkQueueThread.h b/Source/Core/Common/WorkQueueThread.h index be3c3198d4..be723299b2 100644 --- a/Source/Core/Common/WorkQueueThread.h +++ b/Source/Core/Common/WorkQueueThread.h @@ -124,7 +124,7 @@ public: if (m_idle && !m_cancelling.load()) return; - m_wait_cond_var.wait(lg, [&] { return m_idle && m_cancelling.load(); }); + m_wait_cond_var.wait(lg, [&] { return m_idle && !m_cancelling; }); } // If the worker polls IsCanceling(), it can abort its work when Cancelling From c1be9628fc1237ffbae14f2d1a15ed1895be2eda Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Fri, 27 Jan 2023 15:06:35 +0100 Subject: [PATCH 3/3] VideoBackends:Vulkan: Use WorkQueueThread --- .../Vulkan/CommandBufferManager.cpp | 43 ++++--------------- .../Vulkan/CommandBufferManager.h | 6 +-- 2 files changed, 10 insertions(+), 39 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp index 9c460905f7..be02034f67 100644 --- a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp +++ b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp @@ -26,8 +26,7 @@ CommandBufferManager::~CommandBufferManager() if (m_use_threaded_submission) { WaitForWorkerThreadIdle(); - m_submit_loop->Stop(); - m_submit_thread.join(); + m_submit_thread.Shutdown(); } DestroyCommandBuffers(); @@ -221,32 +220,11 @@ VkDescriptorSet CommandBufferManager::AllocateDescriptorSet(VkDescriptorSetLayou bool CommandBufferManager::CreateSubmitThread() { - m_submit_loop = std::make_unique(); - m_submit_thread = std::thread([this]() { - Common::SetCurrentThreadName("Vulkan CommandBufferManager SubmitThread"); - - m_submit_loop->Run([this]() { - while (true) - { - PendingCommandBufferSubmit submit; - { - std::lock_guard guard(m_pending_submit_lock); - if (m_pending_submits.empty()) - { - m_submit_loop->AllowSleep(); - return; - } - - submit = m_pending_submits.front(); - m_pending_submits.pop_front(); - } - - SubmitCommandBuffer(submit.command_buffer_index, submit.present_swap_chain, - submit.present_image_index); - CmdBufferResources& resources = m_command_buffers[submit.command_buffer_index]; - resources.waiting_for_submit.store(false, std::memory_order_release); - } - }); + m_submit_thread.Reset("VK submission thread", [this](PendingCommandBufferSubmit submit) { + SubmitCommandBuffer(submit.command_buffer_index, submit.present_swap_chain, + submit.present_image_index); + CmdBufferResources& resources = m_command_buffers[submit.command_buffer_index]; + resources.waiting_for_submit.store(false, std::memory_order_release); }); return true; @@ -257,7 +235,7 @@ void CommandBufferManager::WaitForWorkerThreadIdle() if (!m_use_threaded_submission) return; - m_submit_loop->Wait(); + m_submit_thread.WaitForCompletion(); } void CommandBufferManager::WaitForFenceCounter(u64 fence_counter) @@ -343,12 +321,7 @@ void CommandBufferManager::SubmitCommandBuffer(bool submit_on_worker_thread, { resources.waiting_for_submit.store(true, std::memory_order_relaxed); // Push to the pending submit queue. - { - std::lock_guard guard(m_pending_submit_lock); - m_pending_submits.push_back({present_swap_chain, present_image_index, m_current_cmd_buffer}); - // Wake up the worker thread for a single iteration. - m_submit_loop->Wakeup(); - } + m_submit_thread.Push({present_swap_chain, present_image_index, m_current_cmd_buffer}); } else { diff --git a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h index 398f56e4ce..0249097423 100644 --- a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h +++ b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.h @@ -14,6 +14,7 @@ #include #include +#include #include "Common/BlockingLoop.h" #include "Common/Flag.h" #include "Common/Semaphore.h" @@ -146,17 +147,14 @@ private: u32 m_current_cmd_buffer = 0; // Threaded command buffer execution - std::thread m_submit_thread; - std::unique_ptr m_submit_loop; struct PendingCommandBufferSubmit { VkSwapchainKHR present_swap_chain; u32 present_image_index; u32 command_buffer_index; }; + Common::WorkQueueThread m_submit_thread; VkSemaphore m_present_semaphore = VK_NULL_HANDLE; - std::deque m_pending_submits; - std::mutex m_pending_submit_lock; Common::Flag m_last_present_failed; Common::Flag m_last_present_done; VkResult m_last_present_result = VK_SUCCESS;