renderer_vulkan: Small cleanups

This commit is contained in:
GPUCode
2023-03-05 17:34:35 +02:00
parent 8f194b5fff
commit 0a8f11ca63
4 changed files with 82 additions and 74 deletions

View File

@ -217,7 +217,7 @@ void RendererVulkan::RenderToMailbox(const Layout::FramebufferLayout& layout,
DrawScreens(frame, layout, flipped); DrawScreens(frame, layout, flipped);
scheduler.Flush(frame->render_ready, nullptr, &frame->is_submitted); scheduler.Flush(&frame->is_submitted, frame->render_ready);
mailbox->Present(frame); mailbox->Present(frame);
} }

View File

@ -210,10 +210,17 @@ void RasterizerVulkan::SetupVertexArray() {
const PAddr data_addr = const PAddr data_addr =
base_address + loader.data_offset + (vs_input_index_min * loader.byte_count); base_address + loader.data_offset + (vs_input_index_min * loader.byte_count);
const u32 vertex_num = vs_input_index_max - vs_input_index_min + 1; const u32 vertex_num = vs_input_index_max - vs_input_index_min + 1;
const u32 data_size = loader.byte_count * vertex_num; u32 data_size = loader.byte_count * vertex_num;
res_cache.FlushRegion(data_addr, data_size); res_cache.FlushRegion(data_addr, data_size);
const u8* src_ptr = memory.GetPhysicalPointer(data_addr); const MemoryRef src_ref = memory.GetPhysicalRef(data_addr);
if (src_ref.GetSize() < data_size) {
LOG_ERROR(Render_Vulkan,
"Vertex buffer size {} exceeds available space {} at address {:#016X}",
data_size, src_ref.GetSize(), data_addr);
}
const u8* src_ptr = src_ref.GetPtr();
u8* dst_ptr = array_ptr + buffer_offset; u8* dst_ptr = array_ptr + buffer_offset;
// Align stride up if required by Vulkan implementation. // Align stride up if required by Vulkan implementation.

View File

@ -42,65 +42,7 @@ Scheduler::Scheduler(const Instance& instance, RenderpassCache& renderpass_cache
Scheduler::~Scheduler() = default; Scheduler::~Scheduler() = default;
void Scheduler::Finish(vk::Semaphore signal, vk::Semaphore wait) { void Scheduler::Flush(std::atomic_bool* submit_done, vk::Semaphore signal, vk::Semaphore wait) {
const u64 presubmit_tick = CurrentTick();
std::atomic_bool submit_done{false};
Flush(signal, wait, &submit_done);
if (use_worker_thread) {
MICROPROFILE_SCOPE(Vulkan_WaitForWorker);
submit_done.wait(false);
}
Wait(presubmit_tick);
}
void Scheduler::DispatchWork() {
if (!use_worker_thread || chunk->Empty()) {
return;
}
{
std::scoped_lock lock{work_mutex};
work_queue.push(std::move(chunk));
}
work_cv.notify_one();
AcquireNewChunk();
}
void Scheduler::WorkerThread(std::stop_token stop_token) {
Common::SetCurrentThreadName("VulkanWorker");
do {
std::unique_ptr<CommandChunk> work;
{
std::unique_lock lock{work_mutex};
Common::CondvarWait(work_cv, lock, stop_token, [&] { return !work_queue.empty(); });
if (stop_token.stop_requested()) {
continue;
}
work = std::move(work_queue.front());
work_queue.pop();
}
const bool has_submit = work->HasSubmit();
work->ExecuteAll(current_cmdbuf);
if (has_submit) {
AllocateWorkerCommandBuffers();
}
std::scoped_lock reserve_lock{reserve_mutex};
chunk_reserve.push_back(std::move(work));
} while (!stop_token.stop_requested());
}
void Scheduler::AllocateWorkerCommandBuffers() {
const vk::CommandBufferBeginInfo begin_info = {
.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit,
};
current_cmdbuf = command_pool.Commit();
current_cmdbuf.begin(begin_info);
}
void Scheduler::Flush(vk::Semaphore signal, vk::Semaphore wait, std::atomic_bool* submit_done) {
const vk::Semaphore handle = master_semaphore.Handle(); const vk::Semaphore handle = master_semaphore.Handle();
const u64 signal_value = master_semaphore.NextTick(); const u64 signal_value = master_semaphore.NextTick();
state = StateFlags::AllDirty; state = StateFlags::AllDirty;
@ -163,6 +105,72 @@ void Scheduler::Flush(vk::Semaphore signal, vk::Semaphore wait, std::atomic_bool
} }
} }
void Scheduler::Finish(vk::Semaphore signal, vk::Semaphore wait) {
const u64 presubmit_tick = CurrentTick();
std::atomic_bool submit_done{false};
Flush(&submit_done, signal, wait);
if (use_worker_thread) {
MICROPROFILE_SCOPE(Vulkan_WaitForWorker);
submit_done.wait(false);
}
Wait(presubmit_tick);
}
void Scheduler::Wait(u64 tick) {
if (tick >= master_semaphore.CurrentTick()) {
// Make sure we are not waiting for the current tick without signalling
Flush();
}
master_semaphore.Wait(tick);
}
void Scheduler::DispatchWork() {
if (!use_worker_thread || chunk->Empty()) {
return;
}
{
std::scoped_lock lock{work_mutex};
work_queue.push(std::move(chunk));
}
work_cv.notify_one();
AcquireNewChunk();
}
void Scheduler::WorkerThread(std::stop_token stop_token) {
Common::SetCurrentThreadName("VulkanWorker");
do {
std::unique_ptr<CommandChunk> work;
{
std::unique_lock lock{work_mutex};
Common::CondvarWait(work_cv, lock, stop_token, [&] { return !work_queue.empty(); });
if (stop_token.stop_requested()) {
continue;
}
work = std::move(work_queue.front());
work_queue.pop();
}
const bool has_submit = work->HasSubmit();
work->ExecuteAll(current_cmdbuf);
if (has_submit) {
AllocateWorkerCommandBuffers();
}
std::scoped_lock reserve_lock{reserve_mutex};
chunk_reserve.push_back(std::move(work));
} while (!stop_token.stop_requested());
}
void Scheduler::AllocateWorkerCommandBuffers() {
const vk::CommandBufferBeginInfo begin_info = {
.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit,
};
current_cmdbuf = command_pool.Commit();
current_cmdbuf.begin(begin_info);
}
void Scheduler::AcquireNewChunk() { void Scheduler::AcquireNewChunk() {
std::scoped_lock lock{reserve_mutex}; std::scoped_lock lock{reserve_mutex};
if (chunk_reserve.empty()) { if (chunk_reserve.empty()) {

View File

@ -39,12 +39,15 @@ public:
~Scheduler(); ~Scheduler();
/// Sends the current execution context to the GPU. /// Sends the current execution context to the GPU.
void Flush(vk::Semaphore signal = nullptr, vk::Semaphore wait = nullptr, void Flush(std::atomic_bool* submit_done = nullptr, vk::Semaphore signal = nullptr,
std::atomic_bool* submit_done = nullptr); vk::Semaphore wait = nullptr);
/// Sends the current execution context to the GPU and waits for it to complete. /// Sends the current execution context to the GPU and waits for it to complete.
void Finish(vk::Semaphore signal = nullptr, vk::Semaphore wait = nullptr); void Finish(vk::Semaphore signal = nullptr, vk::Semaphore wait = nullptr);
/// Waits for the given tick to trigger on the GPU.
void Wait(u64 tick);
/// Sends currently recorded work to the worker thread. /// Sends currently recorded work to the worker thread.
void DispatchWork(); void DispatchWork();
@ -93,16 +96,6 @@ public:
return master_semaphore.IsFree(tick); return master_semaphore.IsFree(tick);
} }
/// Waits for the given tick to trigger on the GPU.
void Wait(u64 tick) {
if (tick >= master_semaphore.CurrentTick()) {
// Make sure we are not waiting for the current tick without signalling
LOG_WARNING(Render_Vulkan, "Flushing current tick");
Flush();
}
master_semaphore.Wait(tick);
}
/// Returns the master timeline semaphore. /// Returns the master timeline semaphore.
[[nodiscard]] MasterSemaphore& GetMasterSemaphore() noexcept { [[nodiscard]] MasterSemaphore& GetMasterSemaphore() noexcept {
return master_semaphore; return master_semaphore;