完成swapchain随窗口大小改变重建

master
InkSoul 2024-03-10 22:13:49 +08:00
parent dae58772e2
commit c6d688a055
2 changed files with 131 additions and 46 deletions

View File

@ -22,12 +22,14 @@ const bool enableValidationLayers = true;
#endif // NDEBUG #endif // NDEBUG
//window init //window init
GLFWwindow* HelloTriangleApplication::initWindow(int Width, int Height) { void HelloTriangleApplication::initWindow(int Width, int Height) {
glfwInit(); glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow(Width, Height, "vulkan", nullptr, nullptr); window = glfwCreateWindow(Width, Height, "vulkan", nullptr, nullptr);
return window; glfwSetWindowUserPointer(window, this);
glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);
} }
// vulkan instace create // vulkan instace create
void HelloTriangleApplication::createInstance() { void HelloTriangleApplication::createInstance() {
@ -110,7 +112,7 @@ void HelloTriangleApplication::initVulkan() {
createSwapChain(); createSwapChain();
creatImageView(); createImageView();
createRenderPass(); createRenderPass();
createGraphicPipeline(); createGraphicPipeline();
@ -143,38 +145,32 @@ void HelloTriangleApplication::mainLoop(GLFWwindow* window){
void HelloTriangleApplication::cleanup(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); cleanupSwapChain();
vkDestroySemaphore(device, renderFinishedSemaphore, nullptr);
vkDestroyFence(device, inFlightFence, nullptr);
vkDestroyCommandPool(device, commandPool, nullptr);
for (auto framebuffer : swapChainFramebuffers)
{
vkDestroyFramebuffer(device, framebuffer, nullptr);
}
vkDestroyPipeline(device, graphicsPipeline, nullptr); vkDestroyPipeline(device, graphicsPipeline, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyRenderPass(device, renderPass, 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); vkDestroyCommandPool(device, commandPool, nullptr);
vkDestroySurfaceKHR(instance, surface, nullptr); vkDestroyDevice(device, nullptr);
if (enableValidationLayers) if (enableValidationLayers)
{ {
DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
} }
vkDestroyDevice(device, nullptr); vkDestroySurfaceKHR(instance, surface, nullptr);
vkDestroyInstance(instance, 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()); swapChainImageViews.resize(swapChainImages.size());
@ -673,13 +709,15 @@ void HelloTriangleApplication::createCommandPool()
void HelloTriangleApplication::createCommandBuffer() void HelloTriangleApplication::createCommandBuffer()
{ {
commandBuffers.resize(MAX_FRAME_IN_FLIGHT);
VkCommandBufferAllocateInfo allocInfo{}; VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = commandPool; allocInfo.commandPool = commandPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 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"); throw std::runtime_error("failed to allocate command buffers in createCommandBuffer");
} }
@ -737,33 +775,46 @@ void HelloTriangleApplication::recordCommandBuffer(VkCommandBuffer commandBuffer
void HelloTriangleApplication::drawFrame() void HelloTriangleApplication::drawFrame()
{ {
//等待所有fence收到信号后返回uint64_max禁用超时 uint32_t currentFrame = 0;
vkWaitForFences(device, 1, &inFlightFence, VK_TRUE, UINT64_MAX);
vkResetFences(device, 1, &inFlightFence);
uint32_t imageIndex; 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); VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
recordCommandBuffer(commandBuffer, 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{}; VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = { imageAvailableSemaphore }; VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame]};
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1; submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages; submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer; submitInfo.pCommandBuffers = &commandBuffers[currentFrame];
VkSemaphore signalSemaphores[] = { renderFinishedSemaphore }; VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame]};
submitInfo.signalSemaphoreCount = 1; submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores; 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"); throw std::runtime_error("failed to submit draw command buffer in drawFrame");
} }
@ -779,12 +830,29 @@ void HelloTriangleApplication::drawFrame()
presentInfo.pSwapchains = swapChains; presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex; presentInfo.pImageIndices = &imageIndex;
presentInfo.pResults = nullptr; 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() void HelloTriangleApplication::createSyncObjects()
{ {
imageAvailableSemaphores.resize(MAX_FRAME_IN_FLIGHT);
renderFinishedSemaphores.resize(MAX_FRAME_IN_FLIGHT);
inFlightFences.resize(MAX_FRAME_IN_FLIGHT);
VkSemaphoreCreateInfo semaphoreInfo{}; VkSemaphoreCreateInfo semaphoreInfo{};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
@ -792,15 +860,22 @@ void HelloTriangleApplication::createSyncObjects()
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;//防止vkWaitForFences在第一帧无限期阻塞 fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;//防止vkWaitForFences在第一帧无限期阻塞
if (vkCreateSemaphore(device,&semaphoreInfo,nullptr,&imageAvailableSemaphore) != VK_SUCCESS || if (vkCreateSemaphore(device,&semaphoreInfo,nullptr,imageAvailableSemaphores.data()) != VK_SUCCESS ||
vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphore) != VK_SUCCESS || vkCreateSemaphore(device, &semaphoreInfo, nullptr, renderFinishedSemaphores.data()) != VK_SUCCESS ||
vkCreateFence(device,&fenceInfo,nullptr,&inFlightFence) != VK_SUCCESS) vkCreateFence(device,&fenceInfo,nullptr,inFlightFences.data()) != VK_SUCCESS)
{ {
throw std::runtime_error("failed to create semaphores in creatSyncObjects"); throw std::runtime_error("failed to create semaphores in creatSyncObjects");
} }
} }
void HelloTriangleApplication::framebufferResizeCallback(GLFWwindow* window, int width, int height)
{
auto app = reinterpret_cast<HelloTriangleApplication*>(glfwGetWindowUserPointer(window));
app->framebufferResized = true;
}
void HelloTriangleApplication::createRenderPass() void HelloTriangleApplication::createRenderPass()
{ {

View File

@ -30,10 +30,12 @@ class HelloTriangleApplication
{ {
public: public:
const int MAX_FRAME_IN_FLIGHT = 2;
HelloTriangleApplication(); HelloTriangleApplication();
~HelloTriangleApplication(); ~HelloTriangleApplication();
void run(int Width, int Height) { void run(int Width, int Height) {
GLFWwindow* window = initWindow(Width,Height); initWindow(Width,Height);
initVulkan(); initVulkan();
mainLoop(window); mainLoop(window);
cleanup(window); cleanup(window);
@ -68,9 +70,7 @@ private:
VkPipeline graphicsPipeline; VkPipeline graphicsPipeline;
VkSemaphore imageAvailableSemaphore;
VkSemaphore renderFinishedSemaphore;
VkFence inFlightFence;
struct QueueFamilyIndices struct QueueFamilyIndices
{ {
@ -93,9 +93,15 @@ private:
VkCommandPool commandPool; VkCommandPool commandPool;
VkCommandBuffer commandBuffer; std::vector<VkCommandBuffer> commandBuffers;
GLFWwindow* initWindow(int Width, int Height); std::vector<VkSemaphore> imageAvailableSemaphores;
std::vector<VkSemaphore> renderFinishedSemaphores;
std::vector<VkFence> inFlightFences;
bool framebufferResized = false;
void initWindow(int Width, int Height);
void createInstance(); void createInstance();
@ -137,8 +143,10 @@ private:
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes); VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes);
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities); VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities);
void createSwapChain(); void createSwapChain();
void cleanupSwapChain();
void recreateSwapChain();
void creatImageView(); void createImageView();
void createRenderPass(); void createRenderPass();
void createGraphicPipeline(); void createGraphicPipeline();
@ -159,6 +167,8 @@ private:
void createSyncObjects(); void createSyncObjects();
static void framebufferResizeCallback(GLFWwindow* window, int width, int height);
}; };
HelloTriangleApplication::HelloTriangleApplication() HelloTriangleApplication::HelloTriangleApplication()