1616const int WIDTH = 800 ;
1717const int HEIGHT = 600 ;
1818
19+ const int MAX_FRAMES_IN_FLIGHT = 2 ;
20+
1921const std::vector<const char *> validationLayers = {
2022 " VK_LAYER_LUNARG_standard_validation"
2123};
@@ -133,8 +135,10 @@ class HelloTriangleApplication {
133135 VkCommandPool commandPool;
134136 std::vector<VkCommandBuffer> commandBuffers;
135137
136- VkSemaphore imageAvailableSemaphore;
137- VkSemaphore renderFinishedSemaphore;
138+ std::vector<VkSemaphore> imageAvailableSemaphores;
139+ std::vector<VkSemaphore> renderFinishedSemaphores;
140+ std::vector<VkFence> inFlightFences;
141+ size_t currentFrame = 0 ;
138142
139143 void initWindow () {
140144 glfwInit ();
@@ -157,7 +161,7 @@ class HelloTriangleApplication {
157161 createFramebuffers ();
158162 createCommandPool ();
159163 createCommandBuffers ();
160- createSemaphores ();
164+ createSyncObjects ();
161165 }
162166
163167 void mainLoop () {
@@ -190,8 +194,11 @@ class HelloTriangleApplication {
190194 void cleanup () {
191195 cleanupSwapChain ();
192196
193- vkDestroySemaphore (device, renderFinishedSemaphore, nullptr );
194- vkDestroySemaphore (device, imageAvailableSemaphore, nullptr );
197+ for (size_t i = 0 ; i < MAX_FRAMES_IN_FLIGHT; i++) {
198+ vkDestroySemaphore (device, renderFinishedSemaphores[i], nullptr );
199+ vkDestroySemaphore (device, imageAvailableSemaphores[i], nullptr );
200+ vkDestroyFence (device, inFlightFences[i], nullptr );
201+ }
195202
196203 vkDestroyCommandPool (device, commandPool, nullptr );
197204
@@ -663,20 +670,33 @@ class HelloTriangleApplication {
663670 }
664671 }
665672
666- void createSemaphores () {
673+ void createSyncObjects () {
674+ imageAvailableSemaphores.resize (MAX_FRAMES_IN_FLIGHT);
675+ renderFinishedSemaphores.resize (MAX_FRAMES_IN_FLIGHT);
676+ inFlightFences.resize (MAX_FRAMES_IN_FLIGHT);
677+
667678 VkSemaphoreCreateInfo semaphoreInfo = {};
668679 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
669680
670- if (vkCreateSemaphore (device, &semaphoreInfo, nullptr , &imageAvailableSemaphore) != VK_SUCCESS ||
671- vkCreateSemaphore (device, &semaphoreInfo, nullptr , &renderFinishedSemaphore) != VK_SUCCESS) {
681+ VkFenceCreateInfo fenceInfo = {};
682+ fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
683+ fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
672684
673- throw std::runtime_error (" failed to create semaphores!" );
685+ for (size_t i = 0 ; i < MAX_FRAMES_IN_FLIGHT; i++) {
686+ if (vkCreateSemaphore (device, &semaphoreInfo, nullptr , &imageAvailableSemaphores[i]) != VK_SUCCESS ||
687+ vkCreateSemaphore (device, &semaphoreInfo, nullptr , &renderFinishedSemaphores[i]) != VK_SUCCESS ||
688+ vkCreateFence (device, &fenceInfo, nullptr , &inFlightFences[i]) != VK_SUCCESS) {
689+ throw std::runtime_error (" failed to create synchronization objects for a frame!" );
690+ }
674691 }
675692 }
676693
677694 void drawFrame () {
695+ vkWaitForFences (device, 1 , &inFlightFences[currentFrame], VK_TRUE, std::numeric_limits<uint64_t >::max ());
696+ vkResetFences (device, 1 , &inFlightFences[currentFrame]);
697+
678698 uint32_t imageIndex;
679- VkResult result = vkAcquireNextImageKHR (device, swapChain, std::numeric_limits<uint64_t >::max (), imageAvailableSemaphore , VK_NULL_HANDLE, &imageIndex);
699+ VkResult result = vkAcquireNextImageKHR (device, swapChain, std::numeric_limits<uint64_t >::max (), imageAvailableSemaphores[currentFrame] , VK_NULL_HANDLE, &imageIndex);
680700
681701 if (result == VK_ERROR_OUT_OF_DATE_KHR) {
682702 recreateSwapChain ();
@@ -688,7 +708,7 @@ class HelloTriangleApplication {
688708 VkSubmitInfo submitInfo = {};
689709 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
690710
691- VkSemaphore waitSemaphores[] = {imageAvailableSemaphore };
711+ VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame] };
692712 VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
693713 submitInfo.waitSemaphoreCount = 1 ;
694714 submitInfo.pWaitSemaphores = waitSemaphores;
@@ -697,11 +717,11 @@ class HelloTriangleApplication {
697717 submitInfo.commandBufferCount = 1 ;
698718 submitInfo.pCommandBuffers = &commandBuffers[imageIndex];
699719
700- VkSemaphore signalSemaphores[] = {renderFinishedSemaphore };
720+ VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame] };
701721 submitInfo.signalSemaphoreCount = 1 ;
702722 submitInfo.pSignalSemaphores = signalSemaphores;
703723
704- if (vkQueueSubmit (graphicsQueue, 1 , &submitInfo, VK_NULL_HANDLE ) != VK_SUCCESS) {
724+ if (vkQueueSubmit (graphicsQueue, 1 , &submitInfo, inFlightFences[currentFrame] ) != VK_SUCCESS) {
705725 throw std::runtime_error (" failed to submit draw command buffer!" );
706726 }
707727
@@ -725,9 +745,7 @@ class HelloTriangleApplication {
725745 throw std::runtime_error (" failed to present swap chain image!" );
726746 }
727747
728- if (enableValidationLayers) {
729- vkQueueWaitIdle (presentQueue);
730- }
748+ currentFrame = (currentFrame + 1 ) % MAX_FRAMES_IN_FLIGHT;
731749 }
732750
733751 VkShaderModule createShaderModule (const std::vector<char >& code) {
0 commit comments