diff --git a/vulkan/vulkan_app.cpp b/vulkan/vulkan_app.cpp index 6ae3fb2..8e0cad3 100644 --- a/vulkan/vulkan_app.cpp +++ b/vulkan/vulkan_app.cpp @@ -660,14 +660,16 @@ void Vulkan::createCommandPool(){ } } -void Vulkan::createCommandBuffer(){ +void Vulkan::createCommandBuffers(){ + commandBuffers.resize(MAX_FRAMES_IN_FLIGHT); + VkCommandBufferAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.commandPool = commandPool; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandBufferCount = 1; + allocInfo.commandBufferCount = (uint32_t)commandBuffers.size(); - if(vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer) != VK_SUCCESS){ + if(vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS){ throw std::runtime_error("Func: createCommandBuffer\nError: Failed to allocate Command Buffers!\n"); } } @@ -717,6 +719,10 @@ void Vulkan::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIn } void Vulkan::createSyncObjects(){ + imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT); + renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT); + inFlightFences.resize(MAX_FRAMES_IN_FLIGHT); + VkSemaphoreCreateInfo semaphoreInfo{}; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; @@ -724,40 +730,42 @@ void Vulkan::createSyncObjects(){ fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - if(vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphore) != VK_SUCCESS - || vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphore) != VK_SUCCESS - || vkCreateFence(device, &fenceInfo, nullptr, &inFlightFence) != VK_SUCCESS){ + for(size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++){ + if(vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]) != VK_SUCCESS + || vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS + || vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS){ throw std::runtime_error("Func: createSyncObjects\nError: Failed to create semaphores!\n"); + } } } void Vulkan::drawFrame(){ - vkWaitForFences(device, 1, &inFlightFence, VK_TRUE, UINT64_MAX); - vkResetFences(device, 1, &inFlightFence); + vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); + vkResetFences(device, 1, &inFlightFences[currentFrame]); uint32_t imageIndex; - vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); + vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); - vkResetCommandBuffer(commandBuffer, 0); - recordCommandBuffer(commandBuffer, imageIndex); + vkResetCommandBuffer(commandBuffers[currentFrame], 0); + recordCommandBuffer(commandBuffers[currentFrame], imageIndex); VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - VkSemaphore waitSemaphores[] = { imageAvailableSemaphore }; + VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] }; VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitDstStageMask = waitStages; submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &commandBuffer; + submitInfo.pCommandBuffers = &commandBuffers[currentFrame]; - VkSemaphore signalSemaphore[] = { renderFinishedSemaphore }; + VkSemaphore signalSemaphore[] = { renderFinishedSemaphores[currentFrame] }; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphore; - if(vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFence) != VK_SUCCESS){ + if(vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS){ throw std::runtime_error("Func: drawFrame\nError: Failed to submit draw command buffer!\n"); } @@ -772,6 +780,8 @@ void Vulkan::drawFrame(){ presentInfo.pImageIndices = &imageIndex; vkQueuePresentKHR(presentQueue, &presentInfo); + + currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; } void Vulkan::initWindow(const char* windowName){ @@ -793,7 +803,7 @@ void Vulkan::initVulkan(){ createGraphicsPipeline(); createFrameBuffers(); createCommandPool(); - createCommandBuffer(); + createCommandBuffers(); createSyncObjects(); } @@ -808,9 +818,11 @@ void Vulkan::mainLoop(){ void Vulkan::cleanup(){ // Vulkan - vkDestroySemaphore(device, imageAvailableSemaphore, nullptr); - vkDestroySemaphore(device, renderFinishedSemaphore, nullptr); - vkDestroyFence(device, inFlightFence, nullptr); + for(size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++){ + vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr); + vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr); + vkDestroyFence(device, inFlightFences[i], nullptr); + } vkDestroyCommandPool(device, commandPool, nullptr); diff --git a/vulkan/vulkan_app.hpp b/vulkan/vulkan_app.hpp index 96171da..498f60d 100644 --- a/vulkan/vulkan_app.hpp +++ b/vulkan/vulkan_app.hpp @@ -72,12 +72,15 @@ private: VkPipeline graphicsPipeline; VkCommandPool commandPool; - VkCommandBuffer commandBuffer; + std::vector commandBuffers; - VkSemaphore imageAvailableSemaphore, renderFinishedSemaphore; - VkFence inFlightFence; + std::vector imageAvailableSemaphores, renderFinishedSemaphores; + std::vector inFlightFences; std::vector swapChainFramebuffers; + + const int MAX_FRAMES_IN_FLIGHT = 2; + uint32_t currentFrame = 0; #pragma endregion bool checkValidationLayerSupport(); @@ -102,7 +105,7 @@ private: void createRenderPass(); void createFrameBuffers(); void createCommandPool(); - void createCommandBuffer(); + void createCommandBuffers(); void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex); void createSyncObjects(); void drawFrame();