diff --git a/README.md b/README.md index 82a1fc1a..e8b46343 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,9 @@ The `DXVK_HUD` environment variable controls a HUD which can display the framera Additionally, `DXVK_HUD=1` has the same effect as `DXVK_HUD=devinfo,fps`, and `DXVK_HUD=full` enables all available HUD elements. +### Frame rate limit +The `DXVK_FRAME_RATE` environment variable can be used to limit the frame rate. A value of `0` uncaps the frame rate, while any positive value will limit rendering to the given number of frames per second. Alternatively, the configuration file can be used. + ### Device filter Some applications do not provide a method to select a different GPU. In that case, DXVK can be forced to use a given device: - `DXVK_FILTER_DEVICE_NAME="Device Name"` Selects devices with a matching Vulkan device name, which can be retrieved with tools such as `vulkaninfo`. Matches on substrings, so "VEGA" or "AMD RADV VEGA10" is supported if the full device name is "AMD RADV VEGA10 (LLVM 9.0.0)", for example. If the substring matches more than one device, the first device matched will be used. diff --git a/src/util/util_fps_limiter.cpp b/src/util/util_fps_limiter.cpp index b7a263e1..c9a7f18a 100644 --- a/src/util/util_fps_limiter.cpp +++ b/src/util/util_fps_limiter.cpp @@ -1,6 +1,7 @@ #include #include "thread.h" +#include "util_env.h" #include "util_fps_limiter.h" #include "util_string.h" @@ -9,7 +10,16 @@ namespace dxvk { FpsLimiter::FpsLimiter() { + std::string env = env::getEnvVar("DXVK_FRAME_RATE"); + if (!env.empty()) { + try { + setTargetFrameRate(std::stod(env)); + m_envOverride = true; + } catch (const std::invalid_argument&) { + // no-op + } + } } @@ -21,12 +31,14 @@ namespace dxvk { void FpsLimiter::setTargetFrameRate(double frameRate) { std::lock_guard lock(m_mutex); - m_targetInterval = frameRate > 0.0 - ? NtTimerDuration(int64_t(double(NtTimerDuration::period::den) / frameRate)) - : NtTimerDuration::zero(); + if (!m_envOverride) { + m_targetInterval = frameRate > 0.0 + ? NtTimerDuration(int64_t(double(NtTimerDuration::period::den) / frameRate)) + : NtTimerDuration::zero(); - if (isEnabled() && !m_initialized) - initialize(); + if (isEnabled() && !m_initialized) + initialize(); + } } @@ -48,7 +60,8 @@ namespace dxvk { // If the swap chain is known to have vsync enabled and the // refresh rate is similar to the target frame rate, disable // the limiter so it does not screw up frame times - if (vsyncEnabled && m_refreshInterval * 100 > m_targetInterval * 97) + if (vsyncEnabled && !m_envOverride + && m_refreshInterval * 100 > m_targetInterval * 97) return; auto t0 = m_lastFrame; diff --git a/src/util/util_fps_limiter.h b/src/util/util_fps_limiter.h index f90af7d4..bf3293b8 100644 --- a/src/util/util_fps_limiter.h +++ b/src/util/util_fps_limiter.h @@ -74,6 +74,7 @@ namespace dxvk { TimePoint m_lastFrame; bool m_initialized = false; + bool m_envOverride = false; NtTimerDuration m_sleepGranularity = NtTimerDuration::zero(); NtTimerDuration m_sleepThreshold = NtTimerDuration::zero();