Skip to content

Commit 08422aa

Browse files
committed
GPU Vulkan Display: Improve semaphores and fences for rendering, allow full CPU + render + display overlap
1 parent 9af7793 commit 08422aa

2 files changed

Lines changed: 33 additions & 17 deletions

File tree

‎GPU/GPUTracking/display/backend/GPUDisplayBackendVulkan.cxx‎

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,9 @@ void GPUDisplayBackendVulkan::createSemaphoresAndFences()
562562
mTextFinishedSemaphore.resize(mFramesInFlight);
563563
mMixFinishedSemaphore.resize(mFramesInFlight);
564564
mDownsampleFinishedSemaphore.resize(mFramesInFlight);
565+
mPresentSemaphore.resize(mImageCount);
565566
mInFlightFence.resize(mFramesInFlight);
567+
mImageFence.resize(mImageCount);
566568
for (uint32_t i = 0; i < mFramesInFlight; i++) {
567569
mImageAvailableSemaphore[i] = mDevice.createSemaphore(semaphoreInfo, nullptr);
568570
mRenderFinishedSemaphore[i] = mDevice.createSemaphore(semaphoreInfo, nullptr);
@@ -571,6 +573,10 @@ void GPUDisplayBackendVulkan::createSemaphoresAndFences()
571573
mDownsampleFinishedSemaphore[i] = mDevice.createSemaphore(semaphoreInfo, nullptr);
572574
mInFlightFence[i] = mDevice.createFence(fenceInfo, nullptr);
573575
}
576+
for (uint32_t i = 0; i < mImageCount; i++) {
577+
mPresentSemaphore[i] = mDevice.createSemaphore(semaphoreInfo, nullptr);
578+
mImageFence[i] = VkFence(VK_NULL_HANDLE);
579+
}
574580
fenceInfo.flags = {};
575581
mSingleCommitFence = mDevice.createFence(fenceInfo, nullptr);
576582
}
@@ -582,6 +588,7 @@ void GPUDisplayBackendVulkan::clearSemaphoresAndFences()
582588
clearVector(mTextFinishedSemaphore, [&](auto& x) { mDevice.destroySemaphore(x, nullptr); });
583589
clearVector(mMixFinishedSemaphore, [&](auto& x) { mDevice.destroySemaphore(x, nullptr); });
584590
clearVector(mDownsampleFinishedSemaphore, [&](auto& x) { mDevice.destroySemaphore(x, nullptr); });
591+
clearVector(mPresentSemaphore, [&](auto& x) { mDevice.destroySemaphore(x, nullptr); });
585592
clearVector(mInFlightFence, [&](auto& x) { mDevice.destroyFence(x, nullptr); });
586593
mDevice.destroyFence(mSingleCommitFence, nullptr);
587594
}
@@ -768,11 +775,11 @@ void GPUDisplayBackendVulkan::createSwapChain(bool forScreenshot, bool forMixing
768775
mSwapChain = mDevice.createSwapchainKHR(swapCreateInfo, nullptr);
769776

770777
mSwapChainImages = mDevice.getSwapchainImagesKHR(mSwapChain);
771-
uint32_t oldFramesInFlight = mFramesInFlight;
778+
uint32_t oldFramesInFlight = mFramesInFlight, oldImageCount = mImageCount;
772779
mFramesInFlight = mDisplay->cfg().vulkan.nFramesInFlight;
773780
mImageCount = mSwapChainImages.size();
774781

775-
if (mFramesInFlight > oldFramesInFlight || !mCommandInfrastructureCreated) {
782+
if (mFramesInFlight != oldFramesInFlight || mImageCount != oldImageCount || !mCommandInfrastructureCreated) {
776783
if (mCommandInfrastructureCreated) {
777784
clearUniformLayoutsAndBuffers(); // TODO: Check what must actually be cleaned up if frames in flight changes
778785
clearCommandBuffers();
@@ -1522,12 +1529,7 @@ void GPUDisplayBackendVulkan::prepareDraw(const hmm_mat4& proj, const hmm_mat4&
15221529
mCurrentFrame = (mCurrentFrame + 1) % mFramesInFlight;
15231530
CHKERR(mDevice.waitForFences(1, &mInFlightFence[mCurrentFrame], true, UINT64_MAX));
15241531
auto getImage = [&]() {
1525-
vk::Fence fen = VkFence(VK_NULL_HANDLE);
1526-
vk::Semaphore sem = VkSemaphore(VK_NULL_HANDLE);
1527-
fen = mInFlightFence[mCurrentFrame];
1528-
CHKERR(mDevice.resetFences(1, &fen));
1529-
// sem = mImageAvailableSemaphore[mCurrentFrame]; // TODO: Why not !
1530-
return mDevice.acquireNextImageKHR(mSwapChain, UINT64_MAX, sem, fen, &mCurrentImageIndex);
1532+
return mDevice.acquireNextImageKHR(mSwapChain, UINT64_MAX, mImageAvailableSemaphore[mCurrentFrame], VkFence(VK_NULL_HANDLE), &mCurrentImageIndex);
15311533
};
15321534

15331535
vk::Result retVal = vk::Result::eSuccess;
@@ -1545,8 +1547,12 @@ void GPUDisplayBackendVulkan::prepareDraw(const hmm_mat4& proj, const hmm_mat4&
15451547
retVal = getImage();
15461548
}
15471549
CHKERR(retVal);
1548-
CHKERR(mDevice.waitForFences(1, &mInFlightFence[mCurrentFrame], true, UINT64_MAX));
1550+
if (mImageFence[mCurrentImageIndex]) {
1551+
CHKERR(mDevice.waitForFences(1, &mImageFence[mCurrentImageIndex], true, UINT64_MAX));
1552+
}
1553+
mImageFence[mCurrentImageIndex] = mInFlightFence[mCurrentFrame];
15491554
CHKERR(mDevice.resetFences(1, &mInFlightFence[mCurrentFrame]));
1555+
15501556
mMustUpdateSwapChain = false;
15511557
mHasDrawnText = false;
15521558

@@ -1578,14 +1584,14 @@ void GPUDisplayBackendVulkan::finishFrame(bool doScreenshot, bool toMixBuffer, f
15781584

15791585
vk::SubmitInfo submitInfo{};
15801586
vk::PipelineStageFlags waitStages[] = {vk::PipelineStageFlagBits::eColorAttachmentOutput};
1581-
submitInfo.pWaitSemaphores = includeMixImage > 0.f ? &mRenderFinishedSemaphore[mCurrentFrame] : nullptr;
1582-
submitInfo.waitSemaphoreCount = submitInfo.pWaitSemaphores != nullptr ? 1 : 0;
1587+
submitInfo.pWaitSemaphores = includeMixImage > 0.f ? &mRenderFinishedSemaphore[mCurrentFrame] : &mImageAvailableSemaphore[mCurrentFrame];
1588+
submitInfo.waitSemaphoreCount = 1;
15831589
submitInfo.pWaitDstStageMask = waitStages;
15841590
submitInfo.commandBufferCount = 1;
15851591
submitInfo.pCommandBuffers = &mCurrentCommandBuffer;
15861592
submitInfo.signalSemaphoreCount = 1;
15871593
submitInfo.pSignalSemaphores = stageFinishedSemaphore;
1588-
CHKERR(mGraphicsQueue.submit(1, &submitInfo, includeMixImage > 0 || toMixBuffer || mHasDrawnText || mDownsampleFSAA ? noFence : mInFlightFence[mCurrentFrame]));
1594+
CHKERR(mGraphicsQueue.submit(1, &submitInfo, noFence));
15891595
if (!toMixBuffer) {
15901596
if (includeMixImage > 0.f) {
15911597
mixImages(mCommandBuffersTexture[mCurrentImageIndex], includeMixImage);
@@ -1595,7 +1601,7 @@ void GPUDisplayBackendVulkan::finishFrame(bool doScreenshot, bool toMixBuffer, f
15951601
submitInfo.pCommandBuffers = &mCommandBuffersTexture[mCurrentImageIndex];
15961602
stageFinishedSemaphore = &mMixFinishedSemaphore[mCurrentFrame];
15971603
submitInfo.pSignalSemaphores = stageFinishedSemaphore;
1598-
CHKERR(mGraphicsQueue.submit(1, &submitInfo, mHasDrawnText || mDownsampleFSAA ? noFence : mInFlightFence[mCurrentFrame]));
1604+
CHKERR(mGraphicsQueue.submit(1, &submitInfo, noFence));
15991605
}
16001606

16011607
if (mDownsampleFSAA) {
@@ -1606,7 +1612,7 @@ void GPUDisplayBackendVulkan::finishFrame(bool doScreenshot, bool toMixBuffer, f
16061612
submitInfo.waitSemaphoreCount = 1;
16071613
stageFinishedSemaphore = &mDownsampleFinishedSemaphore[mCurrentFrame];
16081614
submitInfo.pSignalSemaphores = stageFinishedSemaphore;
1609-
CHKERR(mGraphicsQueue.submit(1, &submitInfo, mHasDrawnText ? noFence : mInFlightFence[mCurrentFrame]));
1615+
CHKERR(mGraphicsQueue.submit(1, &submitInfo, noFence));
16101616
}
16111617

16121618
if (doScreenshot) {
@@ -1625,13 +1631,21 @@ void GPUDisplayBackendVulkan::finishFrame(bool doScreenshot, bool toMixBuffer, f
16251631
submitInfo.pCommandBuffers = &mCommandBuffersText[mCurrentImageIndex];
16261632
stageFinishedSemaphore = &mTextFinishedSemaphore[mCurrentFrame];
16271633
submitInfo.pSignalSemaphores = stageFinishedSemaphore;
1628-
CHKERR(mGraphicsQueue.submit(1, &submitInfo, mInFlightFence[mCurrentFrame]));
1634+
CHKERR(mGraphicsQueue.submit(1, &submitInfo, noFence));
16291635
}
16301636

1631-
CHKERR(mDevice.waitForFences(1, &mInFlightFence[mCurrentFrame], true, UINT64_MAX)); // TODO: I think we need to wait for the fence, so that the image was acquired before we present. Perhaps we can present later to avoid delays
1637+
vk::PipelineStageFlags presentWaitStage = vk::PipelineStageFlagBits::eAllCommands;
1638+
submitInfo.commandBufferCount = 0;
1639+
submitInfo.waitSemaphoreCount = 1;
1640+
submitInfo.pWaitSemaphores = stageFinishedSemaphore;
1641+
submitInfo.pWaitDstStageMask = &presentWaitStage;
1642+
submitInfo.signalSemaphoreCount = 1;
1643+
submitInfo.pSignalSemaphores = &mPresentSemaphore[mCurrentImageIndex];
1644+
CHKERR(mGraphicsQueue.submit(1, &submitInfo, mInFlightFence[mCurrentFrame])); // Empty submit to signal InFlightFence and PresentSemaphore
1645+
16321646
vk::PresentInfoKHR presentInfo{};
16331647
presentInfo.waitSemaphoreCount = 1;
1634-
presentInfo.pWaitSemaphores = stageFinishedSemaphore;
1648+
presentInfo.pWaitSemaphores = &mPresentSemaphore[mCurrentImageIndex];
16351649
presentInfo.swapchainCount = 1;
16361650
presentInfo.pSwapchains = &mSwapChain;
16371651
presentInfo.pImageIndices = &mCurrentImageIndex;

‎GPU/GPUTracking/display/backend/GPUDisplayBackendVulkan.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ class GPUDisplayBackendVulkan : public GPUDisplayBackend
181181
std::vector<vk::Semaphore> mTextFinishedSemaphore;
182182
std::vector<vk::Semaphore> mMixFinishedSemaphore;
183183
std::vector<vk::Semaphore> mDownsampleFinishedSemaphore;
184+
std::vector<vk::Semaphore> mPresentSemaphore;
184185
std::vector<vk::Fence> mInFlightFence;
186+
std::vector<vk::Fence> mImageFence;
185187
std::vector<VulkanBuffer> mUniformBuffersMat[3];
186188
std::vector<VulkanBuffer> mUniformBuffersCol[3];
187189
std::vector<vk::DescriptorSet> mDescriptorSets[3];

0 commit comments

Comments
 (0)