1
0
mirror of synced 2025-02-26 14:21:39 +01:00

impr: Don't wake up frame rate limiter thread more often than necessary

This commit is contained in:
WerWolv 2025-02-23 20:25:29 +01:00
parent 4c0e8bc1d6
commit 7879f8b6a4
3 changed files with 54 additions and 25 deletions

View File

@ -53,6 +53,9 @@ namespace hex {
void drawImGui(); void drawImGui();
void drawWithShader(); void drawWithShader();
void unlockFrameRate();
void forceNewFrame();
GLFWwindow *m_window = nullptr; GLFWwindow *m_window = nullptr;
std::string m_windowTitle, m_windowTitleFull; std::string m_windowTitle, m_windowTitleFull;
@ -64,17 +67,22 @@ namespace hex {
std::list<std::string> m_popupsToOpen; std::list<std::string> m_popupsToOpen;
std::set<int> m_pressedKeys; std::set<int> m_pressedKeys;
std::atomic<bool> m_unlockFrameRate = true;
ImGuiExt::ImHexCustomData m_imguiCustomData; ImGuiExt::ImHexCustomData m_imguiCustomData;
u32 m_searchBarPosition = 0; u32 m_searchBarPosition = 0;
bool m_emergencyPopupOpen = false; bool m_emergencyPopupOpen = false;
std::jthread m_frameRateThread; std::jthread m_frameRateThread;
std::chrono::duration<double, std::nano> m_remainingUnlockedTime;
std::mutex m_sleepMutex;
std::atomic<bool> m_sleepFlag; std::atomic<bool> m_sleepFlag;
std::condition_variable m_sleepCondVar; std::condition_variable m_sleepCondVar;
std::mutex m_sleepMutex;
std::mutex m_wakeupMutex;
std::atomic<bool> m_wakeupFlag;
std::condition_variable m_wakeupCondVar;
gl::Shader m_postProcessingShader; gl::Shader m_postProcessingShader;
}; };

View File

@ -618,7 +618,7 @@ namespace hex {
glfwSetFramebufferSizeCallback(m_window, [](GLFWwindow* window, int width, int height) { glfwSetFramebufferSizeCallback(m_window, [](GLFWwindow* window, int width, int height) {
auto *win = static_cast<Window *>(glfwGetWindowUserPointer(window)); auto *win = static_cast<Window *>(glfwGetWindowUserPointer(window));
win->m_unlockFrameRate = true; win->unlockFrameRate();
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
ImHexApi::System::impl::setMainWindowSize(width, height); ImHexApi::System::impl::setMainWindowSize(width, height);

View File

@ -311,7 +311,7 @@ namespace hex {
// Unlock frame rate if any mouse button is being held down to allow drag scrolling to be smooth // Unlock frame rate if any mouse button is being held down to allow drag scrolling to be smooth
if (ImGui::IsAnyMouseDown()) if (ImGui::IsAnyMouseDown())
m_unlockFrameRate = true; this->unlockFrameRate();
// Unlock frame rate if any modifier key is held down since they don't generate key repeat events // Unlock frame rate if any modifier key is held down since they don't generate key repeat events
if ( if (
@ -320,12 +320,12 @@ namespace hex {
ImGui::IsKeyPressed(ImGuiKey_LeftSuper) || ImGui::IsKeyPressed(ImGuiKey_RightSuper) || ImGui::IsKeyPressed(ImGuiKey_LeftSuper) || ImGui::IsKeyPressed(ImGuiKey_RightSuper) ||
ImGui::IsKeyPressed(ImGuiKey_LeftAlt) || ImGui::IsKeyPressed(ImGuiKey_RightAlt) ImGui::IsKeyPressed(ImGuiKey_LeftAlt) || ImGui::IsKeyPressed(ImGuiKey_RightAlt)
) { ) {
m_unlockFrameRate = true; this->unlockFrameRate();
} }
// Unlock frame rate if there's more than one viewport since these don't call the glfw callbacks registered here // Unlock frame rate if there's more than one viewport since these don't call the glfw callbacks registered here
if (ImGui::GetPlatformIO().Viewports.size() > 1) if (ImGui::GetPlatformIO().Viewports.size() > 1)
m_unlockFrameRate = true; this->unlockFrameRate();
} }
// Hide the window as soon as the render loop exits to make the window // Hide the window as soon as the render loop exits to make the window
@ -929,6 +929,23 @@ namespace hex {
#endif #endif
} }
void Window::unlockFrameRate() {
{
std::scoped_lock lock(m_wakeupMutex);
m_remainingUnlockedTime = std::chrono::seconds(2);
}
this->forceNewFrame();
}
void Window::forceNewFrame() {
std::scoped_lock lock(m_wakeupMutex);
m_wakeupFlag = true;
m_wakeupCondVar.notify_all();
}
void Window::initGLFW() { void Window::initGLFW() {
auto initialWindowProperties = ImHexApi::System::getInitialWindowProperties(); auto initialWindowProperties = ImHexApi::System::getInitialWindowProperties();
glfwSetErrorCallback([](int error, const char *desc) { glfwSetErrorCallback([](int error, const char *desc) {
@ -1029,7 +1046,7 @@ namespace hex {
if (win == nullptr) if (win == nullptr)
return; return;
win->m_unlockFrameRate = true; win->unlockFrameRate();
}; };
static const auto isMainWindow = [](GLFWwindow *window) { static const auto isMainWindow = [](GLFWwindow *window) {
@ -1165,7 +1182,7 @@ namespace hex {
Duration passedTime = {}; Duration passedTime = {};
std::chrono::steady_clock::time_point startTime = {}, endTime = {}; std::chrono::steady_clock::time_point startTime = {}, endTime = {};
Duration requestedFrameTime = {}, remainingUnlockedTime = {}; Duration requestedFrameTime = {};
float targetFps = 0; float targetFps = 0;
const auto nativeFps = []() -> float { const auto nativeFps = []() -> float {
@ -1184,32 +1201,36 @@ namespace hex {
targetFps = ImHexApi::System::getTargetFPS(); targetFps = ImHexApi::System::getTargetFPS();
if (m_unlockFrameRate.exchange(false)) {
remainingUnlockedTime = std::chrono::seconds(2);
}
// If the target frame rate is below 15, use the current monitor's refresh rate // If the target frame rate is below 15, use the current monitor's refresh rate
if (targetFps < 15) { if (targetFps < 15) {
targetFps = nativeFps; targetFps = nativeFps;
} }
passedTime += iterationTime; passedTime += iterationTime;
if (remainingUnlockedTime > std::chrono::nanoseconds(0)) { {
remainingUnlockedTime -= iterationTime;
} else {
targetFps = 5;
}
requestedFrameTime = (Duration(1.0E9) / targetFps) / 1.3;
if (passedTime >= requestedFrameTime) {
std::scoped_lock lock(m_sleepMutex); std::scoped_lock lock(m_sleepMutex);
m_sleepFlag = true;
m_sleepCondVar.notify_all();
passedTime = {}; if (m_remainingUnlockedTime > std::chrono::nanoseconds(0)) {
m_remainingUnlockedTime -= iterationTime;
} else {
targetFps = 0.01;
}
requestedFrameTime = (Duration(1.0E9) / targetFps) / 1.3;
if (passedTime >= requestedFrameTime) {
m_sleepFlag = true;
m_sleepCondVar.notify_all();
passedTime = {};
}
} }
std::this_thread::sleep_for(std::chrono::milliseconds(1)); {
std::unique_lock lock(m_wakeupMutex);
m_wakeupCondVar.wait_for(lock, requestedFrameTime, [&] {
return m_wakeupFlag || stopToken.stop_requested();
});
}
endTime = std::chrono::steady_clock::now(); endTime = std::chrono::steady_clock::now();
} }