From 3e43d096fca48504a9d6c0f777ce2e240dc18bf1 Mon Sep 17 00:00:00 2001 From: Benjamin Kraft Date: Wed, 28 Aug 2024 17:08:52 +0200 Subject: [PATCH] Added resizing --- CMakeLists.txt | 1 + main.cpp | 105 ++++++++++++++++++++++++++++++++++--------------- 2 files changed, 74 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0333f4b..a9c5c78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,5 +6,6 @@ set(CMAKE_CXX_STANDARD 20) add_executable(VulkanSimulation main.cpp) find_package(Vulkan REQUIRED) +find_package(glfw3 REQUIRED) target_link_libraries(VulkanSimulation glfw Vulkan::Vulkan) diff --git a/main.cpp b/main.cpp index 636b4a5..e6037e9 100644 --- a/main.cpp +++ b/main.cpp @@ -12,6 +12,7 @@ #include #include #include +#include const std::vector deviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME @@ -52,6 +53,7 @@ bool checkValidationLayerSupport(){ } #endif +constexpr int MAX_FRAMES_IN_FLIGHT = 2; std::vector readFile(const std::string& fileName){ std::ifstream file(fileName, std::ios::ate | std::ios::binary); @@ -87,7 +89,7 @@ private: void initWindow(){ glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); window = glfwCreateWindow((int)WIDTH, (int)HEIGHT, "Vulkan Simulation", nullptr, nullptr); } void initVulkan(){ @@ -101,7 +103,7 @@ private: createGraphicsPipeline(); createFramebuffers(); createCommandPool(); - createCommandBuffer(); + createCommandBuffers(); createSyncObjects(); } @@ -403,6 +405,26 @@ private: swapchainExtent = extent; } + void cleanupSwapchain(){ + for (auto framebuffer : swapchainFramebuffers){ + vkDestroyFramebuffer(device, framebuffer, nullptr); + } + for (auto imageView : swapchainImageViews){ + vkDestroyImageView(device, imageView, nullptr); + } + vkDestroySwapchainKHR(device, swapchain, nullptr); + } + + void recreateSwapchain(){ + vkDeviceWaitIdle(device); + + cleanupSwapchain(); + + createSwapchain(); + createImageViews(); + createFramebuffers(); + } + VkSwapchainKHR swapchain = VK_NULL_HANDLE; std::vector swapchainImages; VkFormat swapchainImageFormat {}; @@ -615,7 +637,8 @@ private: } VkCommandPool commandPool = VK_NULL_HANDLE; - VkCommandBuffer commandBuffer = VK_NULL_HANDLE; + + std::vector commandBuffers; void createCommandPool(){ QueueFamilyIndices indices = findQueueFamilies(physicalDevice); @@ -628,14 +651,16 @@ private: vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool); } - void createCommandBuffer(){ + void createCommandBuffers(){ + commandBuffers.resize(MAX_FRAMES_IN_FLIGHT); + VkCommandBufferAllocateInfo allocateInfo {}; allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocateInfo.commandPool = commandPool; allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocateInfo.commandBufferCount = 1; + allocateInfo.commandBufferCount = commandBuffers.size(); - vkAllocateCommandBuffers(device, &allocateInfo, &commandBuffer); + vkAllocateCommandBuffers(device, &allocateInfo, commandBuffers.data()); } void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex){ @@ -678,11 +703,15 @@ private: vkEndCommandBuffer(commandBuffer); } - VkSemaphore imageAvailable = VK_NULL_HANDLE; - VkSemaphore renderFinished = VK_NULL_HANDLE; - VkFence inFlight = VK_NULL_HANDLE; + std::vector imageAvailableSemaphores; + std::vector renderFinishedSemaphores; + std::vector inFlightFences; void 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; @@ -690,36 +719,46 @@ private: fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailable); - vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinished); - vkCreateFence(device, &fenceInfo, nullptr, &inFlight); + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++){ + vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]); + vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]); + vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]); + } } + size_t currentFrame = 0; + void drawFrame(){ - vkWaitForFences(device, 1, &inFlight, VK_TRUE, UINT64_MAX); - vkResetFences(device, 1, &inFlight); + vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); uint32_t imageIndex; - vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, imageAvailable, VK_NULL_HANDLE, &imageIndex); - vkResetCommandBuffer(commandBuffer, 0); - recordCommandBuffer(commandBuffer, imageIndex); + VkResult result = vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); + if (result == VK_ERROR_OUT_OF_DATE_KHR){ + recreateSwapchain(); + return; + } + + vkResetFences(device, 1, &inFlightFences[currentFrame]); + + vkResetCommandBuffer(commandBuffers[currentFrame], 0); + recordCommandBuffer(commandBuffers[currentFrame], imageIndex); VkSubmitInfo submitInfo {}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - VkSemaphore waitSemaphores[] = {imageAvailable}; + 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 signalSemaphores[] = {renderFinished}; + VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]}; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; - vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlight); + vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]); VkPresentInfoKHR presentInfo {}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; @@ -731,7 +770,13 @@ private: presentInfo.pSwapchains = swapchains; presentInfo.pImageIndices = &imageIndex; - vkQueuePresentKHR(presentQueue, &presentInfo); + result = vkQueuePresentKHR(presentQueue, &presentInfo); + if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR){ + recreateSwapchain(); + return; + } + + currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; } void mainLoop(){ @@ -743,20 +788,16 @@ private: vkDeviceWaitIdle(device); } void cleanup(){ - vkDestroySemaphore(device, imageAvailable, nullptr); - vkDestroySemaphore(device, renderFinished, nullptr); - vkDestroyFence(device, inFlight, nullptr); - vkDestroyCommandPool(device, commandPool, nullptr); - for (auto framebuffer : swapchainFramebuffers){ - vkDestroyFramebuffer(device, framebuffer, nullptr); + cleanupSwapchain(); + 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); vkDestroyPipeline(device, graphicsPipeline, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyRenderPass(device, renderPass, nullptr); - for (auto imageView : swapchainImageViews){ - vkDestroyImageView(device, imageView, nullptr); - } - vkDestroySwapchainKHR(device, swapchain, nullptr); vkDestroyDevice(device, nullptr); vkDestroySurfaceKHR(instance, surface, nullptr); vkDestroyInstance(instance, nullptr);