From 3f531bbf98da5ad751dce1220c5c5fdf35f86c92 Mon Sep 17 00:00:00 2001 From: ShadelessFox Date: Mon, 4 Nov 2024 17:10:18 +0100 Subject: [PATCH] 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(); }