impr: Don't wake up frame rate limiter thread more often than necessary
This commit is contained in:
parent
4c0e8bc1d6
commit
7879f8b6a4
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user