diff --git a/src/dxgi/dxgi_swapchain.cpp b/src/dxgi/dxgi_swapchain.cpp index 73a5ad6b1..67e2a54cd 100644 --- a/src/dxgi/dxgi_swapchain.cpp +++ b/src/dxgi/dxgi_swapchain.cpp @@ -997,6 +997,27 @@ namespace dxvk { if (m_presenter2 == nullptr) return; + // Engage the frame limiter with large sync intervals even in windowed + // mode since we want to avoid double-presenting to the swap chain. + if (SyncInterval != m_frameRateSyncInterval && m_descFs.Windowed) { + m_frameRateSyncInterval = SyncInterval; + m_frameRateRefresh = 0.0f; + + if (SyncInterval > 1 && wsi::isWindow(m_window)) { + wsi::WsiMode mode = { }; + + if (wsi::getCurrentDisplayMode(wsi::getWindowMonitor(m_window), &mode)) { + if (mode.refreshRate.numerator && mode.refreshRate.denominator) { + m_frameRateRefresh = double(mode.refreshRate.numerator) + / double(mode.refreshRate.denominator); + } + } + } + } else if (!m_descFs.Windowed) { + // Reset tracking when in fullscreen mode + m_frameRateSyncInterval = 0; + } + // Use a negative number to indicate that the limiter should only // be engaged if the target frame rate is actually exceeded double frameRate = std::max(m_frameRateOption, 0.0); diff --git a/src/dxgi/dxgi_swapchain.h b/src/dxgi/dxgi_swapchain.h index b5fb93f96..28be599b0 100644 --- a/src/dxgi/dxgi_swapchain.h +++ b/src/dxgi/dxgi_swapchain.h @@ -199,6 +199,7 @@ namespace dxvk { double m_frameRateOption = 0.0; double m_frameRateRefresh = 0.0; double m_frameRateLimit = 0.0; + uint32_t m_frameRateSyncInterval = 0u; bool m_is_d3d12; DXGI_COLOR_SPACE_TYPE m_colorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;