From 3f531bbf98da5ad751dce1220c5c5fdf35f86c92 Mon Sep 17 00:00:00 2001 From: ShadelessFox Date: Mon, 4 Nov 2024 17:10:18 +0100 Subject: [PATCH 1/2] Use high-resolution timer for a better frame time --- CMakeLists.txt | 4 ++++ src/util/platform.cpp | 36 +++++++++++++++++++++++++++++++----- src/util/platform.hpp | 2 ++ src/window/Window.cpp | 15 ++++++++++----- 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a5e839c..f465fcb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,10 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie -lstdc++fs") endif() +if (WIN32) + target_link_libraries(${PROJECT_NAME} VoxelEngineSrc winmm) +endif() + target_link_libraries(${PROJECT_NAME} VoxelEngineSrc ${CMAKE_DL_LIBS}) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/res DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/src/util/platform.cpp b/src/util/platform.cpp index 6bc3b343..cf16691a 100644 --- a/src/util/platform.cpp +++ b/src/util/platform.cpp @@ -5,9 +5,10 @@ #include #include #include +#include -#include "typedefs.hpp" #include "stringutil.hpp" +#include "typedefs.hpp" #ifdef _WIN32 #include @@ -34,6 +35,27 @@ std::string platform::detect_locale() { .replace(2, 1, "_") .substr(0, 5); } + +void platform::sleep(size_t millis) { + // Uses implementation from the SFML library + // https://github.com/SFML/SFML/blob/master/src/SFML/System/Win32/SleepImpl.cpp + + // Get the minimum supported timer resolution on this system + static const UINT periodMin = []{ + TIMECAPS tc; + timeGetDevCaps(&tc, sizeof(TIMECAPS)); + return tc.wPeriodMin; + }(); + + // Set the timer resolution to the minimum for the Sleep call + timeBeginPeriod(periodMin); + + // Wait... + Sleep(static_cast(millis)); + + // Reset the timer resolution back to the system default + timeEndPeriod(periodMin); +} #else void platform::configure_encoding() { @@ -47,6 +69,10 @@ std::string platform::detect_locale() { return preferredLocaleName.substr(0, 5); } + +void platform::sleep(size_t millis) { + std::this_thread::sleep_for(std::chrono::milliseconds(millis)); +} #endif void platform::open_folder(const std::filesystem::path& folder) { @@ -54,11 +80,11 @@ void platform::open_folder(const std::filesystem::path& folder) { return; } #ifdef __APPLE__ - auto cmd = "open "+util::quote(folder.u8string()); + auto cmd = "open " + util::quote(folder.u8string()); #elif defined(_WIN32) - auto cmd = "start explorer "+util::quote(folder.u8string()); + auto cmd = "start explorer " + util::quote(folder.u8string()); #else - auto cmd = "xdg-open "+util::quote(folder.u8string()); + auto cmd = "xdg-open " + util::quote(folder.u8string()); #endif system(cmd.c_str()); -} +} \ No newline at end of file diff --git a/src/util/platform.hpp b/src/util/platform.hpp index b6e8bde9..1283bcfe 100644 --- a/src/util/platform.hpp +++ b/src/util/platform.hpp @@ -10,4 +10,6 @@ namespace platform { /// @brief Open folder using system file manager asynchronously /// @param folder target folder void open_folder(const std::filesystem::path& folder); + /// Makes the current thread sleep for the specified amount of milliseconds. + void sleep(size_t millis); } diff --git a/src/window/Window.cpp b/src/window/Window.cpp index c77f0d4c..2de948a3 100644 --- a/src/window/Window.cpp +++ b/src/window/Window.cpp @@ -14,6 +14,8 @@ #include "util/ObjectsKeeper.hpp" #include "Events.hpp" +#include "util/platform.hpp" + static debug::Logger logger("window"); GLFWwindow* Window::window = nullptr; @@ -357,11 +359,14 @@ bool Window::isFullscreen() { void Window::swapBuffers() { glfwSwapBuffers(window); Window::resetScissor(); - double currentTime = time(); - if (framerate > 0 && currentTime - prevSwap < (1.0 / framerate)) { - std::this_thread::sleep_for(std::chrono::milliseconds(static_cast( - (1.0 / framerate - (currentTime - prevSwap)) * 1000 - ))); + if (framerate > 0) { + auto elapsedTime = time() - prevSwap; + auto frameTime = 1.0 / framerate; + if (elapsedTime < frameTime) { + platform::sleep( + static_cast((frameTime - elapsedTime) * 1000) + ); + } } prevSwap = time(); } From aaa2115cd6e7093543251ba5c7aad124a27d618e Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 4 Nov 2024 20:16:23 +0300 Subject: [PATCH 2/2] add 'display.limit-fps-iconified' setting --- res/layouts/pages/settings_display.xml.lua | 1 + res/texts/ru_RU.txt | 1 + src/engine.cpp | 7 +++++-- src/files/settings_io.cpp | 1 + src/settings.hpp | 2 ++ 5 files changed, 10 insertions(+), 2 deletions(-) diff --git a/res/layouts/pages/settings_display.xml.lua b/res/layouts/pages/settings_display.xml.lua index a0bc9579..f8b24d0b 100644 --- a/res/layouts/pages/settings_display.xml.lua +++ b/res/layouts/pages/settings_display.xml.lua @@ -60,4 +60,5 @@ function on_open() create_checkbox("camera.shaking", "Camera Shaking") create_checkbox("camera.inertia", "Camera Inertia") create_checkbox("camera.fov-effects", "Camera FOV Effects") + create_checkbox("display.limit-fps-iconified", "Limit Background FPS") end diff --git a/res/texts/ru_RU.txt b/res/texts/ru_RU.txt index 53368e92..490ef4d7 100644 --- a/res/texts/ru_RU.txt +++ b/res/texts/ru_RU.txt @@ -76,6 +76,7 @@ settings.Regular Sounds=Обычные Звуки settings.UI Sounds=Звуки Интерфейса settings.V-Sync=Вертикальная Синхронизация settings.Key=Кнопка +settings.Limit Background FPS=Ограничить фоновую частоту кадров # Управление chunks.reload=Перезагрузить Чанки diff --git a/src/engine.cpp b/src/engine.cpp index acff9542..0cfc6733 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -185,8 +185,11 @@ void Engine::mainloop() { if (!Window::isIconified()) { renderFrame(batch); } - Window::setFramerate(Window::isIconified() ? 20 : - settings.display.framerate.get()); + Window::setFramerate( + Window::isIconified() && settings.display.limitFpsIconified.get() + ? 20 + : settings.display.framerate.get() + ); processPostRunnables(); diff --git a/src/files/settings_io.cpp b/src/files/settings_io.cpp index eb81f3db..d2a85f6a 100644 --- a/src/files/settings_io.cpp +++ b/src/files/settings_io.cpp @@ -51,6 +51,7 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) { builder.add("samples", &settings.display.samples); builder.add("framerate", &settings.display.framerate); builder.add("fullscreen", &settings.display.fullscreen); + builder.add("limit-fps-iconified", &settings.display.limitFpsIconified); builder.section("camera"); builder.add("sensitivity", &settings.camera.sensitivity); diff --git a/src/settings.hpp b/src/settings.hpp index 8d1abdbf..8343ee68 100644 --- a/src/settings.hpp +++ b/src/settings.hpp @@ -29,6 +29,8 @@ struct DisplaySettings { IntegerSetting samples {0}; /// @brief Framerate limit IntegerSetting framerate {-1, -1, 120}; + /// @brief Limit framerate when window is iconified + FlagSetting limitFpsIconified {false}; }; struct ChunksSettings {