From c6db16a52b187af9e47b2497e1be568703f3108d Mon Sep 17 00:00:00 2001 From: Xiang Silian Date: Thu, 6 Nov 2025 17:51:10 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=A4=E6=8D=A2=E9=93=BE=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E6=94=B9=E5=86=99=EF=BC=8C=E5=8A=A0=E5=85=A5=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vulkan/Application.cpp | 251 +++++++++++++++++++++++++++++++++-------- vulkan/Application.h | 23 +++- 2 files changed, 220 insertions(+), 54 deletions(-) diff --git a/vulkan/Application.cpp b/vulkan/Application.cpp index bb8e964..c80b0f6 100644 --- a/vulkan/Application.cpp +++ b/vulkan/Application.cpp @@ -1,4 +1,8 @@ #include "Application.h" +#include +#include + +using namespace std; #ifdef _WIN32 @@ -28,6 +32,7 @@ void Application::initWindow() void Application::run() { initVulkan(); + cout << "initVulkan finished" << endl; mainLoop(); cleanup(); } @@ -234,7 +239,6 @@ void Application::createSwapChain() { swapChainImageFormat = surfaceFormat.format; swapChainExtent = extent; - MAX_FRAMES_IN_FLIGHT = imageCount; } void Application::createPipelineLayout() { @@ -409,26 +413,24 @@ void Application::createCommandPool() { void Application::createCommandBuffer() { - commandBuffers.resize(MAX_FRAMES_IN_FLIGHT); + //std::vector commandBuffers = { commandBuffers_Left, commandBuffers_Right }; 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; + allocInfo.commandBufferCount = 1; - if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) { + if (vkAllocateCommandBuffers(device, &allocInfo, &commandBuffers_Left) != VK_SUCCESS) { + throw std::runtime_error("failed to allocate command buffers!"); + } + + if (vkAllocateCommandBuffers(device, &allocInfo, &commandBuffers_Right) != VK_SUCCESS) { throw std::runtime_error("failed to allocate command buffers!"); } } void Application::createSyncObjects() { - - imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT); - renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT); - inFlightFences.resize(MAX_FRAMES_IN_FLIGHT); - imagesInFlight.resize(MAX_FRAMES_IN_FLIGHT, VK_NULL_HANDLE); - VkSemaphoreCreateInfo semaphoreInfo{}; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; @@ -436,20 +438,13 @@ void Application::createSyncObjects() 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) { - throw std::runtime_error("failed to create synchronization objects!"); - } - } - - // 为每个帧在飞行创建栅栏 - for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - if (vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) { - throw std::runtime_error("failed to create synchronization objects!"); - } - } + vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores_Left); + vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores_Right); + vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores_Left); + vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores_Right); + vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences_Left); + vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences_Right); + } void Application::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) @@ -491,53 +486,92 @@ void Application::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t im } } -void Application::drawFrame() +void Application::drawLeft() { + cout << "call drawLeft curFrame:" << to_string(currentFrame) << endl; // 1. 等待前一帧完成 - vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); + vkWaitForFences(device, 1, &inFlightFences_Left, VK_TRUE, UINT64_MAX); + + cout << "vkWaitForFences inFlightFences_Left" << endl; // 2. 获取交换链图像 - 使用当前帧的信号量 uint32_t imageIndex; - VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX,imageAvailableSemaphores[currentFrame],VK_NULL_HANDLE, &imageIndex); + VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores_Left, VK_NULL_HANDLE, &imageIndex); + + cout << "vkAcquireNextImageKHR set imageAvailableSemaphores_Left ImageIndex:" << to_string(imageIndex) << endl; if (result != VK_SUCCESS) { throw std::runtime_error("failed to acquire swap chain image!"); } - // 3. 检查该图像是否正在被之前的帧使用 - if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) { - vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX); + if (imageIndex == 0) + { + // 3. 检查该图像是否正在被之前的帧使用 + if (imagesInFlight_Left != VK_NULL_HANDLE) { + cout << "vkWaitForFences imagesInFlight_Left ImageIndex:" << to_string(imageIndex) << endl; + vkWaitForFences(device, 1, &imagesInFlight_Left, VK_TRUE, UINT64_MAX); + } + else + { + cout << "imagesInFlight_Left is NULL" << endl; + } + + cout << "imagesInFlight_Left = inFlightFences_Left ImageIndex:" << to_string(imageIndex) << endl; + // 标记该图像正在被当前帧使用 + imagesInFlight_Left = inFlightFences_Left; + } + else + { + // 3. 检查该图像是否正在被之前的帧使用 + if (imagesInFlight_Right != VK_NULL_HANDLE) { + cout << "vkWaitForFences imagesInFlight_Right ImageIndex:" << to_string(imageIndex) << endl; + vkWaitForFences(device, 1, &imagesInFlight_Right, VK_TRUE, UINT64_MAX); + } + cout << "imagesInFlight_Right = inFlightFences_Left ImageIndex:" << to_string(imageIndex) << endl; + imagesInFlight_Right = inFlightFences_Left; } - // 标记该图像正在被当前帧使用 - imagesInFlight[imageIndex] = inFlightFences[currentFrame]; + cout << "vkResetFences inFlightFences_Left" << endl; // 4. 重置栅栏 - vkResetFences(device, 1, &inFlightFences[currentFrame]); + vkResetFences(device, 1, &inFlightFences_Left); + cout << "Process commandBuffers_Left" << endl; // 5. 记录命令缓冲区 - vkResetCommandBuffer(commandBuffers[currentFrame], 0); - recordCommandBuffer(commandBuffers[currentFrame], imageIndex); + vkResetCommandBuffer(commandBuffers_Left, 0); + recordCommandBuffer(commandBuffers_Left, imageIndex); // 6. 提交命令缓冲区 VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; // 等待图像获取完成 - VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] }; + VkSemaphore waitSemaphores[] = { imageAvailableSemaphores_Left }; VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitDstStageMask = waitStages; submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &commandBuffers[currentFrame]; - - // 使用对应图像的渲染完成信号量 - VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[imageIndex] }; + submitInfo.pCommandBuffers = &commandBuffers_Left; + VkSemaphore signalSemaphores[1]; + if (imageIndex == 0) + { + cout << "renderFinishedSemaphores_Left ImageIndex:" << to_string(imageIndex) << endl; + // 使用对应图像的渲染完成信号量 + signalSemaphores[0] = { renderFinishedSemaphores_Left }; + + } + else + { + cout << "renderFinishedSemaphores_Right ImageIndex:" << to_string(imageIndex) << endl; + // 使用对应图像的渲染完成信号量 + signalSemaphores[0] = { renderFinishedSemaphores_Right }; + } submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; - if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) { + cout << "vkQueueSubmit inFlightFences_Left" << endl; + if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences_Left) != VK_SUCCESS) { throw std::runtime_error("failed to submit draw command buffer!"); } @@ -552,14 +586,132 @@ void Application::drawFrame() presentInfo.pSwapchains = swapChains; presentInfo.pImageIndices = &imageIndex; + cout << "Present Left \n" << endl; result = vkQueuePresentKHR(presentQueue, &presentInfo); if (result != VK_SUCCESS) { throw std::runtime_error("failed to present swap chain image!"); } - // 8. 前进到下一帧 - currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; +} + +void Application::drawRight() +{ + cout << "call drawRight curFrame:" << to_string(currentFrame) << endl; + // 1. 等待前一帧完成 + vkWaitForFences(device, 1, &inFlightFences_Right, VK_TRUE, UINT64_MAX); + + cout << "vkWaitForFences inFlightFences_Right" << endl; + + // 2. 获取交换链图像 - 使用当前帧的信号量 + uint32_t imageIndex; + VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores_Right, VK_NULL_HANDLE, &imageIndex); + + cout << "vkAcquireNextImageKHR set imageAvailableSemaphores_Right ImageIndex:" << to_string(imageIndex) << endl; + + if (result != VK_SUCCESS) { + throw std::runtime_error("failed to acquire swap chain image!"); + } + + if (imageIndex == 0) + { + // 3. 检查该图像是否正在被之前的帧使用 + if (imagesInFlight_Left != VK_NULL_HANDLE) { + cout << "vkWaitForFences imagesInFlight_Left ImageIndex:0" << endl; + vkWaitForFences(device, 1, &imagesInFlight_Left, VK_TRUE, UINT64_MAX); + } + cout << "imagesInFlight_Left = inFlightFences_Right ImageIndex:0" << endl; + // 标记该图像正在被当前帧使用 + imagesInFlight_Left = inFlightFences_Right; + } + else + { + // 3. 检查该图像是否正在被之前的帧使用 + if (imagesInFlight_Right != VK_NULL_HANDLE) { + cout << "vkWaitForFences imagesInFlight_Right ImageIndex:1" << endl; + vkWaitForFences(device, 1, &imagesInFlight_Right, VK_TRUE, UINT64_MAX); + } + else { + cout << "imagesInFlight_Right is NULL" << endl; + } + cout << "imagesInFlight_Right = inFlightFences_Right ImageIndex:1" << endl; + imagesInFlight_Right = inFlightFences_Right; + } + + cout << "vkResetFences inFlightFences_Right" << endl; + // 4. 重置栅栏 + vkResetFences(device, 1, &inFlightFences_Right); + + cout << "Process commandBuffers_Right" << endl; + // 5. 记录命令缓冲区 + vkResetCommandBuffer(commandBuffers_Right, 0); + recordCommandBuffer(commandBuffers_Right, imageIndex); + + // 6. 提交命令缓冲区 + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + + // 等待图像获取完成 + VkSemaphore waitSemaphores[] = { imageAvailableSemaphores_Right }; + VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = waitSemaphores; + submitInfo.pWaitDstStageMask = waitStages; + + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffers_Right; + VkSemaphore signalSemaphores[1]; + if (imageIndex == 0) + { + cout << "renderFinishedSemaphores_Left ImageIndex:0" << endl; + // 使用对应图像的渲染完成信号量 + signalSemaphores[0] = { renderFinishedSemaphores_Left }; + + } + else + { + cout << "renderFinishedSemaphores_Right ImageIndex:1" << endl; + // 使用对应图像的渲染完成信号量 + signalSemaphores[0] = { renderFinishedSemaphores_Right }; + } + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = signalSemaphores; + + cout << "vkQueueSubmit inFlightFences_Right" << endl; + if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences_Right) != VK_SUCCESS) { + throw std::runtime_error("failed to submit draw command buffer!"); + } + + // 7. 呈现图像 + VkPresentInfoKHR presentInfo{}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = 1; + presentInfo.pWaitSemaphores = signalSemaphores; // 等待对应图像的渲染完成信号量 + + VkSwapchainKHR swapChains[] = { swapChain }; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = swapChains; + presentInfo.pImageIndices = &imageIndex; + + cout << "Present Right \n" << endl; + result = vkQueuePresentKHR(presentQueue, &presentInfo); + + if (result != VK_SUCCESS) { + throw std::runtime_error("failed to present swap chain image!"); + } +} + +void Application::drawFrame() +{ + if (currentFrame % 2 == 0) + { + drawLeft(); + } + else + { + drawRight(); + } + currentFrame++; } void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) { @@ -579,11 +731,14 @@ void Application::cleanup() { vkDeviceWaitIdle(device); // 正确销毁所有同步对象 - for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr); - vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr); - vkDestroyFence(device, inFlightFences[i], nullptr); - } + vkDestroySemaphore(device, imageAvailableSemaphores_Left, nullptr); + vkDestroySemaphore(device, renderFinishedSemaphores_Left, nullptr); + vkDestroyFence(device, inFlightFences_Left, nullptr); + + // 正确销毁所有同步对象 + vkDestroySemaphore(device, imageAvailableSemaphores_Right, nullptr); + vkDestroySemaphore(device, renderFinishedSemaphores_Right, nullptr); + vkDestroyFence(device, inFlightFences_Right, nullptr); // 不需要手动释放commandBuffers,销毁命令池时会自动释放 // 销毁命令池 diff --git a/vulkan/Application.h b/vulkan/Application.h index f56cde2..26fd3e9 100644 --- a/vulkan/Application.h +++ b/vulkan/Application.h @@ -30,6 +30,8 @@ public: void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex); void createSyncObjects(); void drawFrame(); + void drawLeft(); + void drawRight(); bool isInited() { return inited; } private: VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; // 物理设备 @@ -48,12 +50,21 @@ private: VkQueue presentQueue; // 呈现队列 VkCommandPool commandPool; - std::vector commandBuffers; - std::vector imageAvailableSemaphores; // 每个交换链图像一个 - std::vector renderFinishedSemaphores; // 每个交换链图像一个 - std::vector inFlightFences; // 每个帧在飞行一个 - std::vector imagesInFlight; // 跟踪每个图像的使用状态 + VkCommandBuffer commandBuffers_Left; + VkCommandBuffer commandBuffers_Right; + + VkSemaphore imageAvailableSemaphores_Left; + VkSemaphore imageAvailableSemaphores_Right; + + VkSemaphore renderFinishedSemaphores_Left; + VkSemaphore renderFinishedSemaphores_Right; + + VkFence inFlightFences_Left; + VkFence inFlightFences_Right; + + VkFence imagesInFlight_Left = VK_NULL_HANDLE; + VkFence imagesInFlight_Right = VK_NULL_HANDLE; + int currentFrame = 0; - int MAX_FRAMES_IN_FLIGHT = 2; bool inited = false; }; \ No newline at end of file