mirror of
https://github.com/Lime3DS/Lime3DS
synced 2024-10-30 03:37:52 +00:00
vk_master_semaphore: Remove waitable atomic
* These are buggy on some platforms and regular condition_variables are faster most of the time
This commit is contained in:
parent
222ca7de21
commit
af2efdd2b4
2 changed files with 23 additions and 35 deletions
|
@ -5,7 +5,6 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
#include "video_core/renderer_vulkan/vk_master_semaphore.h"
|
#include "video_core/renderer_vulkan/vk_master_semaphore.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
|
@ -108,7 +107,7 @@ constexpr u64 FENCE_RESERVE = 8;
|
||||||
MasterSemaphoreFence::MasterSemaphoreFence(const Instance& instance_) : instance{instance_} {
|
MasterSemaphoreFence::MasterSemaphoreFence(const Instance& instance_) : instance{instance_} {
|
||||||
const vk::Device device{instance.GetDevice()};
|
const vk::Device device{instance.GetDevice()};
|
||||||
for (u64 i = 0; i < FENCE_RESERVE; i++) {
|
for (u64 i = 0; i < FENCE_RESERVE; i++) {
|
||||||
free_queue.push(device.createFenceUnique({}));
|
free_queue.push_back(device.createFence({}));
|
||||||
}
|
}
|
||||||
wait_thread = std::jthread([this](std::stop_token token) { WaitThread(token); });
|
wait_thread = std::jthread([this](std::stop_token token) { WaitThread(token); });
|
||||||
}
|
}
|
||||||
|
@ -121,13 +120,8 @@ MasterSemaphoreFence::~MasterSemaphoreFence() {
|
||||||
void MasterSemaphoreFence::Refresh() {}
|
void MasterSemaphoreFence::Refresh() {}
|
||||||
|
|
||||||
void MasterSemaphoreFence::Wait(u64 tick) {
|
void MasterSemaphoreFence::Wait(u64 tick) {
|
||||||
while (true) {
|
std::unique_lock lk{free_mutex};
|
||||||
u64 current_value = gpu_tick.load(std::memory_order_relaxed);
|
free_cv.wait(lk, [&] { return gpu_tick.load(std::memory_order_relaxed) >= tick; });
|
||||||
if (current_value >= tick) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
gpu_tick.wait(current_value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MasterSemaphoreFence::SubmitWork(vk::CommandBuffer cmdbuf, vk::Semaphore wait,
|
void MasterSemaphoreFence::SubmitWork(vk::CommandBuffer cmdbuf, vk::Semaphore wait,
|
||||||
|
@ -151,57 +145,56 @@ void MasterSemaphoreFence::SubmitWork(vk::CommandBuffer cmdbuf, vk::Semaphore wa
|
||||||
.pSignalSemaphores = &signal,
|
.pSignalSemaphores = &signal,
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::UniqueFence fence{GetFreeFence()};
|
const vk::Fence fence = GetFreeFence();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
instance.GetGraphicsQueue().submit(submit_info, *fence);
|
instance.GetGraphicsQueue().submit(submit_info, fence);
|
||||||
} catch (vk::DeviceLostError& err) {
|
} catch (vk::DeviceLostError& err) {
|
||||||
UNREACHABLE_MSG("Device lost during submit: {}", err.what());
|
UNREACHABLE_MSG("Device lost during submit: {}", err.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::scoped_lock lock{wait_mutex};
|
std::scoped_lock lock{wait_mutex};
|
||||||
wait_queue.push({
|
wait_queue.emplace(fence, signal_value);
|
||||||
.handle = std::move(fence),
|
|
||||||
.signal_value = signal_value,
|
|
||||||
});
|
|
||||||
wait_cv.notify_one();
|
wait_cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MasterSemaphoreFence::WaitThread(std::stop_token token) {
|
void MasterSemaphoreFence::WaitThread(std::stop_token token) {
|
||||||
const vk::Device device{instance.GetDevice()};
|
const vk::Device device{instance.GetDevice()};
|
||||||
while (!token.stop_requested()) {
|
while (!token.stop_requested()) {
|
||||||
Fence fence;
|
vk::Fence fence;
|
||||||
|
u64 signal_value;
|
||||||
{
|
{
|
||||||
std::unique_lock lock{wait_mutex};
|
std::unique_lock lock{wait_mutex};
|
||||||
Common::CondvarWait(wait_cv, lock, token, [this] { return !wait_queue.empty(); });
|
Common::CondvarWait(wait_cv, lock, token, [this] { return !wait_queue.empty(); });
|
||||||
if (token.stop_requested()) {
|
if (token.stop_requested()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fence = std::move(wait_queue.front());
|
std::tie(fence, signal_value) = wait_queue.front();
|
||||||
wait_queue.pop();
|
wait_queue.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
const vk::Result result = device.waitForFences(*fence.handle, true, WAIT_TIMEOUT);
|
const vk::Result result = device.waitForFences(fence, true, WAIT_TIMEOUT);
|
||||||
if (result != vk::Result::eSuccess) {
|
if (result != vk::Result::eSuccess) {
|
||||||
UNREACHABLE_MSG("Fence wait failed with error {}", vk::to_string(result));
|
UNREACHABLE_MSG("Fence wait failed with error {}", vk::to_string(result));
|
||||||
}
|
}
|
||||||
device.resetFences(*fence.handle);
|
|
||||||
|
|
||||||
gpu_tick.store(fence.signal_value);
|
device.resetFences(fence);
|
||||||
gpu_tick.notify_all();
|
gpu_tick.store(signal_value);
|
||||||
|
|
||||||
std::scoped_lock lock{free_mutex};
|
std::scoped_lock lock{free_mutex};
|
||||||
free_queue.push(std::move(fence.handle));
|
free_queue.push_back(fence);
|
||||||
|
free_cv.notify_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::UniqueFence MasterSemaphoreFence::GetFreeFence() {
|
vk::Fence MasterSemaphoreFence::GetFreeFence() {
|
||||||
std::scoped_lock lock{free_mutex};
|
std::scoped_lock lock{free_mutex};
|
||||||
if (free_queue.empty()) {
|
if (free_queue.empty()) {
|
||||||
return instance.GetDevice().createFenceUnique({});
|
return instance.GetDevice().createFence({});
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::UniqueFence fence{std::move(free_queue.front())};
|
const vk::Fence fence = free_queue.front();
|
||||||
free_queue.pop();
|
free_queue.pop_front();
|
||||||
return fence;
|
return fence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,20 +88,15 @@ public:
|
||||||
private:
|
private:
|
||||||
void WaitThread(std::stop_token token);
|
void WaitThread(std::stop_token token);
|
||||||
|
|
||||||
vk::UniqueFence GetFreeFence();
|
vk::Fence GetFreeFence();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Instance& instance;
|
const Instance& instance;
|
||||||
|
std::deque<vk::Fence> free_queue;
|
||||||
struct Fence {
|
std::queue<Waitable> wait_queue;
|
||||||
vk::UniqueFence handle;
|
|
||||||
u64 signal_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::queue<vk::UniqueFence> free_queue;
|
|
||||||
std::queue<Fence> wait_queue;
|
|
||||||
std::mutex free_mutex;
|
std::mutex free_mutex;
|
||||||
std::mutex wait_mutex;
|
std::mutex wait_mutex;
|
||||||
|
std::condition_variable free_cv;
|
||||||
std::condition_variable_any wait_cv;
|
std::condition_variable_any wait_cv;
|
||||||
std::jthread wait_thread;
|
std::jthread wait_thread;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue