From a6c3d2b0f279f0e3b2509b938cb5ae7373f3a6a4 Mon Sep 17 00:00:00 2001 From: Warwick Date: Thu, 16 Jan 2025 17:18:30 +0000 Subject: [PATCH] quick and dirty frames in flight --- CMakeLists.txt | 20 ++++++++-------- src/main.c | 62 ++++++++++++++++++++++++++++---------------------- 2 files changed, 45 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 32d6744..9dbe85e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,16 +30,16 @@ file(GLOB_RECURSE HEADER_FILES ${CMAKE_SOURCE_DIR}/src/*.h) add_executable(${PROJECT_NAME} ${HEADER_FILES} ${SOURCE_FILES}) -# Error on memory address issues in debug mode -if(CMAKE_BUILD_TYPE MATCHES "Debug") - set( - CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} -Werror -fsanitize=undefined -fsanitize=address" - ) - target_link_options(${PROJECT_NAME} - BEFORE PUBLIC -fsanitize=undefined PUBLIC -fsanitize=address - ) -endif() +## Error on memory address issues in debug mode +#if(CMAKE_BUILD_TYPE MATCHES "Debug") +# set( +# CMAKE_C_FLAGS +# "${CMAKE_C_FLAGS} -Werror -fsanitize=undefined -fsanitize=address" +# ) +# target_link_options(${PROJECT_NAME} +# BEFORE PUBLIC -fsanitize=undefined PUBLIC -fsanitize=address +# ) +#endif() # Link Libraries target_link_libraries(${PROJECT_NAME} diff --git a/src/main.c b/src/main.c index 014847b..71d9893 100644 --- a/src/main.c +++ b/src/main.c @@ -18,6 +18,8 @@ const bool enableValidationLayers = false; const bool enableValidationLayers = true; #endif +#define MAX_FRAMES_IN_FLIGHT 2 + static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -61,11 +63,11 @@ typedef struct Application { VkFramebuffer *swapChainFramebuffers; uint32_t swapChainFramebufferCount; VkCommandPool commandPool; - VkCommandBuffer commandBuffer; - VkSemaphore imageAvailableSemaphore; - VkSemaphore renderFinishedSemaphore; - VkFence inFlightFence; - + VkCommandBuffer commandBuffers[MAX_FRAMES_IN_FLIGHT]; + VkSemaphore imageAvailableSemaphore[MAX_FRAMES_IN_FLIGHT]; + VkSemaphore renderFinishedSemaphore[MAX_FRAMES_IN_FLIGHT]; + VkFence inFlightFence[MAX_FRAMES_IN_FLIGHT]; + uint32_t currentFrame; // initialised to 0 } Application; typedef struct SwapChainSupportDetails { @@ -976,9 +978,9 @@ void createCommandBuffer(Application *app) { allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.commandPool = app->commandPool; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandBufferCount = 1; + allocInfo.commandBufferCount = MAX_FRAMES_IN_FLIGHT; - if (vkAllocateCommandBuffers(app->device, &allocInfo, &app->commandBuffer) != + if (vkAllocateCommandBuffers(app->device, &allocInfo, app->commandBuffers) != VK_SUCCESS) { fprintf(stderr, "Failed to allocate command buffers!"); exit(EXIT_FAILURE); @@ -993,14 +995,16 @@ void createSyncObjects(Application *app) { fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - if (vkCreateSemaphore(app->device, &semaphoreInfo, NULL, - &app->imageAvailableSemaphore) != VK_SUCCESS || - vkCreateSemaphore(app->device, &semaphoreInfo, NULL, - &app->renderFinishedSemaphore) != VK_SUCCESS || - vkCreateFence(app->device, &fenceInfo, NULL, &app->inFlightFence) != - VK_SUCCESS) { - fprintf(stderr, "Failed to create semaphores!"); - exit(EXIT_FAILURE); + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + if (vkCreateSemaphore(app->device, &semaphoreInfo, NULL, + &app->imageAvailableSemaphore[i]) != VK_SUCCESS || + vkCreateSemaphore(app->device, &semaphoreInfo, NULL, + &app->renderFinishedSemaphore[i]) != VK_SUCCESS || + vkCreateFence(app->device, &fenceInfo, NULL, &app->inFlightFence[i]) != + VK_SUCCESS) { + fprintf(stderr, "Failed to create semaphores!"); + exit(EXIT_FAILURE); + } } } @@ -1021,32 +1025,32 @@ void initVulkan(Application *app) { } void drawFrame(Application *app) { - vkWaitForFences(app->device, 1, &app->inFlightFence, VK_TRUE, UINT64_MAX); - vkResetFences(app->device, 1, &app->inFlightFence); + vkWaitForFences(app->device, 1, &app->inFlightFence[app->currentFrame], VK_TRUE, UINT64_MAX); + vkResetFences(app->device, 1, &app->inFlightFence[app->currentFrame]); uint32_t imageIndex; vkAcquireNextImageKHR(app->device, app->swapChain, UINT64_MAX, - app->imageAvailableSemaphore, VK_NULL_HANDLE, + app->imageAvailableSemaphore[app->currentFrame], VK_NULL_HANDLE, &imageIndex); - vkResetCommandBuffer(app->commandBuffer, 0); - recordCommandBuffer(app, app->commandBuffer, imageIndex); + vkResetCommandBuffer(app->commandBuffers[app->currentFrame], 0); + recordCommandBuffer(app, app->commandBuffers[app->currentFrame], imageIndex); VkSubmitInfo submitInfo = {0}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - VkSemaphore waitSemaphores[] = {app->imageAvailableSemaphore}; + VkSemaphore waitSemaphores[] = {app->imageAvailableSemaphore[app->currentFrame]}; VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitDstStageMask = waitStages; submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &app->commandBuffer; - VkSemaphore signalSemaphores[] = {app->renderFinishedSemaphore}; + submitInfo.pCommandBuffers = &app->commandBuffers[app->currentFrame]; + VkSemaphore signalSemaphores[] = {app->renderFinishedSemaphore[app->currentFrame]}; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; - if (vkQueueSubmit(app->graphicsQueue, 1, &submitInfo, app->inFlightFence) != + if (vkQueueSubmit(app->graphicsQueue, 1, &submitInfo, app->inFlightFence[app->currentFrame]) != VK_SUCCESS) { fprintf(stderr, "failed to submit draw command buffer!"); exit(EXIT_FAILURE); @@ -1063,6 +1067,8 @@ void drawFrame(Application *app) { presentInfo.pResults = NULL; // Optional vkQueuePresentKHR(app->presentQueue, &presentInfo); + + app->currentFrame = (app->currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; } void mainLoop(Application *app) { @@ -1075,9 +1081,11 @@ void mainLoop(Application *app) { } void cleanup(Application *app) { - vkDestroySemaphore(app->device, app->imageAvailableSemaphore, NULL); - vkDestroySemaphore(app->device, app->renderFinishedSemaphore, NULL); - vkDestroyFence(app->device, app->inFlightFence, NULL); + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + vkDestroySemaphore(app->device, app->imageAvailableSemaphore[i], NULL); + vkDestroySemaphore(app->device, app->renderFinishedSemaphore[i], NULL); + vkDestroyFence(app->device, app->inFlightFence[i], NULL); + } vkDestroyCommandPool(app->device, app->commandPool, NULL); for (uint i = 0; i < app->swapChainFramebufferCount; i++) { vkDestroyFramebuffer(app->device, app->swapChainFramebuffers[i], NULL);