From 22026cbc60229fb90d3763c4d89e01acce39956a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Kr=C3=A4mer?= <24323470+larskraemer@users.noreply.github.com> Date: Wed, 24 Jun 2020 14:41:34 +0200 Subject: [PATCH 1/2] Create MesaClock class, use chrono classes for time points/durations --- src/keybinds.h | 3 +-- src/logging.cpp | 12 ++++++------ src/logging.h | 8 ++++---- src/overlay.cpp | 40 ++++++++++++++++++++++------------------ src/timing.hpp | 20 ++++++++++++++++++++ 5 files changed, 53 insertions(+), 30 deletions(-) create mode 100644 src/timing.hpp diff --git a/src/keybinds.h b/src/keybinds.h index a9f745c0..8208cddf 100644 --- a/src/keybinds.h +++ b/src/keybinds.h @@ -6,8 +6,7 @@ typedef unsigned long KeySym; #endif -double elapsedF2, elapsedF12, elapsedReloadCfg, elapsedUpload; -uint64_t last_f2_press, last_f12_press, reload_cfg_press, last_upload_press; +Clock::time_point last_f2_press, last_f12_press, reload_cfg_press, last_upload_press; #ifdef HAVE_X11 bool keys_are_pressed(const std::vector& keys) { diff --git a/src/logging.cpp b/src/logging.cpp index 95a78449..56e6bf42 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -6,13 +6,13 @@ string os, cpu, gpu, ram, kernel, driver; bool sysInfoFetched = false; int gpuLoadLog = 0, cpuLoadLog = 0; -uint64_t elapsedLog; +Clock::duration elapsedLog; std::vector logFiles; double fps; std::vector logArray; ofstream out; bool loggingOn; -uint64_t log_start, log_end; +Clock::time_point log_start, log_end; logData currentLogData = {}; bool logUpdate = false; @@ -74,7 +74,7 @@ void writeFile(string filename){ out << logArray[i].gpu_mem_clock << ","; out << logArray[i].gpu_vram_used << ","; out << logArray[i].ram_used << ","; - out << logArray[i].previous << "\n"; + out << std::chrono::duration_cast(logArray[i].previous).count() << "\n"; } out.close(); @@ -93,7 +93,7 @@ string get_log_suffix(){ void logging(void *params_void){ overlay_params *params = reinterpret_cast(params_void); while (loggingOn){ - uint64_t now = os_time_get(); + auto now = Clock::now(); elapsedLog = now - log_start; currentLogData.fps = fps; @@ -101,11 +101,11 @@ void logging(void *params_void){ if (logUpdate) logArray.push_back(currentLogData); - if (params->log_duration && (elapsedLog) >= params->log_duration * 1000000) + if (params->log_duration && (elapsedLog >= std::chrono::seconds(params->log_duration))) loggingOn = false; else if (logUpdate) - this_thread::sleep_for(chrono::milliseconds(params->log_interval)); + this_thread::sleep_for(std::chrono::milliseconds(params->log_interval)); else this_thread::sleep_for(chrono::milliseconds(0)); } diff --git a/src/logging.h b/src/logging.h index 9e45fcd5..8df1def4 100644 --- a/src/logging.h +++ b/src/logging.h @@ -4,7 +4,7 @@ #include #include -#include "mesa/util/os_time.h" +#include "timing.hpp" using namespace std; struct logData{ @@ -18,17 +18,17 @@ struct logData{ float gpu_vram_used; float ram_used; - uint64_t previous; + Clock::duration previous; }; extern string os, cpu, gpu, ram, kernel, driver; extern bool sysInfoFetched; -extern uint64_t elapsedLog; +extern Clock::duration elapsedLog; extern std::vector logFiles; extern double fps; extern std::vector logArray; extern bool loggingOn; -extern uint64_t log_start, log_end; +extern Clock::time_point log_start, log_end; extern logData currentLogData; extern bool logUpdate; diff --git a/src/overlay.cpp b/src/overlay.cpp index 183630ff..08883cb6 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -59,6 +59,7 @@ #include "blacklist.h" #include "version.h" #include "pci_ids.h" +#include "timing.hpp" #ifdef HAVE_DBUS #include "dbus_info.h" @@ -733,20 +734,23 @@ void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& par } void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& params, uint32_t vendorID){ + using namespace std::chrono_literals; bool pressed = false; // FIXME just a placeholder until wayland support - uint64_t now = os_time_get(); /* us */ - elapsedF2 = (double)(now - last_f2_press); - elapsedF12 = (double)(now - last_f12_press); - elapsedReloadCfg = (double)(now - reload_cfg_press); - elapsedUpload = (double)(now - last_upload_press); + auto now = Clock::now(); /* us */ + auto elapsedF2 = now - last_f2_press; + auto elapsedF12 = now - last_f12_press; + auto elapsedReloadCfg = now - reload_cfg_press; + auto elapsedUpload = now - last_upload_press; + + auto keyPressDelay = 500ms; - if (elapsedF2 >= 500000){ + if (elapsedF2 >= keyPressDelay){ #ifdef HAVE_X11 pressed = keys_are_pressed(params.toggle_logging); #else pressed = false; #endif - if (pressed && (now - log_end) / 1000000 > 11){ + if (pressed && (now - log_end > 11s)){ last_f2_press = now; if(loggingOn){ log_end = now; @@ -767,7 +771,7 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par } } - if (elapsedF12 >= 500000){ + if (elapsedF12 >= keyPressDelay){ #ifdef HAVE_X11 pressed = keys_are_pressed(params.toggle_hud); #else @@ -779,7 +783,7 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par } } - if (elapsedReloadCfg >= 500000){ + if (elapsedReloadCfg >= keyPressDelay){ #ifdef HAVE_X11 pressed = keys_are_pressed(params.reload_cfg); #else @@ -791,7 +795,7 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par } } - if (params.permit_upload && elapsedUpload >= 500000){ + if (params.permit_upload && elapsedUpload >= keyPressDelay){ #ifdef HAVE_X11 pressed = keys_are_pressed(params.upload_log); #else @@ -1038,7 +1042,7 @@ static void render_mpris_metadata(struct overlay_params& params, metadata& meta, } #endif -void render_benchmark(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, unsigned height, uint64_t now){ +void render_benchmark(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, unsigned height, Clock::time_point now){ // TODO, FIX LOG_DURATION FOR BENCHMARK int benchHeight = 6 * params.font_size + 10.0f + 58; ImGui::SetNextWindowSize(ImVec2(window_size.x, benchHeight), ImGuiCond_Always); @@ -1048,7 +1052,7 @@ void render_benchmark(swapchain_stats& data, struct overlay_params& params, ImVe ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y + window_size.y + 5), ImGuiCond_Always); vector> benchmark_data = {{"97% ", benchmark.ninety}, {"AVG ", benchmark.avg}, {"1% ", benchmark.oneP}, {"0.1%", benchmark.pointOneP}}; - float display_time = float(now - log_end) / 1000000; + float display_time = std::chrono::duration(now - log_end).count(); static float display_for = 10.0f; float alpha; if(params.background_alpha != 0){ @@ -1082,7 +1086,7 @@ void render_benchmark(swapchain_stats& data, struct overlay_params& params, ImVe ImGui::TextColored(ImVec4(1.0, 1.0, 1.0, alpha / params.background_alpha), "%s", finished); ImGui::Dummy(ImVec2(0.0f, 8.0f)); char duration[20]; - snprintf(duration, sizeof(duration), "Duration: %.1fs", float(log_end - log_start) / 1000000); + snprintf(duration, sizeof(duration), "Duration: %.1fs", std::chrono::duration(log_end - log_start).count()); ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(duration).x / 2)); ImGui::TextColored(ImVec4(1.0, 1.0, 1.0, alpha / params.background_alpha), "%s", duration); for (auto& data_ : benchmark_data){ @@ -1112,7 +1116,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& static float char_width = ImGui::CalcTextSize("A").x; window_size = ImVec2(params.width, params.height); unsigned height = ImGui::GetIO().DisplaySize.y; - uint64_t now = os_time_get(); + auto now = Clock::now(); if (!params.no_display){ ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); @@ -1335,8 +1339,8 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& } if (loggingOn && params.log_interval == 0){ - elapsedLog = (double)(now - log_start); - if (params.log_duration && (elapsedLog) >= params.log_duration * 1000000) + elapsedLog = now - log_start; + if (params.log_duration && (elapsedLog) >= std::chrono::seconds(params.log_duration)) loggingOn = false; currentLogData.fps = fps; @@ -1391,12 +1395,12 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(data.main_window_pos.x + window_size.x - 15, data.main_window_pos.y + 15), 10, params.engine_color, 20); window_size = ImVec2(window_size.x, ImGui::GetCursorPosY() + 10.0f); ImGui::End(); - if (loggingOn && params.log_duration && (now - log_start) >= params.log_duration * 1000000){ + if (loggingOn && params.log_duration && (now - log_start) >= std::chrono::seconds(params.log_duration)){ loggingOn = false; log_end = now; std::thread(calculate_benchmark_data).detach(); } - if((now - log_end) / 1000000 < 12) + if((now - log_end) < 12s) render_benchmark(data, params, window_size, height, now); } diff --git a/src/timing.hpp b/src/timing.hpp new file mode 100644 index 00000000..ea1757e0 --- /dev/null +++ b/src/timing.hpp @@ -0,0 +1,20 @@ +#ifndef MANGOHUD_TIMING_HPP +#define MANGOHUD_TIMING_HPP +#include + +#include "mesa/util/os_time.h" + +class MesaClock { +public: + using rep = int64_t; + using period = std::nano; + using duration = std::chrono::duration; + using time_point = std::chrono::time_point; + const static bool is_steady = true; + static time_point now() noexcept { + return time_point(duration(os_time_get_nano())); + } +}; + +using Clock = MesaClock; +#endif //MANGOHUD_TIMING_HPP \ No newline at end of file From 20221217d43ad3958ccff1c4e5b3db4b85b5b983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Kr=C3=A4mer?= <24323470+larskraemer@users.noreply.github.com> Date: Wed, 24 Jun 2020 20:14:24 +0200 Subject: [PATCH 2/2] Frame-timing using chrono --- src/gl/inject_glx.cpp | 14 ++++++++------ src/overlay.cpp | 16 +++++++++------- src/overlay.h | 11 ++++++----- src/overlay_params.cpp | 3 ++- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/gl/inject_glx.cpp b/src/gl/inject_glx.cpp index 13da5dbc..624bc379 100644 --- a/src/gl/inject_glx.cpp +++ b/src/gl/inject_glx.cpp @@ -127,10 +127,11 @@ EXPORT_C_(void) glXSwapBuffers(void* dpy, void* drawable) { do_imgui_swap(dpy, drawable); glx.SwapBuffers(dpy, drawable); - if (!is_blacklisted() && fps_limit_stats.targetFrameTime > 0){ - fps_limit_stats.frameStart = os_time_get_nano(); + using namespace std::chrono_literals; + if (!is_blacklisted() && fps_limit_stats.targetFrameTime > 0s){ + fps_limit_stats.frameStart = Clock::now(); FpsLimiter(fps_limit_stats); - fps_limit_stats.frameEnd = os_time_get_nano(); + fps_limit_stats.frameEnd = Clock::now(); } } @@ -141,10 +142,11 @@ EXPORT_C_(int64_t) glXSwapBuffersMscOML(void* dpy, void* drawable, int64_t targe do_imgui_swap(dpy, drawable); int64_t ret = glx.SwapBuffersMscOML(dpy, drawable, target_msc, divisor, remainder); - if (!is_blacklisted() && fps_limit_stats.targetFrameTime > 0){ - fps_limit_stats.frameStart = os_time_get_nano(); + using namespace std::chrono_literals; + if (!is_blacklisted() && fps_limit_stats.targetFrameTime > 0s){ + fps_limit_stats.frameStart = Clock::now(); FpsLimiter(fps_limit_stats); - fps_limit_stats.frameEnd = os_time_get_nano(); + fps_limit_stats.frameEnd = Clock::now(); } return ret; } diff --git a/src/overlay.cpp b/src/overlay.cpp index 08883cb6..ed189b10 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -2381,11 +2381,11 @@ static void overlay_DestroySwapchainKHR( void FpsLimiter(struct fps_limit& stats){ stats.sleepTime = stats.targetFrameTime - (stats.frameStart - stats.frameEnd); if (stats.sleepTime > stats.frameOverhead) { - int64_t adjustedSleep = stats.sleepTime - stats.frameOverhead; - this_thread::sleep_for(chrono::nanoseconds(adjustedSleep)); - stats.frameOverhead = ((os_time_get_nano() - stats.frameStart) - adjustedSleep); + auto adjustedSleep = stats.sleepTime - stats.frameOverhead; + this_thread::sleep_for(adjustedSleep); + stats.frameOverhead = ((Clock::now() - stats.frameStart) - adjustedSleep); if (stats.frameOverhead > stats.targetFrameTime) - stats.frameOverhead = 0; + stats.frameOverhead = Clock::duration(0); } } @@ -2435,10 +2435,12 @@ static VkResult overlay_QueuePresentKHR( result = chain_result; } - if (fps_limit_stats.targetFrameTime > 0){ - fps_limit_stats.frameStart = os_time_get_nano(); + using namespace std::chrono_literals; + + if (fps_limit_stats.targetFrameTime > 0s){ + fps_limit_stats.frameStart = Clock::now(); FpsLimiter(fps_limit_stats); - fps_limit_stats.frameEnd = os_time_get_nano(); + fps_limit_stats.frameEnd = Clock::now(); } return result; diff --git a/src/overlay.h b/src/overlay.h index 45521948..cb66dcc8 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -4,6 +4,7 @@ #include "imgui.h" #include "overlay_params.h" #include "iostats.h" +#include "timing.hpp" struct frame_stat { uint64_t stats[OVERLAY_PLOTS_MAX]; @@ -44,11 +45,11 @@ struct swapchain_stats { }; struct fps_limit { - int64_t frameStart; - int64_t frameEnd; - int64_t targetFrameTime; - int64_t frameOverhead; - int64_t sleepTime; + Clock::time_point frameStart; + Clock::time_point frameEnd; + Clock::duration targetFrameTime; + Clock::duration frameOverhead; + Clock::duration sleepTime; }; struct benchmark_stats { diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index ae30711c..39556f16 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -485,8 +485,9 @@ parse_overlay_config(struct overlay_params *params, } // set frametime limit + using namespace std::chrono; if (params->fps_limit >= 0) - fps_limit_stats.targetFrameTime = int64_t(1000000000.0 / params->fps_limit); + fps_limit_stats.targetFrameTime = duration_cast(duration(1) / params->fps_limit); #ifdef HAVE_DBUS if (params->enabled[OVERLAY_PARAM_ENABLED_media_player]) {