[d3d9] Add frame rate limiter and d3d9.maxFrameRate option

This commit is contained in:
Philip Rebohle 2021-06-09 08:05:55 +02:00 committed by Philip Rebohle
parent b537f19a3c
commit 4f5f85925b
5 changed files with 50 additions and 8 deletions

View File

@ -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.
#

View File

@ -40,6 +40,7 @@ namespace dxvk {
: (adapter != nullptr ? adapter->deviceProperties().vendorID : 0);
this->maxFrameLatency = config.getOption<int32_t> ("d3d9.maxFrameLatency", 0);
this->maxFrameRate = config.getOption<int32_t> ("d3d9.maxFrameRate", 0);
this->presentInterval = config.getOption<int32_t> ("d3d9.presentInterval", -1);
this->shaderModel = config.getOption<int32_t> ("d3d9.shaderModel", 3);
this->evictManagedOnUnlock = config.getOption<bool> ("d3d9.evictManagedOnUnlock", false);

View File

@ -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;

View File

@ -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) {

View File

@ -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);