From f4ec69021db51dc801fb928971a2c1c01a498d74 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Thu, 14 Mar 2024 21:18:57 +0100 Subject: [PATCH] impr: Manually implement VSync because GPU manufacturers are terrible at writing drivers --- main/gui/source/window/window.cpp | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/main/gui/source/window/window.cpp b/main/gui/source/window/window.cpp index d8372c795..3f6311a04 100644 --- a/main/gui/source/window/window.cpp +++ b/main/gui/source/window/window.cpp @@ -208,7 +208,6 @@ namespace hex { // Long sleep mode is enabled automatically after a few frames if the window content hasn't changed // and no events have been received if (shouldLongSleep) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // Calculate the time until the next frame constexpr static auto LongSleepFPS = 5.0; const double timeout = std::max(0.0, (1.0 / LongSleepFPS) - (glfwGetTime() - m_lastStartFrameTime)); @@ -236,15 +235,28 @@ namespace hex { // Limit frame rate // If the target FPS are below 15, use the monitor refresh rate, if it's above 200, don't limit the frame rate - const auto targetFPS = ImHexApi::System::getTargetFPS(); - if (targetFPS < 15) { - glfwSwapInterval(1); - } else if (targetFPS > 200) { - glfwSwapInterval(0); + auto targetFPS = ImHexApi::System::getTargetFPS(); + if (targetFPS >= 200) { + // Let it rip } else { + // If the target frame rate is below 15, use the current monitor's refresh rate + if (targetFPS < 15) { + // Fall back to 60 FPS if the monitor refresh rate cannot be determined + targetFPS = 60; + + if (auto monitor = glfwGetWindowMonitor(m_window); monitor != nullptr) { + if (auto videoMode = glfwGetVideoMode(monitor); videoMode != nullptr) { + targetFPS = videoMode->refreshRate; + } + } + } + + // Sleep if we're not in long sleep mode if (!shouldLongSleep) { - glfwSwapInterval(0); + // If anything goes wrong with these checks, make sure that we're sleeping for at least 1ms std::this_thread::sleep_for(std::chrono::milliseconds(1)); + + // Sleep for the remaining time if the frame rate is above the target frame rate const auto frameTime = glfwGetTime() - m_lastStartFrameTime; const auto targetFrameTime = 1.0 / targetFPS; if (frameTime < targetFrameTime) { @@ -718,7 +730,9 @@ namespace hex { glfwSetWindowOpacity(m_window, 1.0F); glfwMakeContextCurrent(m_window); - glfwSwapInterval(1); + + // Disable VSync. Not like any graphics driver actually cares + glfwSwapInterval(0); // Center window GLFWmonitor *monitor = glfwGetPrimaryMonitor();