フレーム・イン・フライト

テクニカル諏訪子 <suwako@076.moe>、2026-07-21 13:59
コミット eb2c9ba2c636f2344fc3ecdb50268eef124cf04b ・親 6b7ea3f ・ファイルを見る

1個のファイル、+32 -18

@@ -16,6 +16,9 @@
1616 #include <util/root.hh>
1717 VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
1818
19+constexpr int MAX_FRAMES_IN_FLIGHT = 2;
20+uint32_t frameIdx = 0;
21+
1922 std::vector<vk::Image> swapChainImages;
2023 vk::CommandBuffer cmdBuf;
2124 vk::CommandBufferBeginInfo beginInfo;
@@ -526,7 +529,7 @@
526529 vk::CommandBufferAllocateInfo allocInfo = {};
527530 allocInfo.commandPool = cmdPool;
528531 allocInfo.level = vk::CommandBufferLevel::ePrimary;
529- allocInfo.commandBufferCount = 1;
532+ allocInfo.commandBufferCount = MAX_FRAMES_IN_FLIGHT;
530533
531534 std::vector<vk::CommandBuffer> cmdBufs = device.allocateCommandBuffers(allocInfo);
532535 cmdBuf = cmdBufs.front();
@@ -538,13 +541,22 @@
538541 #pragma endregion
539542
540543 #pragma region syncObjects
541- vk::Semaphore presentCompleteSemaphore = device.createSemaphore(vk::SemaphoreCreateInfo());
542- vk::Semaphore renderFinishedSemaphore = device.createSemaphore(vk::SemaphoreCreateInfo());
544+ std::vector<vk::Semaphore> presentCompleteSemaphores;
545+ std::vector<vk::Semaphore> renderFinishedSemaphores;
546+ std::vector<vk::Fence> inFlightFences;
547+ assert(presentCompleteSemaphores.empty() && renderFinishedSemaphores.empty() && inFlightFences.empty());
543548
544- vk::FenceCreateInfo fenceInfo = {};
545- fenceInfo.flags = vk::FenceCreateFlagBits::eSignaled;
549+ for (size_t i = 0; i < swapChainImages.size(); ++i) {
550+ renderFinishedSemaphores.emplace_back(device.createSemaphore(vk::SemaphoreCreateInfo()));
551+ }
546552
547- vk::Fence drawFence = device.createFence(fenceInfo);
553+ for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) {
554+ presentCompleteSemaphores.emplace_back(device.createSemaphore(vk::SemaphoreCreateInfo()));
555+
556+ vk::FenceCreateInfo fenceInfo = {};
557+ fenceInfo.flags = vk::FenceCreateFlagBits::eSignaled;
558+ inFlightFences.emplace_back(device.createFence(fenceInfo));
559+ }
548560 #pragma endregion
549561
550562 #pragma region framesInFlight
@@ -552,7 +564,7 @@
552564
553565 #pragma region swapChainRecreate
554566 #pragma endregion
555-
567+
556568 while (!glfwWindowShouldClose(window)) {
557569 if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) {
558570 glfwSetWindowShouldClose(window, true);
@@ -561,15 +573,15 @@
561573 glfwPollEvents();
562574
563575 #pragma region drawFrame
564- auto fenceResult = device.waitForFences(drawFence, vk::True, UINT64_MAX);
576+ auto fenceResult = device.waitForFences(inFlightFences[frameIdx], vk::True, UINT64_MAX);
565577 if (fenceResult != vk::Result::eSuccess) {
566578 assert(false && "フェンスまで待つに失敗。");
567579 break;
568580 }
569581
570- device.resetFences(drawFence);
571- auto [acquireRes, imgIdx] = device.acquireNextImageKHR(swapChain, UINT64_MAX, presentCompleteSemaphore, nullptr);
572-
582+ device.resetFences(inFlightFences[frameIdx]);
583+ auto [acquireRes, imgIdx] = device.acquireNextImageKHR(swapChain, UINT64_MAX, presentCompleteSemaphores[frameIdx], nullptr);
584+
573585 if (acquireRes == vk::Result::eErrorOutOfDateKHR || acquireRes == vk::Result::eSuboptimalKHR) continue;
574586 if (acquireRes != vk::Result::eSuccess) {
575587 assert(false && "次の画像の受け取りに失敗。");
@@ -582,14 +594,14 @@
582594
583595 vk::SubmitInfo submitInfo = {};
584596 submitInfo.waitSemaphoreCount = 1;
585- submitInfo.pWaitSemaphores = &presentCompleteSemaphore;
597+ submitInfo.pWaitSemaphores = &presentCompleteSemaphores[frameIdx];
586598 submitInfo.pWaitDstStageMask = &waitStage;
587599 submitInfo.commandBufferCount = 1;
588600 submitInfo.pCommandBuffers = &cmdBuf;
589601 submitInfo.signalSemaphoreCount = 1;
590- submitInfo.pSignalSemaphores = &renderFinishedSemaphore;
602+ submitInfo.pSignalSemaphores = &renderFinishedSemaphores[frameIdx];
591603
592- gfxQueue.submit(submitInfo, drawFence);
604+ gfxQueue.submit(submitInfo, inFlightFences[frameIdx]);
593605
594606 vk::SubpassDependency depend = {};
595607 depend.srcSubpass = vk::SubpassExternal;
@@ -601,12 +613,14 @@
601613
602614 vk::PresentInfoKHR presentInfo = {};
603615 presentInfo.waitSemaphoreCount = 1;
604- presentInfo.pWaitSemaphores = &renderFinishedSemaphore;
616+ presentInfo.pWaitSemaphores = &renderFinishedSemaphores[frameIdx];
605617 presentInfo.swapchainCount = 1;
606618 presentInfo.pSwapchains = &swapChain;
607619 presentInfo.pImageIndices = &imgIdx;
608620
609621 vk::Result presentRes = gfxQueue.presentKHR(presentInfo);
622+
623+ frameIdx = (frameIdx + 1) % MAX_FRAMES_IN_FLIGHT;
610624 #pragma endregion
611625
612626 device.waitIdle();
@@ -623,9 +637,9 @@
623637 swapChainImageViews.clear();
624638
625639 if (swapChain) device.destroySwapchainKHR(swapChain);
626- if (presentCompleteSemaphore) device.destroySemaphore(presentCompleteSemaphore);
627- if (renderFinishedSemaphore) device.destroySemaphore(renderFinishedSemaphore);
628- if (drawFence) device.destroyFence(drawFence);
640+ for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) device.destroySemaphore(presentCompleteSemaphores[i]);
641+ for (size_t i = 0; i < swapChainImages.size(); ++i) device.destroySemaphore(renderFinishedSemaphores[i]);
642+ for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) device.destroyFence(inFlightFences[i]);
629643 if (device) device.destroy();
630644 #ifndef NDEBUG
631645 if (debugMessenger) instance.destroyDebugUtilsMessengerEXT(debugMessenger);