From 65cc8c2b31fac593019755a42d2901d9e8a543c5 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 26 Nov 2019 00:24:33 +0100 Subject: [PATCH] [d3d11] Create frame latency event for swap chain Needed in order to support the DXGI 1.3 frame latency API. --- src/d3d11/d3d11_swapchain.cpp | 29 ++++++++++++++++++++++++++--- src/d3d11/d3d11_swapchain.h | 11 +++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/d3d11/d3d11_swapchain.cpp b/src/d3d11/d3d11_swapchain.cpp index 59f78c428..441eee604 100644 --- a/src/d3d11/d3d11_swapchain.cpp +++ b/src/d3d11/d3d11_swapchain.cpp @@ -26,7 +26,7 @@ namespace dxvk { m_device (pDevice->GetDXVKDevice()), m_context (m_device->createContext()), m_frameLatencyCap(pDevice->GetOptions()->maxFrameLatency) { - CreateFrameLatencySignal(); + CreateFrameLatencyEvent(); if (!pDevice->GetOptions()->deferSurfaceCreation) CreatePresenter(); @@ -45,6 +45,8 @@ namespace dxvk { if (m_backBuffer) m_backBuffer->ReleasePrivate(); + + DestroyFrameLatencyEvent(); } @@ -175,6 +177,9 @@ namespace dxvk { return DXGI_ERROR_INVALID_CALL; m_frameLatency = MaxLatency; + m_frameLatencySignal->wait(m_frameId - GetActualFrameLatency()); + + SignalFrameLatencyEvent(); return S_OK; } @@ -330,6 +335,8 @@ namespace dxvk { SubmitPresent(immediateContext, sync); } + + SignalFrameLatencyEvent(); } @@ -384,8 +391,11 @@ namespace dxvk { } - void D3D11SwapChain::CreateFrameLatencySignal() { - m_frameLatencySignal = new sync::Fence(m_frameId); + void D3D11SwapChain::CreateFrameLatencyEvent() { + m_frameLatencySignal = new sync::Win32Fence(m_frameId); + + if (m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT) + m_frameLatencyEvent = CreateEvent(nullptr, false, true, nullptr); } @@ -621,6 +631,11 @@ namespace dxvk { } + void D3D11SwapChain::DestroyFrameLatencyEvent() { + CloseHandle(m_frameLatencyEvent); + } + + void D3D11SwapChain::DestroyGammaTexture() { m_gammaTexture = nullptr; m_gammaTextureView = nullptr; @@ -732,6 +747,14 @@ namespace dxvk { } + void D3D11SwapChain::SignalFrameLatencyEvent() { + if (m_frameLatencyEvent) { + // Signal event with the same value that we'd wait for during the next present. + m_frameLatencySignal->setEvent(m_frameLatencyEvent, m_frameId - GetActualFrameLatency() + 1); + } + } + + uint32_t D3D11SwapChain::GetActualFrameLatency() { uint32_t maxFrameLatency = m_frameLatency; diff --git a/src/d3d11/d3d11_swapchain.h b/src/d3d11/d3d11_swapchain.h index cba25a4ab..fa10e3ff3 100644 --- a/src/d3d11/d3d11_swapchain.h +++ b/src/d3d11/d3d11_swapchain.h @@ -4,6 +4,8 @@ #include "../dxvk/hud/dxvk_hud.h" +#include "../util/sync/sync_signal_win32.h" + namespace dxvk { class D3D11Device; @@ -125,7 +127,8 @@ namespace dxvk { uint64_t m_frameId = DXGI_MAX_SWAP_CHAIN_BUFFERS; uint32_t m_frameLatency = DefaultFrameLatency; uint32_t m_frameLatencyCap = 0; - Rc m_frameLatencySignal; + HANDLE m_frameLatencyEvent = nullptr; + Rc m_frameLatencySignal; bool m_dirty = true; bool m_vsync = true; @@ -141,7 +144,7 @@ namespace dxvk { void RecreateSwapChain( BOOL Vsync); - void CreateFrameLatencySignal(); + void CreateFrameLatencyEvent(); void CreatePresenter(); @@ -153,6 +156,8 @@ namespace dxvk { UINT NumControlPoints, const D3D11_VK_GAMMA_CP* pControlPoints); + void DestroyFrameLatencyEvent(); + void DestroyGammaTexture(); void CreateHud(); @@ -163,6 +168,8 @@ namespace dxvk { void InitShaders(); + void SignalFrameLatencyEvent(); + uint32_t GetActualFrameLatency(); uint32_t PickFormats(