From d6497fe9f1eaa19ed6b91cbefb33e597f69206eb Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 7 Aug 2025 18:58:43 +0100 Subject: [PATCH] Avoid reusing semaphores that may still be in flight Fixes validation error `VUID-vkQueueSubmit-pSignalSemaphores-00067` At the moment, this is a little bit too enthusiastic when multiple windows are affected by the same RecordAndSubmitTask. It would be sufficient to use any one of their `renderFinishedSemaphore`s, but one's used from every window. This shouldn't make a major difference to anything, as they'll all be signalled at the same time and waited on by the same presentation, but in principle, redundant semaphores might have some overhead. If this change isn't satisfactory and some things warrant rearranging, then that might become moot anyway, so I've not done anything about it yet and will wait for feedback before doing so. --- include/vsg/app/Presentation.h | 1 - include/vsg/app/RecordAndSubmitTask.h | 1 - include/vsg/app/Window.h | 1 + src/vsg/app/Presentation.cpp | 7 +++---- src/vsg/app/RecordAndSubmitTask.cpp | 12 ++++++------ src/vsg/app/Viewer.cpp | 4 ---- src/vsg/app/Window.cpp | 3 +++ 7 files changed, 13 insertions(+), 16 deletions(-) diff --git a/include/vsg/app/Presentation.h b/include/vsg/app/Presentation.h index a611c1678c..c632049213 100644 --- a/include/vsg/app/Presentation.h +++ b/include/vsg/app/Presentation.h @@ -24,7 +24,6 @@ namespace vsg VkResult present(); Windows windows; - Semaphores waitSemaphores; // taken from RecordAndSubmitTasks.signalSemaphores ref_ptr queue; // assign in application for GraphicsQueue from device }; diff --git a/include/vsg/app/RecordAndSubmitTask.h b/include/vsg/app/RecordAndSubmitTask.h index abe8c739bc..461b37a3e9 100644 --- a/include/vsg/app/RecordAndSubmitTask.h +++ b/include/vsg/app/RecordAndSubmitTask.h @@ -39,7 +39,6 @@ namespace vsg Windows windows; Semaphores waitSemaphores; // assign in application setup CommandGraphs commandGraphs; // assign in application setup - Semaphores signalSemaphores; // connect to Presentation.waitSemaphores ref_ptr transferTask; // data is transferred for this frame diff --git a/include/vsg/app/Window.h b/include/vsg/app/Window.h index d1b475d251..7765bb22f9 100644 --- a/include/vsg/app/Window.h +++ b/include/vsg/app/Window.h @@ -122,6 +122,7 @@ namespace vsg ref_ptr imageView; ref_ptr framebuffer; ref_ptr imageAvailableSemaphore; + ref_ptr renderFinishedSemaphore; }; using Frames = std::vector; diff --git a/src/vsg/app/Presentation.cpp b/src/vsg/app/Presentation.cpp index 87512249b0..44928c34eb 100644 --- a/src/vsg/app/Presentation.cpp +++ b/src/vsg/app/Presentation.cpp @@ -20,10 +20,6 @@ VkResult Presentation::present() //debug("Presentation::present()"); std::vector vk_semaphores; - for (auto& semaphore : waitSemaphores) - { - vk_semaphores.emplace_back(*(semaphore)); - } std::vector vk_swapchains; std::vector indices; @@ -34,6 +30,9 @@ VkResult Presentation::present() { vk_swapchains.emplace_back(*(window->getOrCreateSwapchain())); indices.emplace_back(static_cast(imageIndex)); + + auto& renderFinishedSemaphore = window->frame(imageIndex).renderFinishedSemaphore; + vk_semaphores.push_back(*renderFinishedSemaphore); } } diff --git a/src/vsg/app/RecordAndSubmitTask.cpp b/src/vsg/app/RecordAndSubmitTask.cpp index 5306579f2e..81d3f64f76 100644 --- a/src/vsg/app/RecordAndSubmitTask.cpp +++ b/src/vsg/app/RecordAndSubmitTask.cpp @@ -215,6 +215,8 @@ VkResult RecordAndSubmitTask::finish(ref_ptr recordedCom if (earlyDataTransferredSemaphore) transferTask->assignTransferConsumedCompletedSemaphore(TransferTask::TRANSFER_BEFORE_RECORD_TRAVERSAL, earlyTransferConsumerCompletedSemaphore); if (lateDataTransferredSemaphore) transferTask->assignTransferConsumedCompletedSemaphore(TransferTask::TRANSFER_AFTER_RECORD_TRAVERSAL, lateTransferConsumerCompletedSemaphore); + current_fence->dependentSemaphores().clear(); + for (auto& window : windows) { auto imageIndex = window->imageIndex(); @@ -224,6 +226,10 @@ VkResult RecordAndSubmitTask::finish(ref_ptr recordedCom vk_waitSemaphores.emplace_back(*semaphore); vk_waitStages.emplace_back(semaphore->pipelineStageFlags()); + + auto& renderFinishedSemaphore = window->frame(imageIndex).renderFinishedSemaphore; + vk_signalSemaphores.emplace_back(*renderFinishedSemaphore); + current_fence->dependentSemaphores().push_back(renderFinishedSemaphore); } for (auto& semaphore : waitSemaphores) @@ -232,12 +238,6 @@ VkResult RecordAndSubmitTask::finish(ref_ptr recordedCom vk_waitStages.emplace_back(semaphore->pipelineStageFlags()); } - current_fence->dependentSemaphores() = signalSemaphores; - for (auto& semaphore : signalSemaphores) - { - vk_signalSemaphores.emplace_back(*(semaphore)); - } - if (earlyDataTransferredSemaphore) { vk_signalSemaphores.emplace_back(earlyTransferConsumerCompletedSemaphore->vk()); diff --git a/src/vsg/app/Viewer.cpp b/src/vsg/app/Viewer.cpp index bb3206c64e..9d8374e924 100644 --- a/src/vsg/app/Viewer.cpp +++ b/src/vsg/app/Viewer.cpp @@ -524,13 +524,10 @@ void Viewer::assignRecordAndSubmitTaskAndPresentation(CommandGraphs in_commandGr Windows activeWindows(findWindows.windows.begin(), findWindows.windows.end()); - auto renderFinishedSemaphore = vsg::Semaphore::create(device); - // set up Submission with CommandBuffer and signals auto recordAndSubmitTask = vsg::RecordAndSubmitTask::create(device, numBuffers); recordAndSubmitTask->commandGraphs = commandGraphs; recordAndSubmitTask->databasePager = databasePager; - recordAndSubmitTask->signalSemaphores.emplace_back(renderFinishedSemaphore); recordAndSubmitTask->windows = activeWindows; recordAndSubmitTask->queue = mainQueue; recordAndSubmitTasks.emplace_back(recordAndSubmitTask); @@ -541,7 +538,6 @@ void Viewer::assignRecordAndSubmitTaskAndPresentation(CommandGraphs in_commandGr if (instrumentation) recordAndSubmitTask->assignInstrumentation(instrumentation); auto presentation = vsg::Presentation::create(); - presentation->waitSemaphores.emplace_back(renderFinishedSemaphore); presentation->windows = activeWindows; presentation->queue = device->getQueue(deviceQueueFamily.presentFamily); presentations.emplace_back(presentation); diff --git a/src/vsg/app/Window.cpp b/src/vsg/app/Window.cpp index df738fb7b6..bac1c912db 100644 --- a/src/vsg/app/Window.cpp +++ b/src/vsg/app/Window.cpp @@ -447,6 +447,9 @@ VkResult Window::acquireNextImage(uint64_t timeout) // the acquired image's semaphore must be available now so make it the new _availableSemaphore and set its entry to the one to use for the next frame by swapping ref_ptr<>'s _availableSemaphore.swap(_frames[nextImageIndex].imageAvailableSemaphore); + if (!_frames[nextImageIndex].renderFinishedSemaphore) + _frames[nextImageIndex].renderFinishedSemaphore = vsg::Semaphore::create(_device); + // shift up previous frame indices for (size_t i = _indices.size() - 1; i > 0; --i) {