diff --git a/src/d3d11/d3d11_swapchain.cpp b/src/d3d11/d3d11_swapchain.cpp index d98e4d807..405539c1d 100644 --- a/src/d3d11/d3d11_swapchain.cpp +++ b/src/d3d11/d3d11_swapchain.cpp @@ -34,6 +34,7 @@ namespace dxvk { InitRenderState(); InitSamplers(); InitShaders(); + InitOptions(); } @@ -194,8 +195,7 @@ namespace dxvk { void D3D11SwapChain::PresentImage(UINT SyncInterval) { - // Wait for the sync event so that we - // respect the maximum frame latency + // Wait for the sync event so that we respect the maximum frame latency Rc syncEvent = m_dxgiDevice->GetFrameSyncEvent(m_desc.BufferCount); syncEvent->wait(); @@ -203,6 +203,9 @@ namespace dxvk { m_hud->update(); for (uint32_t i = 0; i < SyncInterval || i < 1; i++) { + if (m_asyncPresent) + SynchronizePresent(); + m_context->beginRecording( m_device->createCommandList()); @@ -308,16 +311,27 @@ namespace dxvk { m_device->presentImage(m_presenter, sync.present, &m_presentStatus); - - status = m_device->waitForSubmission(&m_presentStatus); - - if (status != VK_SUCCESS) - RecreateSwapChain(m_vsync); + + if (!m_asyncPresent) + SynchronizePresent(); } } - + + void D3D11SwapChain::SynchronizePresent() { + // Recreate swap chain if the previous present call failed + VkResult status = m_device->waitForSubmission(&m_presentStatus); + + if (status != VK_SUCCESS) + RecreateSwapChain(m_vsync); + } + + void D3D11SwapChain::RecreateSwapChain(BOOL Vsync) { + // Ensure that we can safely destroy the swap chain + m_device->waitForSubmission(&m_presentStatus); + m_presentStatus.result = VK_SUCCESS; + vk::PresenterDesc presenterDesc; presenterDesc.imageExtent = { m_desc.Width, m_desc.Height }; presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1); @@ -582,6 +596,16 @@ namespace dxvk { } + void D3D11SwapChain::InitOptions() { + // Not synchronizing after present seems to increase + // the likelyhood of hangs on Nvidia for some reason. + m_asyncPresent = !m_device->adapter()->matchesDriver( + DxvkGpuVendor::Nvidia, VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR, 0, 0); + + applyTristate(m_asyncPresent, m_parent->GetOptions()->asyncPresent); + } + + void D3D11SwapChain::InitRenderState() { m_iaState.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; m_iaState.primitiveRestart = VK_FALSE; diff --git a/src/d3d11/d3d11_swapchain.h b/src/d3d11/d3d11_swapchain.h index 145757317..671a82802 100644 --- a/src/d3d11/d3d11_swapchain.h +++ b/src/d3d11/d3d11_swapchain.h @@ -120,8 +120,12 @@ namespace dxvk { bool m_dirty = true; bool m_vsync = true; + bool m_asyncPresent = false; + void PresentImage(UINT SyncInterval); + void SynchronizePresent(); + void FlushImmediateContext(); void RecreateSwapChain( @@ -141,6 +145,8 @@ namespace dxvk { void CreateHud(); + void InitOptions(); + void InitRenderState(); void InitSamplers();