@@ -63,7 +63,11 @@ class VulkanExample : public VulkanExampleBase
6363 VkDescriptorSetLayout descriptorSetLayout; // Compute shader binding layout
6464 std::array<VkDescriptorSet, maxConcurrentFrames> descriptorSets; // Compute shader bindings
6565 std::array<VkFence, maxConcurrentFrames> fences{}; // Fences to make sure command buffers are done
66- std::array<VkSemaphore, maxConcurrentFrames> semaphores{}; // Semaphores for submission ordering
66+ struct ComputeSemaphores {
67+ VkSemaphore ready{ VK_NULL_HANDLE };
68+ VkSemaphore complete{ VK_NULL_HANDLE };
69+ };
70+ std::array<ComputeSemaphores, maxConcurrentFrames> semaphores{}; // Semaphores for submission ordering
6771 VkPipelineLayout pipelineLayout; // Layout of the compute pipeline
6872 VkPipeline pipelineCalculate; // Compute pipeline for N-Body velocity calculation (1st pass)
6973 VkPipeline pipelineIntegrate; // Compute pipeline for euler integration (2nd pass)
@@ -113,7 +117,8 @@ class VulkanExample : public VulkanExampleBase
113117 vkDestroyFence (device, fence, nullptr );
114118 }
115119 for (auto & semaphore : compute.semaphores ) {
116- vkDestroySemaphore (device, semaphore, nullptr );
120+ vkDestroySemaphore (device, semaphore.ready , nullptr );
121+ vkDestroySemaphore (device, semaphore.complete , nullptr );
117122 }
118123
119124 storageBuffer.destroy ();
@@ -415,8 +420,14 @@ class VulkanExample : public VulkanExampleBase
415420 // Semaphores to order compute and graphics submissions
416421 for (auto & semaphore : compute.semaphores ) {
417422 VkSemaphoreCreateInfo semaphoreInfo{ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
418- vkCreateSemaphore (device, &semaphoreInfo, nullptr , &semaphore);
423+ vkCreateSemaphore (device, &semaphoreInfo, nullptr , &semaphore.ready );
424+ vkCreateSemaphore (device, &semaphoreInfo, nullptr , &semaphore.complete );
419425 }
426+ // Signal first used ready semaphore
427+ VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo ();
428+ computeSubmitInfo.signalSemaphoreCount = 1 ;
429+ computeSubmitInfo.pSignalSemaphores = &compute.semaphores [-1 % maxConcurrentFrames].ready ;
430+ VK_CHECK_RESULT (vkQueueSubmit (compute.queue , 1 , &computeSubmitInfo, VK_NULL_HANDLE));
420431 }
421432
422433 void updateComputeUniformBuffers ()
@@ -645,50 +656,53 @@ class VulkanExample : public VulkanExampleBase
645656 if (!prepared)
646657 return ;
647658
648- VulkanExampleBase::prepareFrame (false );
649-
650659 // Submit compute commands
651-
652- VK_CHECK_RESULT (vkWaitForFences (device, 1 , &compute.fences [currentBuffer], VK_TRUE, UINT64_MAX));
653- VK_CHECK_RESULT (vkResetFences (device, 1 , &compute.fences [currentBuffer]));
654-
655- updateComputeUniformBuffers ();
656- buildComputeCommandBuffer ();
660+ {
661+ VK_CHECK_RESULT (vkWaitForFences (device, 1 , &compute.fences [currentBuffer], VK_TRUE, UINT64_MAX));
662+ VK_CHECK_RESULT (vkResetFences (device, 1 , &compute.fences [currentBuffer]));
663+
664+ updateComputeUniformBuffers ();
665+ buildComputeCommandBuffer ();
666+
667+ // Wait for rendering finished
668+ VkPipelineStageFlags waitDstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
669+ VkSubmitInfo submitInfo = vks::initializers::submitInfo ();
670+ submitInfo.waitSemaphoreCount = 1 ;
671+ submitInfo.pWaitSemaphores = &compute.semaphores [((int )currentBuffer - 1 ) % maxConcurrentFrames].ready ;
672+ submitInfo.pWaitDstStageMask = &waitDstStageMask;
673+ submitInfo.signalSemaphoreCount = 1 ;
674+ submitInfo.pSignalSemaphores = &compute.semaphores [currentBuffer].complete ;
675+ submitInfo.commandBufferCount = 1 ;
676+ submitInfo.pCommandBuffers = &compute.commandBuffers [currentBuffer];
677+ VK_CHECK_RESULT (vkQueueSubmit (compute.queue , 1 , &submitInfo, compute.fences [currentBuffer]));
678+ }
657679
658- // Wait for rendering finished
659- VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
680+ // Submit graphics commands
681+ {
682+ VK_CHECK_RESULT (vkWaitForFences (device, 1 , &waitFences[currentBuffer], VK_TRUE, UINT64_MAX));
683+ VK_CHECK_RESULT (vkResetFences (device, 1 , &waitFences[currentBuffer]));
660684
661- VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo ();
662- computeSubmitInfo.commandBufferCount = 1 ;
663- computeSubmitInfo.pCommandBuffers = &compute.commandBuffers [currentBuffer];
664- computeSubmitInfo.pWaitDstStageMask = &waitStageMask;
665- computeSubmitInfo.signalSemaphoreCount = 1 ;
666- computeSubmitInfo.pSignalSemaphores = &compute.semaphores [currentBuffer];
667- VK_CHECK_RESULT (vkQueueSubmit (compute.queue , 1 , &computeSubmitInfo, compute.fences [currentBuffer]));
685+ VulkanExampleBase::prepareFrame (false );
668686
669- // Submit graphics commands
670-
671- VK_CHECK_RESULT (vkWaitForFences (device, 1 , &waitFences[currentBuffer], VK_TRUE, UINT64_MAX));
672- VK_CHECK_RESULT (vkResetFences (device, 1 , &waitFences[currentBuffer]));
687+ updateGraphicsUniformBuffers ();
688+ buildGraphicsCommandBuffer ();
673689
674- updateGraphicsUniformBuffers ();
675- buildGraphicsCommandBuffer ();
690+ VkPipelineStageFlags waitDstStageMask[2 ] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT };
691+ VkSemaphore waitSemaphores[2 ] = { presentCompleteSemaphores[currentBuffer], compute.semaphores [currentBuffer].complete };
692+ VkSemaphore signalSemaphores[2 ] = { renderCompleteSemaphores[currentImageIndex], compute.semaphores [currentBuffer].ready };
676693
677- VkPipelineStageFlags graphicsWaitStageMasks[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
678- VkSemaphore graphicsWaitSemaphores[] = { compute.semaphores [currentBuffer], presentCompleteSemaphores[currentBuffer] };
694+ VkSubmitInfo submitInfo = vks::initializers::submitInfo ();
695+ submitInfo.waitSemaphoreCount = 2 ;
696+ submitInfo.pWaitSemaphores = waitSemaphores;
697+ submitInfo.pWaitDstStageMask = waitDstStageMask;
698+ submitInfo.commandBufferCount = 1 ;
699+ submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
700+ submitInfo.signalSemaphoreCount = 2 ;
701+ submitInfo.pSignalSemaphores = signalSemaphores;
702+ VK_CHECK_RESULT (vkQueueSubmit (queue, 1 , &submitInfo, waitFences[currentBuffer]));
679703
680- // Submit graphics commands
681- VkSubmitInfo graphicsSubmitInfo = vks::initializers::submitInfo ();
682- graphicsSubmitInfo.commandBufferCount = 1 ;
683- graphicsSubmitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
684- graphicsSubmitInfo.waitSemaphoreCount = 2 ;
685- graphicsSubmitInfo.pWaitSemaphores = graphicsWaitSemaphores;
686- graphicsSubmitInfo.pWaitDstStageMask = graphicsWaitStageMasks;
687- graphicsSubmitInfo.signalSemaphoreCount = 1 ;
688- graphicsSubmitInfo.pSignalSemaphores = &renderCompleteSemaphores[currentImageIndex];
689- VK_CHECK_RESULT (vkQueueSubmit (queue, 1 , &graphicsSubmitInfo, waitFences[currentBuffer]));
690-
691- VulkanExampleBase::submitFrame (VK_NULL_HANDLE, true );
704+ VulkanExampleBase::submitFrame (VK_NULL_HANDLE, true );
705+ }
692706 }
693707};
694708
0 commit comments