[vk] use boost::container::deque instead of std::queue for presentation swapchain of frames (#3120)

This may reduce total overhead (as benchmarks show boost::container::deque being better performing than std::deque, especially with the limited set of ops like push_front and pop_back
May actually not help at all and be worse through, as always, performance tests are welcome

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

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3120
Reviewed-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
lizzie
2025-12-18 11:29:38 +01:00
committed by crueter
parent 057d566ff4
commit 959f72297d
2 changed files with 32 additions and 34 deletions

View File

@@ -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();
}
}

View File

@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -5,7 +8,7 @@
#include <condition_variable>
#include <mutex>
#include <queue>
#include <boost/container/deque.hpp>
#include "common/common_types.h"
#include "common/polyfill_thread.h"
@@ -88,8 +91,8 @@ private:
#endif
vk::CommandPool cmdpool;
std::vector<Frame> frames;
std::queue<Frame*> present_queue;
std::queue<Frame*> free_queue;
boost::container::deque<Frame*> present_queue;
boost::container::deque<Frame*> free_queue;
std::condition_variable_any frame_cv;
std::condition_variable free_cv;
std::mutex swapchain_mutex;