From 4f5f85925b316d0f3c77a99d387a1c2eebbdc2db Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 9 Jun 2021 08:05:55 +0200 Subject: [PATCH] [d3d9] Add frame rate limiter and d3d9.maxFrameRate option --- dxvk.conf | 8 ++++++++ src/d3d9/d3d9_options.cpp | 1 + src/d3d9/d3d9_options.h | 3 +++ src/d3d9/d3d9_swapchain.cpp | 41 +++++++++++++++++++++++++++++-------- src/d3d9/d3d9_swapchain.h | 5 +++++ 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/dxvk.conf b/dxvk.conf index e4ff023d..349dc944 100644 --- a/dxvk.conf +++ b/dxvk.conf @@ -19,6 +19,14 @@ # d3d9.maxFrameLatency = 0 +# Enables a frame rate limiter, unless the game is already +# limited to the same refresh rate by vertical synchronization. +# +# Supported values : Any non-negative integer + +# d3d9.maxFrameRate = 0 + + # Override PCI vendor and device IDs reported to the application. Can # cause the app to adjust behaviour depending on the selected values. # diff --git a/src/d3d9/d3d9_options.cpp b/src/d3d9/d3d9_options.cpp index fa2564c2..d373aa9d 100644 --- a/src/d3d9/d3d9_options.cpp +++ b/src/d3d9/d3d9_options.cpp @@ -40,6 +40,7 @@ namespace dxvk { : (adapter != nullptr ? adapter->deviceProperties().vendorID : 0); this->maxFrameLatency = config.getOption ("d3d9.maxFrameLatency", 0); + this->maxFrameRate = config.getOption ("d3d9.maxFrameRate", 0); this->presentInterval = config.getOption ("d3d9.presentInterval", -1); this->shaderModel = config.getOption ("d3d9.shaderModel", 3); this->evictManagedOnUnlock = config.getOption ("d3d9.evictManagedOnUnlock", false); diff --git a/src/d3d9/d3d9_options.h b/src/d3d9/d3d9_options.h index 87e1e0ec..e49bb61e 100644 --- a/src/d3d9/d3d9_options.h +++ b/src/d3d9/d3d9_options.h @@ -26,6 +26,9 @@ namespace dxvk { /// a higher value. May help with frame timing issues. int32_t maxFrameLatency; + /// Limit frame rate + int32_t maxFrameRate; + /// Set the max shader model the device can support in the caps. int32_t shaderModel; diff --git a/src/d3d9/d3d9_swapchain.cpp b/src/d3d9/d3d9_swapchain.cpp index 8b37a9cb..35a522bd 100644 --- a/src/d3d9/d3d9_swapchain.cpp +++ b/src/d3d9/d3d9_swapchain.cpp @@ -173,7 +173,7 @@ namespace dxvk { , m_context (m_device->createContext()) , m_frameLatencyCap (pDevice->GetOptions()->maxFrameLatency) , m_frameLatencySignal(new sync::Fence(m_frameId)) - , m_dialog (pDevice->GetOptions()->enableDialogMode) { + , m_dialog (pDevice->GetOptions()->enableDialogMode) { this->NormalizePresentParameters(pPresentParams); m_presentParams = *pPresentParams; m_window = m_presentParams.hDeviceWindow; @@ -914,7 +914,10 @@ namespace dxvk { m_device->vkd(), presenterDevice, presenterDesc); - + + m_presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate); + m_presenter->setFrameRateLimiterRefreshRate(m_displayRefreshRate); + CreateRenderTargetViews(); } @@ -1138,6 +1141,16 @@ namespace dxvk { return option > 0 ? uint32_t(option) : uint32_t(Preferred); } + + void D3D9SwapChainEx::NotifyDisplayRefreshRate( + double RefreshRate) { + m_displayRefreshRate = RefreshRate; + + if (m_presenter != nullptr) + m_presenter->setFrameRateLimiterRefreshRate(RefreshRate); + } + + HRESULT D3D9SwapChainEx::EnterFullscreenMode( D3DPRESENT_PARAMETERS* pPresentParams, const D3DDISPLAYMODEEX* pFullscreenDisplayMode) { @@ -1246,9 +1259,19 @@ namespace dxvk { devMode.dmDisplayFrequency = mode.RefreshRate; } - return SetMonitorDisplayMode(GetDefaultMonitor(), &devMode) - ? D3D_OK - : D3DERR_NOTAVAILABLE; + HMONITOR monitor = GetDefaultMonitor(); + + if (!SetMonitorDisplayMode(monitor, &devMode)) + return D3DERR_NOTAVAILABLE; + + devMode.dmFields = DM_DISPLAYFREQUENCY; + + if (GetMonitorDisplayMode(monitor, ENUM_CURRENT_SETTINGS, &devMode)) + NotifyDisplayRefreshRate(double(devMode.dmDisplayFrequency)); + else + NotifyDisplayRefreshRate(0.0); + + return D3D_OK; } @@ -1256,9 +1279,11 @@ namespace dxvk { if (hMonitor == nullptr) return D3DERR_INVALIDCALL; - return RestoreMonitorDisplayMode() - ? D3D_OK - : D3DERR_NOTAVAILABLE; + if (!RestoreMonitorDisplayMode()) + return D3DERR_NOTAVAILABLE; + + NotifyDisplayRefreshRate(0.0); + return D3D_OK; } bool D3D9SwapChainEx::UpdatePresentRegion(const RECT* pSourceRect, const RECT* pDestRect) { diff --git a/src/d3d9/d3d9_swapchain.h b/src/d3d9/d3d9_swapchain.h index ca21f69f..24feb3ef 100644 --- a/src/d3d9/d3d9_swapchain.h +++ b/src/d3d9/d3d9_swapchain.h @@ -128,6 +128,8 @@ namespace dxvk { WindowState m_windowState; + double m_displayRefreshRate = 0.0; + void PresentImage(UINT PresentInterval); void SubmitPresent(const vk::PresenterSync& Sync, uint32_t FrameId); @@ -167,6 +169,9 @@ namespace dxvk { void NormalizePresentParameters(D3DPRESENT_PARAMETERS* pPresentParams); + void NotifyDisplayRefreshRate( + double RefreshRate); + HRESULT EnterFullscreenMode( D3DPRESENT_PARAMETERS* pPresentParams, const D3DDISPLAYMODEEX* pFullscreenDisplayMode);