diff --git a/src/pc/gfx/gfx_vulkan.cpp b/src/pc/gfx/gfx_vulkan.cpp index f3a7e99..387c511 100644 --- a/src/pc/gfx/gfx_vulkan.cpp +++ b/src/pc/gfx/gfx_vulkan.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "gfx_rendering_api.h" #include "gfx_pc.h" @@ -22,6 +23,15 @@ static std::vector swapchain_images; static std::vector swapchain_views; static VkRenderPass render_pass = VK_NULL_HANDLE; +// TODO: removed hardcoded 3 frame queue, should be variable +static std::array command_buffers; +static std::array image_available; +static std::array render_finished; +static std::array in_flight; +static uint32_t current_frame = 0; +static uint32_t image_index = 0; +static VkCommandBuffer current_cmd = VK_NULL_HANDLE; + VKAPI_ATTR VkBool32 VKAPI_CALL gfx_vulkan_debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -415,11 +425,37 @@ static void gfx_vulkan_create_render_pass() { vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass); } +static void gfx_vulkan_create_sync() { + for(int i = 0; i < 3; i++) { + VkCommandBufferAllocateInfo allocate_info = {}; + allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocate_info.commandPool = command_pool; + allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocate_info.commandBufferCount = 1; + + vkAllocateCommandBuffers(device, &allocate_info, &command_buffers[i]); + } + + VkSemaphoreCreateInfo semaphore_create_info = {}; + semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkFenceCreateInfo fence_create_info = {}; + fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_create_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + for (size_t i = 0; i < 3; i++) { + vkCreateSemaphore(device, &semaphore_create_info, nullptr, &image_available[i]); + vkCreateSemaphore(device, &semaphore_create_info, nullptr, &render_finished[i]); + vkCreateFence(device, &fence_create_info, nullptr, &in_flight[i]); + } +} + static void gfx_vulkan_renderer_init(void) { gfx_vulkan_create_instance(); gfx_vulkan_create_device(); gfx_vulkan_create_swapchain(); gfx_vulkan_create_render_pass(); + gfx_vulkan_create_sync(); } static void gfx_vulkan_renderer_on_resize(void) { @@ -427,12 +463,73 @@ static void gfx_vulkan_renderer_on_resize(void) { } static void gfx_vulkan_renderer_start_frame(void) { + vkWaitForFences( + device, 1, + &in_flight[current_frame], + VK_TRUE, std::numeric_limits::max()); + + image_index = 0; + VkResult result = vkAcquireNextImageKHR( + device, swapchain, + std::numeric_limits::max(), + image_available[current_frame], + VK_NULL_HANDLE, &image_index); + + if (result == VK_ERROR_OUT_OF_DATE_KHR) { + printf("Swapchain is out of date!\n"); + return; + } + + current_cmd = command_buffers[current_frame]; + + VkCommandBufferBeginInfo beginInfo = {}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; + + vkBeginCommandBuffer(current_cmd, &beginInfo); } static void gfx_vulkan_renderer_end_frame(void) { + vkEndCommandBuffer(current_cmd); } static void gfx_vulkan_renderer_finish_render(void) { + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + + VkSemaphore wait_semaphores[] = {image_available[current_frame]}; + VkPipelineStageFlags wait_stages[] = { + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; + submit_info.waitSemaphoreCount = 1; + submit_info.pWaitSemaphores = wait_semaphores; + submit_info.pWaitDstStageMask = wait_stages; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = ¤t_cmd; + + VkSemaphore signal_semaphores[] = {render_finished[current_frame]}; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = signal_semaphores; + + vkResetFences(device, 1, &in_flight[current_frame]); + + if (vkQueueSubmit(graphics_queue, 1, &submit_info, in_flight[current_frame]) != VK_SUCCESS) { + return; + } + + // present + VkPresentInfoKHR present_info = {}; + present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + + present_info.waitSemaphoreCount = 1; + present_info.pWaitSemaphores = signal_semaphores; + VkSwapchainKHR swapChains[] = {swapchain}; + present_info.swapchainCount = 1; + present_info.pSwapchains = swapChains; + present_info.pImageIndices = &image_index; + + vkQueuePresentKHR(present_queue, &present_info); + + current_frame = (current_frame + 1) % 3; } static const char* gfx_vulkan_get_name() {