From 69bad7bf8c01116981e40dd74e09f71e464e2097 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 25 Nov 2019 17:45:28 +0100 Subject: [PATCH] [d3d11] Move frame latency handling into D3D11SwapChain --- src/d3d11/d3d11_device.cpp | 24 +++--------------------- src/d3d11/d3d11_device.h | 9 +-------- src/d3d11/d3d11_swapchain.cpp | 26 ++++++++++++++++++++++++-- src/d3d11/d3d11_swapchain.h | 12 ++++++++++-- 4 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 3f5a5fb6..75acde81 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -2474,10 +2474,8 @@ namespace dxvk { m_d3d11Device (this, FeatureLevel, FeatureFlags), m_d3d11DeviceExt(this, &m_d3d11Device), m_d3d11Interop (this, &m_d3d11Device), - m_wineFactory (this, &m_d3d11Device), - m_frameLatencyCap(m_d3d11Device.GetOptions()->maxFrameLatency) { - for (uint32_t i = 0; i < m_frameEvents.size(); i++) - m_frameEvents[i] = new sync::Signal(true); + m_wineFactory (this, &m_d3d11Device) { + } @@ -2712,7 +2710,7 @@ namespace dxvk { if (MaxLatency == 0) MaxLatency = DefaultFrameLatency; - if (MaxLatency > m_frameEvents.size()) + if (MaxLatency > DXGI_MAX_SWAP_CHAIN_BUFFERS) return DXGI_ERROR_INVALID_CALL; m_frameLatency = MaxLatency; @@ -2790,22 +2788,6 @@ namespace dxvk { } - Rc STDMETHODCALLTYPE D3D11DXGIDevice::GetFrameSyncEvent(UINT BufferCount) { - uint32_t frameLatency = m_frameLatency; - - if (BufferCount != 0 - && BufferCount <= frameLatency) - frameLatency = BufferCount; - - if (m_frameLatencyCap != 0 - && m_frameLatencyCap <= frameLatency) - frameLatency = m_frameLatencyCap; - - uint32_t frameId = m_frameId++ % frameLatency; - return m_frameEvents[frameId]; - } - - Rc STDMETHODCALLTYPE D3D11DXGIDevice::GetDXVKDevice() { return m_dxvkDevice; } diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index c0c43884..40dcc986 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -634,9 +634,6 @@ namespace dxvk { void STDMETHODCALLTYPE Trim() final; - Rc STDMETHODCALLTYPE GetFrameSyncEvent( - UINT BufferCount); - Rc STDMETHODCALLTYPE GetDXVKDevice(); private: @@ -653,11 +650,7 @@ namespace dxvk { WineDXGISwapChainFactory m_wineFactory; - uint32_t m_frameLatencyCap = 0; - uint32_t m_frameLatency = DefaultFrameLatency; - uint32_t m_frameId = 0; - - std::array, 16> m_frameEvents; + uint32_t m_frameLatency = DefaultFrameLatency; Rc CreateDevice(D3D_FEATURE_LEVEL FeatureLevel); diff --git a/src/d3d11/d3d11_swapchain.cpp b/src/d3d11/d3d11_swapchain.cpp index d97ed50f..a52feaf6 100644 --- a/src/d3d11/d3d11_swapchain.cpp +++ b/src/d3d11/d3d11_swapchain.cpp @@ -24,7 +24,10 @@ namespace dxvk { m_window (hWnd), m_desc (*pDesc), m_device (pDevice->GetDXVKDevice()), - m_context (m_device->createContext()) { + m_context (m_device->createContext()), + m_frameLatencyCap(pDevice->GetOptions()->maxFrameLatency) { + CreateFrameLatencySignals(); + if (!pDevice->GetOptions()->deferSurfaceCreation) CreatePresenter(); @@ -206,7 +209,8 @@ namespace dxvk { immediateContext->Flush(); // Wait for the sync event so that we respect the maximum frame latency - auto syncEvent = m_dxgiDevice->GetFrameSyncEvent(m_desc.BufferCount); + uint32_t frameId = m_frameId++ % GetActualFrameLatency(); + auto syncEvent = m_frameLatencySignals[frameId]; syncEvent->wait(); if (m_hud != nullptr) @@ -366,6 +370,12 @@ namespace dxvk { } + void D3D11SwapChain::CreateFrameLatencySignals() { + for (uint32_t i = 0; i < m_frameLatencySignals.size(); i++) + m_frameLatencySignals[i] = new sync::Signal(true); + } + + void D3D11SwapChain::CreatePresenter() { DxvkDeviceQueue graphicsQueue = m_device->queues().graphics; @@ -709,6 +719,18 @@ namespace dxvk { } + uint32_t D3D11SwapChain::GetActualFrameLatency() { + uint32_t maxFrameLatency = DefaultFrameLatency; + m_dxgiDevice->GetMaximumFrameLatency(&maxFrameLatency); + + if (m_frameLatencyCap) + maxFrameLatency = std::min(maxFrameLatency, m_frameLatencyCap); + + maxFrameLatency = std::min(maxFrameLatency, m_desc.BufferCount + 1); + return maxFrameLatency; + } + + uint32_t D3D11SwapChain::PickFormats( DXGI_FORMAT Format, VkSurfaceFormatKHR* pDstFormats) { diff --git a/src/d3d11/d3d11_swapchain.h b/src/d3d11/d3d11_swapchain.h index de42f172..34d4d4f8 100644 --- a/src/d3d11/d3d11_swapchain.h +++ b/src/d3d11/d3d11_swapchain.h @@ -21,7 +21,7 @@ namespace dxvk { }; class D3D11SwapChain : public ComObject { - + constexpr static uint32_t DefaultFrameLatency = 1; public: D3D11SwapChain( @@ -68,7 +68,7 @@ namespace dxvk { UINT SyncInterval, UINT PresentFlags, const DXGI_PRESENT_PARAMETERS* pPresentParameters); - + private: enum BindingIds : uint32_t { @@ -117,6 +117,10 @@ namespace dxvk { std::vector> m_imageViews; + uint32_t m_frameId = 0; + std::array, DXGI_MAX_SWAP_CHAIN_BUFFERS> m_frameLatencySignals; + uint32_t m_frameLatencyCap = 0; + bool m_dirty = true; bool m_vsync = true; @@ -131,6 +135,8 @@ namespace dxvk { void RecreateSwapChain( BOOL Vsync); + void CreateFrameLatencySignals(); + void CreatePresenter(); void CreateRenderTargetViews(); @@ -150,6 +156,8 @@ namespace dxvk { void InitSamplers(); void InitShaders(); + + uint32_t GetActualFrameLatency(); uint32_t PickFormats( DXGI_FORMAT Format,