From b1c2cdbec8dd978a9e2bb0e41461eaab63d4a33d Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Sat, 4 Mar 2023 21:15:32 -0500 Subject: [PATCH] More conservative frame sync: wait before vs after DX12 / Vulkan present operations --- neo/sys/DeviceManager_DX12.cpp | 10 +++++----- neo/sys/DeviceManager_VK.cpp | 21 ++++++--------------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/neo/sys/DeviceManager_DX12.cpp b/neo/sys/DeviceManager_DX12.cpp index e357fed3..a13de424 100644 --- a/neo/sys/DeviceManager_DX12.cpp +++ b/neo/sys/DeviceManager_DX12.cpp @@ -636,6 +636,11 @@ void DeviceManager_DX12::EndFrame() void DeviceManager_DX12::Present() { + // SRS - Sync on previous frame's command queue completion vs. waitForIdle() on whole device + nvrhiDevice->waitEventQuery( m_FrameWaitQuery ); + nvrhiDevice->resetEventQuery( m_FrameWaitQuery ); + nvrhiDevice->setEventQuery( m_FrameWaitQuery, nvrhi::CommandQueue::Graphics ); + if( !windowVisible ) { return; @@ -654,11 +659,6 @@ void DeviceManager_DX12::Present() // SRS - Don't change deviceParms.vsyncEnabled here, simply test for vsync mode 2 to set DXGI SyncInterval m_SwapChain->Present( deviceParms.vsyncEnabled && r_swapInterval.GetInteger() == 2 ? 1 : 0, presentFlags ); - // SRS - Sync on previous frame's command queue completion vs. waitForIdle() on whole device - nvrhiDevice->waitEventQuery( m_FrameWaitQuery ); - nvrhiDevice->resetEventQuery( m_FrameWaitQuery ); - nvrhiDevice->setEventQuery( m_FrameWaitQuery, nvrhi::CommandQueue::Graphics ); - m_FrameFence->SetEventOnCompletion( m_FrameCount, m_FrameFenceEvents[bufferIndex] ); m_GraphicsQueue->Signal( m_FrameFence, m_FrameCount ); m_FrameCount++; diff --git a/neo/sys/DeviceManager_VK.cpp b/neo/sys/DeviceManager_VK.cpp index d2314abd..c5a7ab1c 100644 --- a/neo/sys/DeviceManager_VK.cpp +++ b/neo/sys/DeviceManager_VK.cpp @@ -1270,6 +1270,11 @@ void DeviceManager_VK::EndFrame() void DeviceManager_VK::Present() { + // SRS - Sync on previous frame's command queue completion vs. waitForIdle() on whole device + m_NvrhiDevice->waitEventQuery( m_FrameWaitQuery ); + m_NvrhiDevice->resetEventQuery( m_FrameWaitQuery ); + m_NvrhiDevice->setEventQuery( m_FrameWaitQuery, nvrhi::CommandQueue::Graphics ); + vk::PresentInfoKHR info = vk::PresentInfoKHR() .setWaitSemaphoreCount( 1 ) .setPWaitSemaphores( &m_PresentSemaphore ) @@ -1280,26 +1285,12 @@ void DeviceManager_VK::Present() const vk::Result res = m_PresentQueue.presentKHR( &info ); assert( res == vk::Result::eSuccess || res == vk::Result::eErrorOutOfDateKHR || res == vk::Result::eSuboptimalKHR ); - if( deviceParms.enableDebugRuntime ) + if( deviceParms.enableDebugRuntime || deviceParms.vsyncEnabled ) { // according to vulkan-tutorial.com, "the validation layer implementation expects // the application to explicitly synchronize with the GPU" m_PresentQueue.waitIdle(); } - else - { - if( deviceParms.vsyncEnabled ) - { - m_PresentQueue.waitIdle(); - } - // SRS - Sync on previous frame's command queue completion vs. waitForIdle() on whole device - else - { - m_NvrhiDevice->waitEventQuery( m_FrameWaitQuery ); - m_NvrhiDevice->resetEventQuery( m_FrameWaitQuery ); - m_NvrhiDevice->setEventQuery( m_FrameWaitQuery, nvrhi::CommandQueue::Graphics ); - } - } } DeviceManager* DeviceManager::CreateVK()