1
Fork 0

Add Vulkan sync primitives

This commit is contained in:
Joshua Goins 2022-10-04 10:01:45 -04:00
parent 7def557f92
commit e5c0552585

View file

@ -5,6 +5,7 @@
#include <cstring>
#include <cstdio>
#include <array>
#include <limits>
#include "gfx_rendering_api.h"
#include "gfx_pc.h"
@ -22,6 +23,15 @@ static std::vector<VkImage> swapchain_images;
static std::vector<VkImageView> swapchain_views;
static VkRenderPass render_pass = VK_NULL_HANDLE;
// TODO: removed hardcoded 3 frame queue, should be variable
static std::array<VkCommandBuffer, 3> command_buffers;
static std::array<VkSemaphore, 3> image_available;
static std::array<VkSemaphore, 3> render_finished;
static std::array<VkFence, 3> 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<uint64_t>::max());
image_index = 0;
VkResult result = vkAcquireNextImageKHR(
device, swapchain,
std::numeric_limits<uint64_t>::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 = &current_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() {