renderer_vulkan: Address various sync issues

* Drop Common::SPSCQueue as it sometimes gives garbage frames.

* Reduce master semaphore timeout to allow the wait to recover in cases wher it gets stuck
This commit is contained in:
GPUCode
2023-03-05 01:27:39 +02:00
parent 223627c381
commit b9021ea469
5 changed files with 27 additions and 9 deletions

View File

@@ -15,7 +15,7 @@ namespace Vulkan {
class Instance;
constexpr u64 WAIT_TIMEOUT = std::numeric_limits<u64>::max();
constexpr u64 WAIT_TIMEOUT = 1000000000;
class MasterSemaphore {
public:

View File

@@ -229,7 +229,7 @@ void RenderpassCache::EndRendering() {
// The Mali guide recommends flushing at the end of each major renderpass
// Testing has shown this has a significant effect on rendering performance
if (cmd_count > 20 && instance.ShouldFlush()) {
scheduler.Flush();
// scheduler.Flush();
cmd_count = 0;
}
}

View File

@@ -74,9 +74,6 @@ void Scheduler::WorkerThread(std::stop_token stop_token) {
std::unique_ptr<CommandChunk> work;
{
std::unique_lock lock{work_mutex};
if (work_queue.empty()) {
wait_cv.notify_all();
}
Common::CondvarWait(work_cv, lock, stop_token, [&] { return !work_queue.empty(); });
if (stop_token.stop_requested()) {
continue;

View File

@@ -45,7 +45,7 @@ PresentMailbox::PresentMailbox(const Instance& instance_, Swapchain& swapchain_,
frame.cmdbuf = command_buffers[i];
frame.render_ready = device.createSemaphore({});
frame.present_done = device.createFence({.flags = vk::FenceCreateFlagBits::eSignaled});
free_queue.Push(&frame);
free_queue.queue.push(&frame);
}
present_thread = std::jthread([this](std::stop_token token) { PresentThread(token); });

View File

@@ -7,7 +7,6 @@
#include <mutex>
#include <queue>
#include "common/polyfill_thread.h"
#include "common/threadsafe_queue.h"
#include "video_core/renderer_vulkan/vk_common.h"
VK_DEFINE_HANDLE(VmaAllocation)
@@ -52,6 +51,28 @@ private:
void CopyToSwapchain(Frame* frame);
void RecreateSwapchain();
struct FrameQueue {
void Push(Frame* frame) {
std::scoped_lock lock{mutex};
queue.push(frame);
cv.notify_one();
}
Frame* PopWait(std::stop_token token = {}) {
std::unique_lock lock{mutex};
if (queue.empty()) {
Common::CondvarWait(cv, lock, token, [this] { return !queue.empty(); });
}
Frame* frame = queue.front();
queue.pop();
return frame;
}
std::queue<Frame*> queue;
std::condition_variable_any cv;
std::mutex mutex;
};
private:
const Instance& instance;
Swapchain& swapchain;
@@ -60,8 +81,8 @@ private:
vk::CommandPool command_pool;
vk::Queue graphics_queue;
std::array<Frame, SWAP_CHAIN_SIZE> swap_chain{};
Common::SPSCQueue<Frame*> free_queue{};
Common::SPSCQueue<Frame*, true> present_queue{};
FrameQueue free_queue;
FrameQueue present_queue;
std::jthread present_thread;
std::mutex swapchain_mutex;
std::condition_variable swapchain_cv;