From c6d688a055d6443f52b13be0922bef5643986857 Mon Sep 17 00:00:00 2001 From: InkSoul Date: Sun, 10 Mar 2024 22:13:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90swapchain=E9=9A=8F=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E5=A4=A7=E5=B0=8F=E6=94=B9=E5=8F=98=E9=87=8D=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VulkanTutorial.cpp | 153 +++++++++++++++++++++++++++++++++------------ VulkanTutorial.h | 24 ++++--- 2 files changed, 131 insertions(+), 46 deletions(-) diff --git a/VulkanTutorial.cpp b/VulkanTutorial.cpp index d0fd263..78a3c61 100644 --- a/VulkanTutorial.cpp +++ b/VulkanTutorial.cpp @@ -22,12 +22,14 @@ const bool enableValidationLayers = true; #endif // NDEBUG //window init -GLFWwindow* HelloTriangleApplication::initWindow(int Width, int Height) { +void HelloTriangleApplication::initWindow(int Width, int Height) { glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); window = glfwCreateWindow(Width, Height, "vulkan", nullptr, nullptr); - return window; + glfwSetWindowUserPointer(window, this); + glfwSetFramebufferSizeCallback(window, framebufferResizeCallback); + } // vulkan instace create void HelloTriangleApplication::createInstance() { @@ -110,7 +112,7 @@ void HelloTriangleApplication::initVulkan() { createSwapChain(); - creatImageView(); + createImageView(); createRenderPass(); createGraphicPipeline(); @@ -143,38 +145,32 @@ void HelloTriangleApplication::mainLoop(GLFWwindow* window){ void HelloTriangleApplication::cleanup(GLFWwindow* window) { - std::cout << "\nstart to destroy resource\n" << std::endl; + std::cout << "\n======== start to destroy resource ========\n" << std::endl; - vkDestroySemaphore(device, imageAvailableSemaphore, nullptr); - vkDestroySemaphore(device, renderFinishedSemaphore, nullptr); - vkDestroyFence(device, inFlightFence, nullptr); - - vkDestroyCommandPool(device, commandPool, nullptr); - - for (auto framebuffer : swapChainFramebuffers) - { - vkDestroyFramebuffer(device, framebuffer, nullptr); - } + cleanupSwapChain(); vkDestroyPipeline(device, graphicsPipeline, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyRenderPass(device, renderPass, nullptr); - for (auto imageView : swapChainImageViews) + for (size_t i = 0; i < MAX_FRAME_IN_FLIGHT; i++) { - vkDestroyImageView(device, imageView, nullptr); + vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr); + vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr); + vkDestroyFence(device, inFlightFences[i], nullptr); } + - vkDestroySwapchainKHR(device, swapChain, nullptr); - - vkDestroySurfaceKHR(instance, surface, nullptr); + vkDestroyCommandPool(device, commandPool, nullptr); + + vkDestroyDevice(device, nullptr); if (enableValidationLayers) { DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); } - vkDestroyDevice(device, nullptr); + vkDestroySurfaceKHR(instance, surface, nullptr); vkDestroyInstance(instance, nullptr); @@ -561,7 +557,47 @@ void HelloTriangleApplication::createSwapChain() } -void HelloTriangleApplication::creatImageView() +void HelloTriangleApplication::cleanupSwapChain() +{ + for (auto framebuffer : swapChainFramebuffers) + { + vkDestroyFramebuffer(device, framebuffer, nullptr); + } + + for (auto imageView : swapChainImageViews) + { + vkDestroyImageView(device, imageView, nullptr); + } + + vkDestroySwapchainKHR(device, swapChain, nullptr); + +} + +void HelloTriangleApplication::recreateSwapChain() +{ + + int width = 0, height = 0; + glfwGetFramebufferSize(window, &width, &height); + while (width == 0 || height == 0) + { + if (glfwWindowShouldClose(window)) + { + return; + } + glfwGetFramebufferSize(window, &width, &height); + glfwWaitEvents(); + } + + vkDeviceWaitIdle(device); + + cleanupSwapChain(); + + createSwapChain(); + createImageView(); + creatFramebuffers(); +} + +void HelloTriangleApplication::createImageView() { swapChainImageViews.resize(swapChainImages.size()); @@ -673,13 +709,15 @@ void HelloTriangleApplication::createCommandPool() void HelloTriangleApplication::createCommandBuffer() { + commandBuffers.resize(MAX_FRAME_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("failed to allocate command buffers in createCommandBuffer"); } @@ -737,33 +775,46 @@ void HelloTriangleApplication::recordCommandBuffer(VkCommandBuffer commandBuffer void HelloTriangleApplication::drawFrame() { - //等待所有fence收到信号后返回,uint64_max禁用超时 - vkWaitForFences(device, 1, &inFlightFence, VK_TRUE, UINT64_MAX); - - vkResetFences(device, 1, &inFlightFence); - + uint32_t currentFrame = 0; uint32_t imageIndex; - vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); + //等待所有fence收到信号后返回,uint64_max禁用超时 + vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); - 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; + } + else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) + { + throw std::runtime_error("failed to acquire swap chain image in drawFrame"); + } + + vkResetFences(device, 1, &inFlightFences[currentFrame]); + + //vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &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 signalSemaphores[] = { renderFinishedSemaphore }; + VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame]}; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; - if (vkQueueSubmit(graphicQueue,1,&submitInfo,inFlightFence) != VK_SUCCESS) + if (vkQueueSubmit(graphicQueue,1,&submitInfo,inFlightFences[currentFrame]) != VK_SUCCESS) { throw std::runtime_error("failed to submit draw command buffer in drawFrame"); } @@ -779,12 +830,29 @@ void HelloTriangleApplication::drawFrame() presentInfo.pSwapchains = swapChains; presentInfo.pImageIndices = &imageIndex; presentInfo.pResults = nullptr; - vkQueuePresentKHR(presentQueue, &presentInfo); + //vkQueuePresentKHR(presentQueue, &presentInfo); + + result = vkQueuePresentKHR(presentQueue, &presentInfo); + if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) + { + framebufferResized = false; + recreateSwapChain(); + } + else if (result != VK_SUCCESS) + { + throw std::runtime_error("failed to present swap chain image in drawFrame"); + } + + currentFrame = (currentFrame + 1) % MAX_FRAME_IN_FLIGHT;//前进下一帧 } void HelloTriangleApplication::createSyncObjects() { + imageAvailableSemaphores.resize(MAX_FRAME_IN_FLIGHT); + renderFinishedSemaphores.resize(MAX_FRAME_IN_FLIGHT); + inFlightFences.resize(MAX_FRAME_IN_FLIGHT); + VkSemaphoreCreateInfo semaphoreInfo{}; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; @@ -792,15 +860,22 @@ void HelloTriangleApplication::createSyncObjects() fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;//防止vkWaitForFences在第一帧无限期阻塞 - if (vkCreateSemaphore(device,&semaphoreInfo,nullptr,&imageAvailableSemaphore) != VK_SUCCESS || - vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphore) != VK_SUCCESS || - vkCreateFence(device,&fenceInfo,nullptr,&inFlightFence) != VK_SUCCESS) + if (vkCreateSemaphore(device,&semaphoreInfo,nullptr,imageAvailableSemaphores.data()) != VK_SUCCESS || + vkCreateSemaphore(device, &semaphoreInfo, nullptr, renderFinishedSemaphores.data()) != VK_SUCCESS || + vkCreateFence(device,&fenceInfo,nullptr,inFlightFences.data()) != VK_SUCCESS) { throw std::runtime_error("failed to create semaphores in creatSyncObjects"); } } +void HelloTriangleApplication::framebufferResizeCallback(GLFWwindow* window, int width, int height) +{ + auto app = reinterpret_cast(glfwGetWindowUserPointer(window)); + app->framebufferResized = true; + +} + void HelloTriangleApplication::createRenderPass() { diff --git a/VulkanTutorial.h b/VulkanTutorial.h index 90982e3..cebb729 100644 --- a/VulkanTutorial.h +++ b/VulkanTutorial.h @@ -30,10 +30,12 @@ class HelloTriangleApplication { public: + const int MAX_FRAME_IN_FLIGHT = 2; + HelloTriangleApplication(); ~HelloTriangleApplication(); void run(int Width, int Height) { - GLFWwindow* window = initWindow(Width,Height); + initWindow(Width,Height); initVulkan(); mainLoop(window); cleanup(window); @@ -68,9 +70,7 @@ private: VkPipeline graphicsPipeline; - VkSemaphore imageAvailableSemaphore; - VkSemaphore renderFinishedSemaphore; - VkFence inFlightFence; + struct QueueFamilyIndices { @@ -93,9 +93,15 @@ private: VkCommandPool commandPool; - VkCommandBuffer commandBuffer; + std::vector commandBuffers; - GLFWwindow* initWindow(int Width, int Height); + std::vector imageAvailableSemaphores; + std::vector renderFinishedSemaphores; + std::vector inFlightFences; + + bool framebufferResized = false; + + void initWindow(int Width, int Height); void createInstance(); @@ -137,8 +143,10 @@ private: VkPresentModeKHR chooseSwapPresentMode(const std::vector& availablePresentModes); VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities); void createSwapChain(); + void cleanupSwapChain(); + void recreateSwapChain(); - void creatImageView(); + void createImageView(); void createRenderPass(); void createGraphicPipeline(); @@ -159,6 +167,8 @@ private: void createSyncObjects(); + static void framebufferResizeCallback(GLFWwindow* window, int width, int height); + }; HelloTriangleApplication::HelloTriangleApplication()