diff --git a/Hello_triangle/main.cpp b/Hello_triangle/main.cpp index 217ca7e..50ac839 100644 --- a/Hello_triangle/main.cpp +++ b/Hello_triangle/main.cpp @@ -69,6 +69,7 @@ const std::vector deviceExtensions = { std::vector imageAvailableSemaphores; std::vector renderFinishedSemaphores; std::vector inFlightFences; + bool framebufferResized = false; uint32_t currentFrame = 0; @@ -83,9 +84,17 @@ const std::vector deviceExtensions = { glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr); + glfwSetWindowUserPointer(window, this); + glfwSetFramebufferSizeCallback(window, framebufferResizeCallback); + } + + + static void framebufferResizeCallback(GLFWwindow* window, int width, int height) { + auto app = reinterpret_cast(glfwGetWindowUserPointer(window)); + app->framebufferResized = true; } void initVulkan() { @@ -104,6 +113,41 @@ const std::vector deviceExtensions = { createSyncObjects(); } + + void recreateSwapChain() { + int width = 0, height = 0; + glfwGetFramebufferSize(window, &width, &height); + + while (width == 0 || height == 0) { + glfwGetFramebufferSize(window, &width, &height); + glfwWaitEvents(); + } + + + vkDeviceWaitIdle(device); + + cleanupSwapChain(); + + createSwapChain(); + createImageViews(); + createFramebuffers(); + + } + + void cleanupSwapChain() { + for (size_t i = 0; i < swapchainFrameBuffers.size(); i++) { + vkDestroyFramebuffer(device, swapchainFrameBuffers[i], nullptr); + } + + for (size_t i = 0; i < swapChainImageViews.size(); i++) { + vkDestroyImageView(device, swapChainImageViews[i], nullptr); + } + + vkDestroySwapchainKHR(device, swapChain, nullptr); + + } + + void createSyncObjects() { imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT); renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT); @@ -867,10 +911,19 @@ const std::vector deviceExtensions = { void drawFrame() { vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); - vkResetFences(device, 1, &inFlightFences[currentFrame]); uint32_t imageIndex; - vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); + VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); + + if (result == VK_ERROR_OUT_OF_DATE_KHR) { + recreateSwapChain(); + return; + } + else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { + throw std::runtime_error("failed to acquire swap chain image!"); + } + + vkResetFences(device, 1, &inFlightFences[currentFrame]); vkResetCommandBuffer(commandBuffers[currentFrame], 0); recordCommandBuffer(commandBuffers[currentFrame], imageIndex); @@ -906,14 +959,27 @@ const std::vector deviceExtensions = { 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 || framebufferResized) { + framebufferResized = false; + recreateSwapChain(); + } + else if (result != VK_SUCCESS) { + throw std::runtime_error("failed to present swap chain image!"); + } currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; - - } void cleanup(){ + cleanupSwapChain(); + + + vkDestroyPipeline(device, graphicsPipeline, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + vkDestroyRenderPass(device, renderPass, nullptr); + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr); vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr); @@ -923,19 +989,6 @@ const std::vector deviceExtensions = { vkDestroyCommandPool(device, commandPool, nullptr); - for (auto framebuffer : swapchainFrameBuffers) { - vkDestroyFramebuffer(device, framebuffer, 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); if(enableValidationLayers){