renderer_vulkan: Small cleanups
This commit is contained in:
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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()) {
|
||||||
|
@ -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;
|
||||||
|
Reference in New Issue
Block a user