diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index 0b29ad1389..3b5c2e3c01 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp @@ -146,7 +146,7 @@ PresentManager::PresentManager(const vk::Instance& instance_, .pNext = nullptr, .flags = VK_FENCE_CREATE_SIGNALED_BIT, }); - free_queue.push(&frame); + free_queue.push_back(&frame); } if (use_present_thread) { @@ -164,7 +164,7 @@ Frame* PresentManager::GetRenderFrame() { // Take the frame from the queue Frame* frame = free_queue.front(); - free_queue.pop(); + free_queue.pop_front(); // Wait for the presentation to be finished so all frame resources are free frame->present_done.Wait(); @@ -174,18 +174,17 @@ Frame* PresentManager::GetRenderFrame() { } void PresentManager::Present(Frame* frame) { - if (!use_present_thread) { + if (use_present_thread) { + scheduler.Record([this, frame](vk::CommandBuffer) { + std::unique_lock lock{queue_mutex}; + present_queue.push_back(frame); + frame_cv.notify_one(); + }); + } else { scheduler.WaitWorker(); CopyToSwapchain(frame); - free_queue.push(frame); - return; + free_queue.push_back(frame); } - - scheduler.Record([this, frame](vk::CommandBuffer) { - std::unique_lock lock{queue_mutex}; - present_queue.push(frame); - frame_cv.notify_one(); - }); } void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, VkFormat image_view_format, @@ -277,29 +276,25 @@ void PresentManager::PresentThread(std::stop_token token) { Common::SetCurrentThreadName("VulkanPresent"); while (!token.stop_requested()) { std::unique_lock lock{queue_mutex}; - // Wait for presentation frames frame_cv.wait(lock, token, [this] { return !present_queue.empty(); }); - if (token.stop_requested()) { - return; + if (!token.stop_requested()) { + // Take the frame and notify anyone waiting + Frame* frame = present_queue.front(); + present_queue.pop_front(); + frame_cv.notify_one(); + + // By exchanging the lock ownership we take the swapchain lock + // before the queue lock goes out of scope. This way the swapchain + // lock in WaitPresent is guaranteed to occur after here. + std::exchange(lock, std::unique_lock{swapchain_mutex}); + CopyToSwapchain(frame); + + // Free the frame for reuse + std::scoped_lock fl{free_mutex}; + free_queue.push_back(frame); + free_cv.notify_one(); } - - // Take the frame and notify anyone waiting - Frame* frame = present_queue.front(); - present_queue.pop(); - frame_cv.notify_one(); - - // By exchanging the lock ownership we take the swapchain lock - // before the queue lock goes out of scope. This way the swapchain - // lock in WaitPresent is guaranteed to occur after here. - std::exchange(lock, std::unique_lock{swapchain_mutex}); - - CopyToSwapchain(frame); - - // Free the frame for reuse - std::scoped_lock fl{free_mutex}; - free_queue.push(frame); - free_cv.notify_one(); } } diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h index 5820280602..377de8fed3 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.h +++ b/src/video_core/renderer_vulkan/vk_present_manager.h @@ -5,7 +5,7 @@ #include #include -#include +#include #include "common/common_types.h" #include "common/polyfill_thread.h" @@ -88,8 +88,8 @@ private: #endif vk::CommandPool cmdpool; std::vector frames; - std::queue present_queue; - std::queue free_queue; + boost::container::deque present_queue; + boost::container::deque free_queue; std::condition_variable_any frame_cv; std::condition_variable free_cv; std::mutex swapchain_mutex;