diff --git a/vktest/src/main.cpp b/vktest/src/main.cpp index 0c03079..fe8b8e3 100644 --- a/vktest/src/main.cpp +++ b/vktest/src/main.cpp @@ -114,6 +114,7 @@ class HelloTriangleApplication std::vector inFlightFences; std::vector imagesInFlight; size_t currentFrame = 0; + bool framebufferResized = false; public: void run() @@ -141,9 +142,11 @@ class HelloTriangleApplication glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr); + glfwSetWindowUserPointer(window, this); + + glfwSetFramebufferSizeCallback(window, framebufferResizeCallback); } void initVulkan() @@ -176,6 +179,8 @@ class HelloTriangleApplication void cleanup() { + cleanupSwapChain(); + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr); @@ -185,21 +190,6 @@ class HelloTriangleApplication 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) @@ -434,6 +424,50 @@ class HelloTriangleApplication swapChainExtent = extent; } + void cleanupSwapChain() + { + for (auto framebuffer : swapChainFramebuffers) + { + vkDestroyFramebuffer(device, framebuffer, nullptr); + } + + vkFreeCommandBuffers(device, commandPool, static_cast(commandBuffers.size()), commandBuffers.data()); + + vkDestroyPipeline(device, graphicsPipeline, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + vkDestroyRenderPass(device, renderPass, nullptr); + + for (auto imageView : swapChainImageViews) + { + vkDestroyImageView(device, imageView, nullptr); + } + + vkDestroySwapchainKHR(device, swapChain, nullptr); + } + + void recreateSwapChain() + { + int width = 0; + int height = 0; + glfwGetFramebufferSize(window, &width, &height); + while (width == 0 || height == 0) + { + glfwGetFramebufferSize(window, &width, &height); + glfwWaitEvents(); + } + + vkDeviceWaitIdle(device); + + cleanupSwapChain(); + + createSwapChain(); + createImageViews(); + createRenderPass(); + createGraphicsPipeline(); + createFramebuffers(); + createCommandBuffers(); + } + void createImageViews() { swapChainImageViews.resize(swapChainImages.size()); @@ -763,7 +797,18 @@ class HelloTriangleApplication vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); 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!"); + } if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) { @@ -806,11 +851,29 @@ class HelloTriangleApplication presentInfo.pImageIndices = &imageIndex; presentInfo.pResults = nullptr; - 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; } + static void framebufferResizeCallback(GLFWwindow* window, int width, int height) + { + auto app = reinterpret_cast(glfwGetWindowUserPointer(window)); + app->framebufferResized = true; + } + private: std::vector getRequiredInstanceExtensions()