diff --git a/vulkan/AppBase.h b/vulkan/AppBase.h index 7eb9ff0..639fc43 100644 --- a/vulkan/AppBase.h +++ b/vulkan/AppBase.h @@ -1,14 +1,14 @@ #ifndef VULKAN_UTILS_H #define VULKAN_UTILS_H -#define VK_CHECK(x) \ - do \ - { \ - VkResult err = x; \ - if (err) \ - { \ - assert(false); \ - } \ +#define VK_CHECK(x) \ + do \ + { \ + VkResult err = x; \ + if (err) \ + { \ + assert(false); \ + } \ } while (0) #ifdef _WIN32 diff --git a/vulkan/Application.cpp b/vulkan/Application.cpp index 2849407..cc5a6dd 100644 --- a/vulkan/Application.cpp +++ b/vulkan/Application.cpp @@ -72,7 +72,6 @@ void Application::initVulkan() createFramebuffers(); // 创建帧缓冲区 createCommandPool(); // 创建命令池 createCommandBuffer(); // 创建命令缓冲区 - recordCommandBuffer(commandBuffer, 0); // 录制命令缓冲区(初始化时) createSyncObjects(); // 创建同步对象 } @@ -124,30 +123,7 @@ void Application::createFramebuffers() { } } -void Application::createCommandPool() { - QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice, surface); - VkCommandPoolCreateInfo poolInfo{}; - poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value(); - poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; // 添加标志 - - if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) { - throw std::runtime_error("failed to create command pool!"); - } -} - -void Application::createCommandBuffer() { - VkCommandBufferAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.commandPool = commandPool; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandBufferCount = 1; - - if (vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer) != VK_SUCCESS) { - throw std::runtime_error("failed to allocate command buffers!"); - } -} void Application::mainLoop() { @@ -234,7 +210,7 @@ void Application::createSwapChain() { // 选择交换链格式、颜色空间和分辨率 VkSurfaceFormatKHR surfaceFormat = { VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; - VkExtent2D extent = { 0, 0 }; + VkExtent2D extent = { 1, 1 }; VkSurfaceCapabilitiesKHR surface_capabilities{}; vkGetPhysicalDeviceSurfaceCapabilitiesKHR(this->physicalDevice, this->surface, &surface_capabilities); @@ -442,6 +418,57 @@ void Application::createRenderPass() { +void Application::createCommandPool() { + QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice, surface); + + VkCommandPoolCreateInfo poolInfo{}; + poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value(); + poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; // 添加标志 + + if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) { + throw std::runtime_error("failed to create command pool!"); + } +} + +void Application::createCommandBuffer() +{ + int MAX_FRAMES_IN_FLIGHT = swapChainImages.size(); + commandBuffers.resize(MAX_FRAMES_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 = (uint32_t)MAX_FRAMES_IN_FLIGHT; + + if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) { + throw std::runtime_error("failed to allocate command buffers!"); + } +} + +void Application::createSyncObjects() +{ + int MAX_FRAMES_IN_FLIGHT = swapChainImages.size(); + 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; + + VkFenceCreateInfo fenceInfo{}; + fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]) != VK_SUCCESS || + vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS || + vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) { + throw std::runtime_error("failed to create synchronization objects!"); + } + } +} + void Application::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) { VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -478,48 +505,33 @@ void Application::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t im } } -void Application::createSyncObjects() { - VkSemaphoreCreateInfo semaphoreInfo{}; - semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - - VkFenceCreateInfo fenceInfo{}; - fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; // 初始状态为已触发 - - if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphore) != VK_SUCCESS || - vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphore) != VK_SUCCESS || - vkCreateFence(device, &fenceInfo, nullptr, &inFlightFence) != VK_SUCCESS) { - throw std::runtime_error("failed to create synchronization objects!"); - } -} - void Application::drawFrame() { - vkWaitForFences(device, 1, &inFlightFence, VK_TRUE, UINT64_MAX); - vkResetFences(device, 1, &inFlightFence); + vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); + vkResetFences(device, 1, &inFlightFences[currentFrame]); uint32_t imageIndex; - vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); + vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); - vkResetCommandBuffer(commandBuffer, 0); - recordCommandBuffer(commandBuffer, imageIndex); // 重新录制命令缓冲区 + vkResetCommandBuffer(commandBuffers[currentFrame], 0); + recordCommandBuffer(commandBuffers[currentFrame], currentFrame); 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(graphicsQueue, 1, &submitInfo, inFlightFence) != VK_SUCCESS) { + if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) { throw std::runtime_error("failed to submit draw command buffer!"); } @@ -534,6 +546,8 @@ void Application::drawFrame() { presentInfo.pImageIndices = &imageIndex; vkQueuePresentKHR(presentQueue, &presentInfo); + int MAX_FRAMES_IN_FLIGHT = swapChainImages.size(); + currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; } void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) { @@ -548,13 +562,19 @@ void Application::cleanup() { DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); } - // 销毁命令缓冲区 - vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer); + - // 销毁同步对象 - vkDestroySemaphore(device, imageAvailableSemaphore, nullptr); - vkDestroySemaphore(device, renderFinishedSemaphore, nullptr); - vkDestroyFence(device, inFlightFence, nullptr); + int MAX_FRAMES_IN_FLIGHT = swapChainImages.size(); + for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) + { + // 销毁命令缓冲区 + vkFreeCommandBuffers(device, commandPool, 1, &commandBuffers[i]); + // 销毁同步对象 + vkDestroySemaphore(device, imageAvailableSemaphores[0], nullptr); + vkDestroySemaphore(device, renderFinishedSemaphores[0], nullptr); + vkDestroyFence(device, inFlightFences[0], nullptr); + } + // 销毁帧缓冲区 for (auto framebuffer : swapChainFramebuffers) { diff --git a/vulkan/Application.h b/vulkan/Application.h index 751cdd1..914802c 100644 --- a/vulkan/Application.h +++ b/vulkan/Application.h @@ -45,11 +45,12 @@ private: VkPipelineLayout pipelineLayout; // 管线布局 VkPipeline graphicsPipeline; // 图形管线 std::vector swapChainFramebuffers; // 帧缓冲区 - VkCommandPool commandPool; // 命令池 - VkCommandBuffer commandBuffer; // 命令缓冲区 - VkSemaphore imageAvailableSemaphore; // 图像可用信号量 - VkSemaphore renderFinishedSemaphore; // 渲染完成信号量 - VkFence inFlightFence; // 同步栅栏 VkQueue presentQueue; // 呈现队列 + VkCommandPool commandPool; // 命令池 + std::vector commandBuffers; // 命令缓冲区 + std::vector imageAvailableSemaphores; // 图像可用信号量 + std::vector renderFinishedSemaphores; // 渲染完成信号量 + std::vector inFlightFences; // 同步栅栏 + int currentFrame = 0; }; \ No newline at end of file