From 7c4abd18f453011c7ad45929f7d0df76d3b3a25a Mon Sep 17 00:00:00 2001 From: ladevieq Date: Mon, 13 Mar 2023 01:05:09 +0100 Subject: Improve command buffer allocation function Implement virtual frame using new API --- api-test/main.cpp | 119 ++++++++++++++++++++++++++++------------- include/api-test/vk-device.hpp | 6 +-- 2 files changed, 85 insertions(+), 40 deletions(-) diff --git a/api-test/main.cpp b/api-test/main.cpp index ee09f69..583bced 100644 --- a/api-test/main.cpp +++ b/api-test/main.cpp @@ -1,7 +1,9 @@ #include #include +#include #include #include +#include #include #define STB_IMAGE_IMPLEMENTATION @@ -35,10 +37,23 @@ RENDERDOC_API_1_4_1 *rdoc_api = nullptr; static constexpr size_t Kb = 1024U; static constexpr size_t Mb = 1024U * Kb; -void ui() { +void ui(uint32_t frame_time) { + static float max_fps = 0.f; + static uint32_t max_frame_time = 1000U; + float fps = 1000000U / frame_time; + if (fps > max_fps) { + max_fps = fps; + } + if (frame_time > max_frame_time) { + max_frame_time = frame_time; + } ImGui::NewFrame(); - bool open = true; - ImGui::ShowDemoWindow(&open); + // bool open = true; + // ImGui::ShowDemoWindow(&open); + ImGui::Text("FPS : %f\n", fps); + ImGui::Text("Max FPS : %f\n", max_fps); + ImGui::Text("frame_time : %f ms\n", frame_time / 1000.f); + ImGui::Text("max frame_time : %f ms\n", max_frame_time / 1000.f); ImGui::EndFrame(); ImGui::Render(); } @@ -87,7 +102,7 @@ int main() { .format = VK_FORMAT_B8G8R8A8_UNORM, .colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, }, - .present_mode = VK_PRESENT_MODE_FIFO_KHR, + .present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR, .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, }); auto& surface = device.get_surface(surface_handle); @@ -191,26 +206,36 @@ int main() { auto semaphore = device.create_semaphore({ .type = VK_SEMAPHORE_TYPE_TIMELINE, }); - auto acquire_semaphore = device.create_semaphore({ - .type = VK_SEMAPHORE_TYPE_BINARY, - }); + constexpr uint32_t virtual_frames_count = 2U; + handle submit_semaphores[virtual_frames_count]; + for (auto& submit_semaphore : submit_semaphores) { + submit_semaphore = device.create_semaphore({ + .type = VK_SEMAPHORE_TYPE_BINARY, + }); + } + handle acquire_semaphores[virtual_frames_count]; + for (auto& acquire_semaphore : acquire_semaphores) { + acquire_semaphore = device.create_semaphore({ + .type = VK_SEMAPHORE_TYPE_BINARY, + }); + } - std::array command_buffers; - device.allocate_command_buffers(command_buffers.data(), 2, QueueType::GRAPHICS); + std::array graphics_command_buffers; + device.allocate_command_buffers(graphics_command_buffers, QueueType::GRAPHICS); RD_START_CAPTURE; - command_buffers[0].start(); + graphics_command_buffers[0].start(); - command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - command_buffers[0].barrier(ui_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - command_buffers[0].copy(staging_buffer_handle, gpu_texture_handle); - command_buffers[0].copy(staging_buffer_handle, second_texture, static_cast(offset)); - command_buffers[0].copy(staging_buffer_handle, ui_texture_handle, static_cast(ui_offset)); + graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + graphics_command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + graphics_command_buffers[0].barrier(ui_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + graphics_command_buffers[0].copy(staging_buffer_handle, gpu_texture_handle); + graphics_command_buffers[0].copy(staging_buffer_handle, second_texture, static_cast(offset)); + graphics_command_buffers[0].copy(staging_buffer_handle, ui_texture_handle, static_cast(ui_offset)); - command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); - command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); + graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); + graphics_command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); struct compute_params { uint32_t input1; @@ -225,27 +250,34 @@ int main() { }; memcpy(uniform_buffer.mapped_ptr, ¶ms, sizeof(params)); - command_buffers[0].dispatch({ + graphics_command_buffers[0].dispatch({ .pipeline = compute, .group_size = { .vec = { image_size, image_size, 1U }}, .local_group_size = { .vec = { 8U, 8U, 1U }}, .uniforms_offset = 0U, }); - command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - command_buffers[0].stop(); + graphics_command_buffers[0].stop(); - std::array compute_command_buffers = {command_buffers[0]}; - device.submit(compute_command_buffers, {}, semaphore); + device.submit(std::span { static_cast(graphics_command_buffers.data()), 1 }, {}, semaphore); RD_END_CAPTURE; - std::array ui_command_buffers = {command_buffers[1]}; + // std::array ui_command_buffers = {command_buffers[1]}; std::array, 1U> color_attachment {}; + uint32_t frame_time; + uint32_t frame_count = 0U; while(wnd.isOpen) { + auto start = std::chrono::system_clock::now(); wnd.poll_events(); + uint32_t virtual_frame_index = frame_count % virtual_frames_count; + auto& submit_semaphore = submit_semaphores[virtual_frame_index]; + auto& acquire_semaphore = acquire_semaphores[virtual_frame_index]; + auto command_buffers = std::span { static_cast(graphics_command_buffers.data() + virtual_frame_index + 1U), 1 }; + graphics_command_buffer& command_buffer = graphics_command_buffers[virtual_frame_index + 1U]; for (auto& event : wnd.events) { if (event.type == EVENT_TYPES::MOUSE_MOVE) { io.MousePos.x = static_cast(event.x); @@ -255,21 +287,22 @@ int main() { io.MouseDown[0] = event.type == EVENT_TYPES::BUTTON_PRESS; } - ui(); + ui(frame_time); auto* draw_data = ImGui::GetDrawData(); update_buffers(draw_data, vertex_buffer, index_buffer); - device.wait(semaphore); + // device.wait(semaphore); + device.wait(submit_semaphore); surface.acquire_image_index(acquire_semaphore); color_attachment[0] = surface.get_backbuffer_image(); RD_START_CAPTURE; - command_buffers[1].start(), + command_buffer.start(), - command_buffers[1].barrier(surface.get_backbuffer_image(), VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, VK_ACCESS_2_NONE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - command_buffers[1].begin_renderpass({ + command_buffer.barrier(surface.get_backbuffer_image(), VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, VK_ACCESS_2_NONE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + command_buffer.begin_renderpass({ .render_area = { .x = static_cast(draw_data->DisplayPos.x), .y = static_cast(draw_data->DisplayPos.y), @@ -305,7 +338,7 @@ int main() { .texture_index = ui_texture.get_sampled_index(), }; - command_buffers[1].render({ + command_buffer.render({ .pipeline = graphics, .index_buffer = index_buffer_handle, .vertex_count = draw_command.ElemCount, @@ -321,14 +354,21 @@ int main() { memcpy(uniform_buffer.mapped_ptr, draws.data(), sizeof(draw_params) * draw_index); - command_buffers[1].end_renderpass(); - command_buffers[1].barrier(surface.get_backbuffer_image(), VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + command_buffer.end_renderpass(); + command_buffer.barrier(surface.get_backbuffer_image(), VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + + command_buffer.stop(); + + // device.submit(command_buffers, acquire_semaphore, semaphore); + // device.wait(semaphore); + // device.present(surface_handle, {}); - command_buffers[1].stop(); + device.submit(command_buffers, acquire_semaphore, submit_semaphore); + device.present(surface_handle, submit_semaphore); + + auto end = std::chrono::system_clock::now(); + frame_time = std::chrono::duration_cast(end - start).count(); - device.submit(ui_command_buffers, acquire_semaphore, semaphore); - device.wait(semaphore); - device.present(surface_handle, {}); RD_END_CAPTURE; } @@ -340,7 +380,12 @@ int main() { device.destroy_pipeline(graphics); device.destroy_semaphore(semaphore); - device.destroy_semaphore(acquire_semaphore); + for (auto& submit_semaphore : submit_semaphores) { + device.destroy_semaphore(submit_semaphore); + } + for (auto& acquire_semaphore : acquire_semaphores) { + device.destroy_semaphore(acquire_semaphore); + } device.destroy_texture(gpu_texture_handle); device.destroy_texture(second_texture); diff --git a/include/api-test/vk-device.hpp b/include/api-test/vk-device.hpp index ca5457a..1ece366 100644 --- a/include/api-test/vk-device.hpp +++ b/include/api-test/vk-device.hpp @@ -49,9 +49,9 @@ class vkdevice { void destroy_surface(handle handle); - template - void allocate_command_buffers(cmd_buf_type* buffers, size_t count, QueueType queue_type) { - allocate_command_buffers(static_cast(buffers), count, queue_type); + template + void allocate_command_buffers(array_type& buffers, QueueType queue_type) { + allocate_command_buffers(static_cast(buffers.data()), buffers.size(), queue_type); } [[nodiscard]] inline device_texture& get_texture(handle handle) { -- cgit v1.3