From ba6346110c5fd1396d5b3fa244fbc8b43be00d4e Mon Sep 17 00:00:00 2001 From: jackun Date: Mon, 17 Aug 2020 20:38:09 +0300 Subject: [PATCH 001/130] [OpenGL] Enable color mask Maybe previous state needs to be restored afterwards? --- src/gl/imgui_impl_opengl3.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gl/imgui_impl_opengl3.cpp b/src/gl/imgui_impl_opengl3.cpp index 2103773b..c5f822bc 100644 --- a/src/gl/imgui_impl_opengl3.cpp +++ b/src/gl/imgui_impl_opengl3.cpp @@ -499,6 +499,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); glDisable(GL_FRAMEBUFFER_SRGB); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); //#ifdef GL_POLYGON_MODE if (!g_IsGLES && g_GlVersion >= 200) From 0230efee8bb313026e086aa4bc650e31adcff54e Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Mon, 17 Aug 2020 20:57:15 +0200 Subject: [PATCH 002/130] Small adjustments to render_mango --- src/overlay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlay.cpp b/src/overlay.cpp index b36ad683..4111fd49 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -1237,7 +1237,7 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& } ImGui::EndTable(); if (params.enabled[OVERLAY_PARAM_ENABLED_frame_timing]){ - ImGui::Dummy(ImVec2(0.0f, params.font_size * params.font_scale / 2)); + ImGui::Dummy(ImVec2(0.0f, 8.0f)); ImGui::PushFont(data.font1); ImGui::TextColored(data.colors.engine, "%s", "Frametime"); ImGui::PopFont(); @@ -1258,7 +1258,7 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::PopStyleColor(); } ImGui::End(); - window_size = ImVec2(window_size.x, ImGui::GetCursorPosY() + 150.0f); + window_size = ImVec2(window_size.x, 200); } void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan) From 60940e5a02c5251fe1aa1d9ad7f2bf74d7076a73 Mon Sep 17 00:00:00 2001 From: jackun Date: Tue, 18 Aug 2020 19:13:27 +0300 Subject: [PATCH 003/130] [OpenGL] Just "refcount" by glXCreate/DestroyContext calls; recreate "lost" objects --- src/gl/gl.h | 1 + src/gl/imgui_hud.cpp | 4 +-- src/gl/imgui_impl_opengl3.cpp | 7 ++++ src/gl/inject_glx.cpp | 61 ++++++++++++++++++++++++++--------- src/loaders/loader_glx.cpp | 16 +++++++++ src/loaders/loader_glx.h | 2 ++ 6 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/gl/gl.h b/src/gl/gl.h index 34b8e137..79b5a3db 100644 --- a/src/gl/gl.h +++ b/src/gl/gl.h @@ -15,6 +15,7 @@ int glXSwapIntervalMESA(unsigned int); int glXGetSwapIntervalMESA(void); int glXMakeCurrent(void*, void*, void*); void* glXGetCurrentContext(); +void *glXCreateContextAttribsARB(void *dpy, void *config,void *share_context, int direct, const int *attrib_list); void* glXGetProcAddress(const unsigned char*); void* glXGetProcAddressARB(const unsigned char*); diff --git a/src/gl/imgui_hud.cpp b/src/gl/imgui_hud.cpp index 257ad62f..4ada82de 100644 --- a/src/gl/imgui_hud.cpp +++ b/src/gl/imgui_hud.cpp @@ -85,11 +85,11 @@ void imgui_create(void *ctx) if (!ctx) return; - + imgui_shutdown(); imgui_init(); inited = true; - + gladLoadGL(); GetOpenGLVersion(sw_stats.version_gl.major, diff --git a/src/gl/imgui_impl_opengl3.cpp b/src/gl/imgui_impl_opengl3.cpp index c5f822bc..c87e7da2 100644 --- a/src/gl/imgui_impl_opengl3.cpp +++ b/src/gl/imgui_impl_opengl3.cpp @@ -480,6 +480,13 @@ void ImGui_ImplOpenGL3_NewFrame() { if (!g_ShaderHandle) ImGui_ImplOpenGL3_CreateDeviceObjects(); + else if (!glIsProgram(g_ShaderHandle)) { // TODO Got created in a now dead context? +#ifndef NDEBUG + fprintf(stderr, "MANGOHUD: recreating lost objects\n"); +#endif + ImGui_ImplOpenGL3_CreateDeviceObjects(); + } + if (!glIsTexture(g_FontTexture)) { #ifndef NDEBUG fprintf(stderr, "MANGOHUD: GL Texture lost? Regenerating.\n"); diff --git a/src/gl/inject_glx.cpp b/src/gl/inject_glx.cpp index 624bc379..763a4b33 100644 --- a/src/gl/inject_glx.cpp +++ b/src/gl/inject_glx.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "real_dlsym.h" #include "loaders/loader_glx.h" @@ -31,7 +32,7 @@ EXPORT_C_(void *) glXGetProcAddressARB(const unsigned char* procName); static glx_loader glx; -static std::vector gl_threads; +static std::atomic refcnt (0); void* get_glx_proc_address(const char* name) { glx.Load(); @@ -57,12 +58,50 @@ EXPORT_C_(void *) glXCreateContext(void *dpy, void *vis, void *shareList, int di { glx.Load(); void *ctx = glx.CreateContext(dpy, vis, shareList, direct); + if (ctx) + refcnt++; #ifndef NDEBUG std::cerr << __func__ << ":" << ctx << std::endl; #endif return ctx; } +EXPORT_C_(void *) glXCreateContextAttribs(void *dpy, void *config,void *share_context, int direct, const int *attrib_list) +{ + glx.Load(); + void *ctx = glx.CreateContextAttribs(dpy, config, share_context, direct, attrib_list); + if (ctx) + refcnt++; +#ifndef NDEBUG + std::cerr << __func__ << ":" << ctx << std::endl; +#endif + return ctx; +} + +EXPORT_C_(void *) glXCreateContextAttribsARB(void *dpy, void *config,void *share_context, int direct, const int *attrib_list) +{ + glx.Load(); + void *ctx = glx.CreateContextAttribsARB(dpy, config, share_context, direct, attrib_list); + if (ctx) + refcnt++; +#ifndef NDEBUG + std::cerr << __func__ << ":" << ctx << std::endl; +#endif + return ctx; +} + +EXPORT_C_(void) glXDestroyContext(void *dpy, void *ctx) +{ + glx.Load(); + glx.DestroyContext(dpy, ctx); + refcnt--; + if (refcnt <= 0) + imgui_shutdown(); +#ifndef NDEBUG + std::cerr << __func__ << ":" << ctx << std::endl; +#endif +} + EXPORT_C_(int) glXMakeCurrent(void* dpy, void* drawable, void* ctx) { glx.Load(); #ifndef NDEBUG @@ -73,21 +112,10 @@ EXPORT_C_(int) glXMakeCurrent(void* dpy, void* drawable, void* ctx) { if (!is_blacklisted()) { if (ret) { - //TODO might as well just ignore everything here as long as VBOs get recreated anyway - auto it = std::find(gl_threads.begin(), gl_threads.end(), std::this_thread::get_id()); - if (!ctx) { - if (it != gl_threads.end()) - gl_threads.erase(it); - if (!gl_threads.size()) - imgui_set_context(nullptr); - } else { - if (it == gl_threads.end()) - gl_threads.push_back(std::this_thread::get_id()); - imgui_set_context(ctx); + imgui_set_context(ctx); #ifndef NDEBUG - std::cerr << "MANGOHUD: GL thread count: " << gl_threads.size() << "\n"; + std::cerr << "MANGOHUD: GL ref count: " << refcnt << "\n"; #endif - } } if (params.gl_vsync >= -1) { @@ -214,11 +242,14 @@ struct func_ptr { void *ptr; }; -static std::array name_to_funcptr_map = {{ +static std::array name_to_funcptr_map = {{ #define ADD_HOOK(fn) { #fn, (void *) fn } ADD_HOOK(glXGetProcAddress), ADD_HOOK(glXGetProcAddressARB), + ADD_HOOK(glXCreateContextAttribs), + ADD_HOOK(glXCreateContextAttribsARB), ADD_HOOK(glXCreateContext), + ADD_HOOK(glXDestroyContext), ADD_HOOK(glXMakeCurrent), ADD_HOOK(glXSwapBuffers), ADD_HOOK(glXSwapBuffersMscOML), diff --git a/src/loaders/loader_glx.cpp b/src/loaders/loader_glx.cpp index ca22ccd4..d245a76a 100644 --- a/src/loaders/loader_glx.cpp +++ b/src/loaders/loader_glx.cpp @@ -42,6 +42,22 @@ bool glx_loader::Load() { return false; } + CreateContextAttribs = + reinterpret_castCreateContextAttribs)>( + GetProcAddress((const unsigned char *)"glXCreateContextAttribs")); +// if (!CreateContextAttribs) { +// CleanUp(true); +// return false; +// } + + CreateContextAttribsARB = + reinterpret_castCreateContextAttribsARB)>( + GetProcAddress((const unsigned char *)"glXCreateContextAttribsARB")); +// if (!CreateContextAttribsARB) { +// CleanUp(true); +// return false; +// } + DestroyContext = reinterpret_castDestroyContext)>( GetProcAddress((const unsigned char *)"glXDestroyContext")); diff --git a/src/loaders/loader_glx.h b/src/loaders/loader_glx.h index 760894c4..e3ecc9fb 100644 --- a/src/loaders/loader_glx.h +++ b/src/loaders/loader_glx.h @@ -13,6 +13,8 @@ class glx_loader { decltype(&::glXGetProcAddress) GetProcAddress; decltype(&::glXGetProcAddressARB) GetProcAddressARB; decltype(&::glXCreateContext) CreateContext; + decltype(&::glXCreateContextAttribsARB) CreateContextAttribs; + decltype(&::glXCreateContextAttribsARB) CreateContextAttribsARB; decltype(&::glXDestroyContext) DestroyContext; decltype(&::glXSwapBuffers) SwapBuffers; decltype(&::glXSwapIntervalEXT) SwapIntervalEXT; From c1a255260f5039a211585adba5927a64c1dfec17 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Thu, 20 Aug 2020 01:14:20 +0200 Subject: [PATCH 004/130] Add recording circle to render_mango --- src/overlay.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/overlay.cpp b/src/overlay.cpp index 4111fd49..0e0a96b5 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -1257,6 +1257,8 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::PopStyleColor(); } + if(logger->is_active()) + ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(data.main_window_pos.x + window_size.x - 15, data.main_window_pos.y + 15), 10, params.engine_color, 20); ImGui::End(); window_size = ImVec2(window_size.x, 200); } From 3dc3c82522da91eb2c0dd237584a10f40c3339b0 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Fri, 21 Aug 2020 20:16:00 +0200 Subject: [PATCH 005/130] Add frametime to log --- src/logging.cpp | 4 +++- src/logging.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/logging.cpp b/src/logging.cpp index c01f2e40..2c5e28b7 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -60,10 +60,11 @@ void writeFile(string filename){ std::ofstream out(filename, ios::out | ios::app); out << "os," << "cpu," << "gpu," << "ram," << "kernel," << "driver" << endl; out << os << "," << cpu << "," << gpu << "," << ram << "," << kernel << "," << driver << endl; - out << "fps," << "cpu_load," << "gpu_load," << "cpu_temp," << "gpu_temp," << "gpu_core_clock," << "gpu_mem_clock," << "gpu_vram_used," << "ram_used," << "elapsed" << endl; + out << "fps," << "frametime," << "cpu_load," << "gpu_load," << "cpu_temp," << "gpu_temp," << "gpu_core_clock," << "gpu_mem_clock," << "gpu_vram_used," << "ram_used," << "elapsed" << endl; for (size_t i = 0; i < logArray.size(); i++){ out << logArray[i].fps << ","; + out << logArray[i].frametime << ","; out << logArray[i].cpu_load << ","; out << logArray[i].gpu_load << ","; out << logArray[i].cpu_temp << ","; @@ -136,6 +137,7 @@ void Logger::try_log() { currentLogData.previous = elapsedLog; currentLogData.fps = fps; + currentLogData.frametime = 1000 / fps; m_log_array.push_back(currentLogData); if(m_params->log_duration and (elapsedLog >= std::chrono::seconds(m_params->log_duration))){ diff --git a/src/logging.h b/src/logging.h index 7bcfc0a5..bd981da4 100644 --- a/src/logging.h +++ b/src/logging.h @@ -16,6 +16,7 @@ using namespace std; struct logData{ double fps; + double frametime; int cpu_load; int gpu_load; int cpu_temp; From c630588d22882c5a1ff26217f1e5370e9439022c Mon Sep 17 00:00:00 2001 From: jackun Date: Sun, 23 Aug 2020 11:57:21 +0300 Subject: [PATCH 006/130] Update version in meson.build --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index c880a5c3..b43ac65a 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project('MangoHud', ['c', 'cpp'], - version : 'v0.4.0', + version : 'v0.5.1', license : 'MIT', default_options : ['buildtype=release', 'c_std=c99', 'cpp_std=c++14'] ) From a7db4276e3b67396fa8a1e1cb62fda6d367dbd6c Mon Sep 17 00:00:00 2001 From: jackun Date: Mon, 24 Aug 2020 17:48:27 +0300 Subject: [PATCH 007/130] Don't force bash usage in launcher script --- bin/mangohud.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/mangohud.in b/bin/mangohud.in index 610725a8..e9fec054 100755 --- a/bin/mangohud.in +++ b/bin/mangohud.in @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh if [ "$#" -eq 0 ]; then programname=`basename "$0"` From cec98369ae34d910476b78f98adece96016ab603 Mon Sep 17 00:00:00 2001 From: jackun Date: Tue, 25 Aug 2020 07:58:56 +0300 Subject: [PATCH 008/130] Include array, explicitly --- src/overlay.cpp | 1 + src/overlay_params.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/overlay.cpp b/src/overlay.cpp index 0e0a96b5..a75f1764 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index caef330e..ae243f1f 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "overlay_params.h" #include "overlay.h" From 9ddd075b1870e2c6257c04a8b9c9b063da1068dd Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Wed, 2 Sep 2020 07:50:26 +0200 Subject: [PATCH 009/130] Get actual frametime for logs --- src/logging.cpp | 2 +- src/overlay.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/logging.cpp b/src/logging.cpp index 2c5e28b7..d00107c9 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -137,7 +137,7 @@ void Logger::try_log() { currentLogData.previous = elapsedLog; currentLogData.fps = fps; - currentLogData.frametime = 1000 / fps; + currentLogData.frametime = frametime; m_log_array.push_back(currentLogData); if(m_params->log_duration and (elapsedLog >= std::chrono::seconds(m_params->log_duration))){ diff --git a/src/overlay.cpp b/src/overlay.cpp index a75f1764..282c8cce 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -928,6 +928,7 @@ void update_hud_info(struct swapchain_stats& sw_stats, struct overlay_params& pa now - sw_stats.last_present_time; } + frametime = now - sw_stats.last_present_time; if (elapsed >= params.fps_sampling_period) { std::thread(update_hw_info, std::ref(sw_stats), std::ref(params), vendorID).detach(); From d0c9176d6d486203de929f4fc20af59637591f30 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Wed, 2 Sep 2020 07:50:56 +0200 Subject: [PATCH 010/130] Log frametime as nanoseconds --- src/logging.cpp | 3 ++- src/logging.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/logging.cpp b/src/logging.cpp index d00107c9..4a2a56ac 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -7,6 +7,7 @@ string os, cpu, gpu, ram, kernel, driver; bool sysInfoFetched = false; double fps; +uint64_t frametime; logData currentLogData = {}; std::unique_ptr logger; @@ -73,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 << std::chrono::duration_cast(logArray[i].previous).count() << "\n"; + out << std::chrono::duration_cast(logArray[i].previous).count() << "\n"; } logger->clear_log_data(); } diff --git a/src/logging.h b/src/logging.h index bd981da4..a7397b94 100644 --- a/src/logging.h +++ b/src/logging.h @@ -16,7 +16,7 @@ using namespace std; struct logData{ double fps; - double frametime; + uint64_t frametime; int cpu_load; int gpu_load; int cpu_temp; @@ -70,6 +70,7 @@ extern std::unique_ptr logger; extern string os, cpu, gpu, ram, kernel, driver; extern bool sysInfoFetched; extern double fps; +extern uint64_t frametime; extern logData currentLogData; string exec(string command); From c4a7d3002b27e1e8acec748f985500eca3477276 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Wed, 2 Sep 2020 07:52:28 +0200 Subject: [PATCH 011/130] Moved try_log() outside of no_display --- src/overlay.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/overlay.cpp b/src/overlay.cpp index 282c8cce..2853d799 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -1554,9 +1554,6 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::PopFont(); #endif - if (params.log_interval == 0){ - logger->try_log(); - } if(logger->is_active()) 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); @@ -1585,6 +1582,11 @@ static void compute_swapchain_display(struct swapchain_data *data) ImGui::EndFrame(); ImGui::Render(); + + if (instance_data->params.log_interval == 0){ + logger->try_log(); + } + } static uint32_t vk_memory_type(struct device_data *data, From c337fddc582737049afb7045357c600f8c178bc3 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Wed, 2 Sep 2020 09:44:39 +0200 Subject: [PATCH 012/130] Move try_log() into render_imgui --- src/overlay.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/overlay.cpp b/src/overlay.cpp index 2853d799..dfb59d0d 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -1194,6 +1194,9 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& static int tableCols = 2; static float ralign_width = 0, old_scale = 0; window_size = ImVec2(300, params.height); + if (params.log_interval == 0){ + logger->try_log(); + } if (old_scale != params.font_scale) { ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; @@ -1275,6 +1278,9 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size = ImVec2(params.width, params.height); unsigned height = ImGui::GetIO().DisplaySize.y; auto now = Clock::now(); + if (params.log_interval == 0){ + logger->try_log(); + } if (old_scale != params.font_scale) { ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; @@ -1582,10 +1588,6 @@ static void compute_swapchain_display(struct swapchain_data *data) ImGui::EndFrame(); ImGui::Render(); - - if (instance_data->params.log_interval == 0){ - logger->try_log(); - } } From 956b07e385da4cfd5c14545b196bf9b7d464fc06 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sat, 5 Sep 2020 07:07:04 +0200 Subject: [PATCH 013/130] Add minhook as module --- .gitmodules | 3 +++ modules/minhook | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 modules/minhook diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..b6ae151c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "modules/minhook"] + path = modules/minhook + url = https://github.com/TsudaKageyu/minhook diff --git a/modules/minhook b/modules/minhook new file mode 160000 index 00000000..df662265 --- /dev/null +++ b/modules/minhook @@ -0,0 +1 @@ +Subproject commit df6622659e366c63dfc9591245fa6a9a10ec4759 From 6da562200226b6b882fcefebbc04125b2beb8e23 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sat, 5 Sep 2020 07:42:15 +0200 Subject: [PATCH 014/130] Add minhook dep in meson --- meson.build | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/meson.build b/meson.build index b43ac65a..7041c65b 100644 --- a/meson.build +++ b/meson.build @@ -207,5 +207,14 @@ endif dearimgui_sp = subproject('dearimgui') dearimgui_dep = dearimgui_sp.get_variable('dearimgui_dep') +if ['windows', 'mingw'].contains(host_machine.system()) + subdir('modules/minhook') + windows_deps = [ + minhook_dep + ] +else + windows_deps = null_dep +endif + subdir('src') subdir('data') From b7aa6a997b48a884711991c2b73bc0cb6b383408 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sat, 5 Sep 2020 07:42:39 +0200 Subject: [PATCH 015/130] Separate unix and windows in meson --- meson.build | 28 +++++-- src/meson.build | 193 +++++++++++++++++++++++++----------------------- 2 files changed, 122 insertions(+), 99 deletions(-) diff --git a/meson.build b/meson.build index 7041c65b..6a0dc0d2 100644 --- a/meson.build +++ b/meson.build @@ -30,9 +30,11 @@ else endif # TODO: this is very incomplete +is_unixy = false if ['linux', 'cygwin', 'gnu'].contains(host_machine.system()) pre_args += '-D_GNU_SOURCE' pre_args += '-DHAVE_PTHREAD' + is_unixy = true endif if get_option('glibcxx_asserts') @@ -77,9 +79,16 @@ endforeach vulkan_wsi_args = [] vulkan_wsi_deps = [] -dep_x11 = dependency('x11', required: get_option('with_x11')) -dep_wayland_client = dependency('wayland-client', - required: get_option('with_wayland'), version : '>=1.11') +if is_unixy + dep_x11 = dependency('x11', required: get_option('with_x11')) + dep_wayland_client = dependency('wayland-client', + required: get_option('with_wayland'), version : '>=1.11') + dbus_dep = dependency('dbus-1', required: get_option('with_dbus')).partial_dependency(compile_args : true, includes : true) +else + dep_x11 = null_dep + dep_wayland_client = null_dep + dbus_dep = null_dep +endif if dep_x11.found() vulkan_wsi_args += ['-DVK_USE_PLATFORM_XLIB_KHR'] @@ -90,7 +99,7 @@ if dep_wayland_client.found() vulkan_wsi_deps += dep_wayland_client endif -if not dep_x11.found() and not dep_wayland_client.found() +if is_unixy and not dep_x11.found() and not dep_wayland_client.found() error('At least one of "with_x11" and "with_wayland" should be enabled') endif @@ -100,7 +109,6 @@ inc_common = [ dep_vulkan = dependency('vulkan', required: get_option('use_system_vulkan')) dep_pthread = dependency('threads') -dbus_dep = dependency('dbus-1', required: get_option('with_dbus')).partial_dependency(compile_args : true, includes : true) # Check for generic C arguments c_args = [] @@ -157,10 +165,14 @@ foreach a : cpp_args endforeach # check for dl support -if cc.has_function('dlopen') - dep_dl = null_dep +if is_unixy + if cc.has_function('dlopen') + dep_dl = null_dep + else + dep_dl = cc.find_library('dl') + endif else - dep_dl = cc.find_library('dl') + dep_dl = null_dep endif # check for linking with rt by default diff --git a/src/meson.build b/src/meson.build index 205f13c7..57174c88 100644 --- a/src/meson.build +++ b/src/meson.build @@ -26,90 +26,100 @@ foreach s : ['overlay.frag', 'overlay.vert'] command : [glslang, '-V', '-x', '-o', '@OUTPUT@', '@INPUT@']) endforeach -vklayer_files = files( - 'overlay.cpp', - 'overlay_params.cpp', - 'font_unispace.c', - 'blacklist.cpp', - 'cpu.cpp', - 'file_utils.cpp', - 'memory.cpp', - 'config.cpp', - 'iostats.cpp', - 'gpu.cpp', - 'notify.cpp', - 'elfhacks.cpp', - 'real_dlsym.cpp', - 'pci_ids.cpp', - 'logging.cpp', -) - -opengl_files = files( - 'gl/glad.c', - 'gl/imgui_impl_opengl3.cpp', - 'gl/imgui_hud.cpp', - 'gl/inject_egl.cpp', -) +vklayer_files = [] +opengl_files = [] +if ['windows', 'mingw'].contains(host_machine.system()) + vklayer_files += files( -if get_option('with_dlsym').enabled() - pre_args += '-DHOOK_DLSYM' + ) endif -nvml_h_found = get_option('with_nvml') == 'enabled' -if get_option('with_nvml') == 'system' - nvml_h_found = cc.has_header('nvml.h') - if not nvml_h_found - error('nvml.h was not found. Disable with \'-Dwith_nvml=disabled\' if gpu stats by NVML is not needed.') - endif - pre_args += '-DUSE_SYSTEM_NVML' -endif +if is_unixy + vklayer_files = files( + 'overlay.cpp', + 'overlay_params.cpp', + 'font_unispace.c', + 'blacklist.cpp', + 'cpu.cpp', + 'file_utils.cpp', + 'memory.cpp', + 'config.cpp', + 'iostats.cpp', + 'gpu.cpp', + 'notify.cpp', + 'elfhacks.cpp', + 'real_dlsym.cpp', + 'pci_ids.cpp', + 'logging.cpp', + ) -if nvml_h_found - pre_args += '-DHAVE_NVML' - vklayer_files += files( - 'nvml.cpp', - 'loaders/loader_nvml.cpp', + opengl_files = files( + 'gl/glad.c', + 'gl/imgui_impl_opengl3.cpp', + 'gl/imgui_hud.cpp', + 'gl/inject_egl.cpp', ) -endif -if get_option('with_xnvctrl').enabled() + if get_option('with_dlsym').enabled() + pre_args += '-DHOOK_DLSYM' + endif - if not get_option('with_x11').enabled() - error('XNVCtrl also needs \'with_x11\'') + nvml_h_found = get_option('with_nvml') == 'enabled' + if get_option('with_nvml') == 'system' + nvml_h_found = cc.has_header('nvml.h') + if not nvml_h_found + error('nvml.h was not found. Disable with \'-Dwith_nvml=disabled\' if gpu stats by NVML is not needed.') + endif + pre_args += '-DUSE_SYSTEM_NVML' endif - xnvctrl_h_found = cc.has_header('NVCtrl/NVCtrl.h') - if not xnvctrl_h_found - error('NVCtrl.h was not found. Disable with \'-Dwith_xnvctrl=disabled\' if gpu stats by XNVCtrl is not needed.') + if nvml_h_found + pre_args += '-DHAVE_NVML' + vklayer_files += files( + 'nvml.cpp', + 'loaders/loader_nvml.cpp', + ) endif - pre_args += '-DHAVE_XNVCTRL' - vklayer_files += files( - 'loaders/loader_nvctrl.cpp', - 'nvctrl.cpp', - ) -endif + if get_option('with_xnvctrl').enabled() -if get_option('with_x11').enabled() - pre_args += '-DHAVE_X11' + if not get_option('with_x11').enabled() + error('XNVCtrl also needs \'with_x11\'') + endif - vklayer_files += files( - 'loaders/loader_x11.cpp', - 'shared_x11.cpp', - ) + xnvctrl_h_found = cc.has_header('NVCtrl/NVCtrl.h') + if not xnvctrl_h_found + error('NVCtrl.h was not found. Disable with \'-Dwith_xnvctrl=disabled\' if gpu stats by XNVCtrl is not needed.') + endif - opengl_files += files( - 'loaders/loader_glx.cpp', - 'gl/inject_glx.cpp', - ) -endif + pre_args += '-DHAVE_XNVCTRL' + vklayer_files += files( + 'loaders/loader_nvctrl.cpp', + 'nvctrl.cpp', + ) + endif -if dbus_dep.found() and get_option('with_dbus').enabled() - pre_args += '-DHAVE_DBUS' - vklayer_files += files( - 'dbus.cpp', - 'loaders/loader_dbus.cpp', - ) + if get_option('with_x11').enabled() + pre_args += '-DHAVE_X11' + + vklayer_files += files( + 'loaders/loader_x11.cpp', + 'shared_x11.cpp', + ) + + opengl_files += files( + 'loaders/loader_glx.cpp', + 'gl/inject_glx.cpp', + ) + endif + + if dbus_dep.found() and get_option('with_dbus').enabled() + pre_args += '-DHAVE_DBUS' + vklayer_files += files( + 'dbus.cpp', + 'loaders/loader_dbus.cpp', + ) + endif endif link_args = cc.get_supported_link_arguments(['-Wl,-Bsymbolic-functions', '-Wl,-z,relro', '-Wl,--exclude-libs,ALL']) @@ -147,28 +157,29 @@ vklayer_mesa_overlay = shared_library( install_dir : libdir_mangohud, install : true ) - -mangohud_dlsym = shared_library( - 'MangoHud_dlsym', - files( - 'elfhacks.cpp', - 'real_dlsym.cpp', - 'hook_dlsym.cpp', - ), - c_args : [ - pre_args, - no_override_init_args, - ], - cpp_args : [ - pre_args, - ], - gnu_symbol_visibility : 'hidden', - dependencies : [dep_dl], - include_directories : [inc_common], - link_args : link_args, - install_dir : libdir_mangohud, - install : true -) +if is_unixy + mangohud_dlsym = shared_library( + 'MangoHud_dlsym', + files( + 'elfhacks.cpp', + 'real_dlsym.cpp', + 'hook_dlsym.cpp', + ), + c_args : [ + pre_args, + no_override_init_args, + ], + cpp_args : [ + pre_args, + ], + gnu_symbol_visibility : 'hidden', + dependencies : [dep_dl], + include_directories : [inc_common], + link_args : link_args, + install_dir : libdir_mangohud, + install : true + ) +endif configure_file(input : 'mangohud.json.in', output : '@0@.json'.format(meson.project_name()), From 3ffa1bed7ae1381c0917e06d7b58fce3a803ae5b Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sat, 5 Sep 2020 07:51:36 +0200 Subject: [PATCH 016/130] Windows attach dll --- src/meson.build | 2 +- src/win/main.cpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/win/main.cpp diff --git a/src/meson.build b/src/meson.build index 57174c88..7e999afb 100644 --- a/src/meson.build +++ b/src/meson.build @@ -30,7 +30,7 @@ vklayer_files = [] opengl_files = [] if ['windows', 'mingw'].contains(host_machine.system()) vklayer_files += files( - + 'win/main.cpp' ) endif diff --git a/src/win/main.cpp b/src/win/main.cpp new file mode 100644 index 00000000..08cd9882 --- /dev/null +++ b/src/win/main.cpp @@ -0,0 +1,32 @@ +#include "windows.h" +#include + +void ConsoleSetup() +{ + // With this trick we'll be able to print content to the console, and if we have luck we could get information printed by the game. + AllocConsole(); + SetConsoleTitle("MangoHud"); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + freopen("CONIN$", "r", stdin); +} + +int MainThread(){ + ConsoleSetup(); + return 0; +} + +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID) +{ + + DisableThreadLibraryCalls(hInstance); + + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MainThread, NULL, 0, NULL); + break; + } + + return TRUE; +} \ No newline at end of file From 8d3e8b520560dfb376fe4d846aa4383f522d7441 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sat, 5 Sep 2020 08:09:42 +0200 Subject: [PATCH 017/130] Add kiero to win --- src/meson.build | 3 +- src/win/kiero.cpp | 727 ++++++++++++++++++++++++++++++++++++++++++++++ src/win/kiero.h | 78 +++++ src/win/main.cpp | 2 + 4 files changed, 809 insertions(+), 1 deletion(-) create mode 100644 src/win/kiero.cpp create mode 100644 src/win/kiero.h diff --git a/src/meson.build b/src/meson.build index 7e999afb..933c4be2 100644 --- a/src/meson.build +++ b/src/meson.build @@ -30,7 +30,8 @@ vklayer_files = [] opengl_files = [] if ['windows', 'mingw'].contains(host_machine.system()) vklayer_files += files( - 'win/main.cpp' + 'win/main.cpp', + 'win/kiero.cpp' ) endif diff --git a/src/win/kiero.cpp b/src/win/kiero.cpp new file mode 100644 index 00000000..103c038e --- /dev/null +++ b/src/win/kiero.cpp @@ -0,0 +1,727 @@ +#include "kiero.h" +#include +#include + +#if KIERO_INCLUDE_D3D9 +# include +#endif + +#if KIERO_INCLUDE_D3D10 +# include +# include +# include +#endif + +#if KIERO_INCLUDE_D3D11 +# include +# include +#endif + +#if KIERO_INCLUDE_D3D12 +# include +# include +#endif + +#if KIERO_INCLUDE_OPENGL +# include +#endif + +#if KIERO_INCLUDE_VULKAN +# include +#endif + +#if KIERO_USE_MINHOOK +# include "minhook/include/MinHook.h" +#endif + +#ifdef _UNICODE +# define KIERO_TEXT(text) L##text +#else +# define KIERO_TEXT(text) text +#endif + +#define KIERO_ARRAY_SIZE(arr) ((size_t)(sizeof(arr)/sizeof(arr[0]))) + +static kiero::RenderType::Enum g_renderType = kiero::RenderType::None; +static uint150_t* g_methodsTable = NULL; + +kiero::Status::Enum kiero::init(RenderType::Enum _renderType) +{ + if (g_renderType != RenderType::None) + { + return Status::AlreadyInitializedError; + } + + if (_renderType != RenderType::None) + { + if (_renderType >= RenderType::D3D9 && _renderType <= RenderType::D3D12) + { + WNDCLASSEX windowClass; + windowClass.cbSize = sizeof(WNDCLASSEX); + windowClass.style = CS_HREDRAW | CS_VREDRAW; + windowClass.lpfnWndProc = DefWindowProc; + windowClass.cbClsExtra = 0; + windowClass.cbWndExtra = 0; + windowClass.hInstance = GetModuleHandle(NULL); + windowClass.hIcon = NULL; + windowClass.hCursor = NULL; + windowClass.hbrBackground = NULL; + windowClass.lpszMenuName = NULL; + windowClass.lpszClassName = KIERO_TEXT("Kiero"); + windowClass.hIconSm = NULL; + + ::RegisterClassEx(&windowClass); + + HWND window = ::CreateWindow(windowClass.lpszClassName, KIERO_TEXT("Kiero DirectX Window"), WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL, NULL, windowClass.hInstance, NULL); + + if (_renderType == RenderType::D3D9) + { +#if KIERO_INCLUDE_D3D9 + HMODULE libD3D9; + if ((libD3D9 = ::GetModuleHandle(KIERO_TEXT("d3d9.dll"))) == NULL) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::ModuleNotFoundError; + } + + void* Direct3DCreate9; + if ((Direct3DCreate9 = ::GetProcAddress(libD3D9, "Direct3DCreate9")) == NULL) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + LPDIRECT3D9 direct3D9; + if ((direct3D9 = ((LPDIRECT3D9(__stdcall*)(uint32_t))(Direct3DCreate9))(D3D_SDK_VERSION)) == NULL) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + D3DDISPLAYMODE displayMode; + if (direct3D9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode) < 0) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + D3DPRESENT_PARAMETERS params; + params.BackBufferWidth = 0; + params.BackBufferHeight = 0; + params.BackBufferFormat = displayMode.Format; + params.BackBufferCount = 0; + params.MultiSampleType = D3DMULTISAMPLE_NONE; + params.MultiSampleQuality = NULL; + params.SwapEffect = D3DSWAPEFFECT_DISCARD; + params.hDeviceWindow = window; + params.Windowed = 1; + params.EnableAutoDepthStencil = 0; + params.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + params.Flags = NULL; + params.FullScreen_RefreshRateInHz = 0; + params.PresentationInterval = 0; + + LPDIRECT3DDEVICE9 device; + if (direct3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_DISABLE_DRIVER_MANAGEMENT, ¶ms, &device) < 0) + { + direct3D9->Release(); + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + g_methodsTable = (uint150_t*)::calloc(119, sizeof(uint150_t)); + ::memcpy(g_methodsTable, *(uint150_t**)device, 119 * sizeof(uint150_t)); + +#if KIERO_USE_MINHOOK + MH_Initialize(); +#endif + + direct3D9->Release(); + direct3D9 = NULL; + + device->Release(); + device = NULL; + + g_renderType = RenderType::D3D9; + + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + + return Status::Success; +#endif + } + else if (_renderType == RenderType::D3D10) + { +#if KIERO_INCLUDE_D3D10 + HMODULE libDXGI; + HMODULE libD3D10; + if ((libDXGI = ::GetModuleHandle(KIERO_TEXT("dxgi.dll"))) == NULL || (libD3D10 = ::GetModuleHandle(KIERO_TEXT("d3d10.dll"))) == NULL) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::ModuleNotFoundError; + } + + void* CreateDXGIFactory; + if ((CreateDXGIFactory = ::GetProcAddress(libDXGI, "CreateDXGIFactory")) == NULL) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + IDXGIFactory* factory; + if (((long(__stdcall*)(const IID&, void**))(CreateDXGIFactory))(__uuidof(IDXGIFactory), (void**)&factory) < 0) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + IDXGIAdapter* adapter; + if (factory->EnumAdapters(0, &adapter) == DXGI_ERROR_NOT_FOUND) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + void* D3D10CreateDeviceAndSwapChain; + if ((D3D10CreateDeviceAndSwapChain = ::GetProcAddress(libD3D10, "D3D10CreateDeviceAndSwapChain")) == NULL) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + DXGI_RATIONAL refreshRate; + refreshRate.Numerator = 60; + refreshRate.Denominator = 1; + + DXGI_MODE_DESC bufferDesc; + bufferDesc.Width = 100; + bufferDesc.Height = 100; + bufferDesc.RefreshRate = refreshRate; + bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + + DXGI_SAMPLE_DESC sampleDesc; + sampleDesc.Count = 1; + sampleDesc.Quality = 0; + + DXGI_SWAP_CHAIN_DESC swapChainDesc; + swapChainDesc.BufferDesc = bufferDesc; + swapChainDesc.SampleDesc = sampleDesc; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = 1; + swapChainDesc.OutputWindow = window; + swapChainDesc.Windowed = 1; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + + IDXGISwapChain* swapChain; + ID3D10Device* device; + + if (((long(__stdcall*)( + IDXGIAdapter*, + D3D10_DRIVER_TYPE, + HMODULE, + UINT, + UINT, + DXGI_SWAP_CHAIN_DESC*, + IDXGISwapChain**, + ID3D10Device**))(D3D10CreateDeviceAndSwapChain))(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, &swapChainDesc, &swapChain, &device) < 0) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + g_methodsTable = (uint150_t*)::calloc(116, sizeof(uint150_t)); + ::memcpy(g_methodsTable, *(uint150_t**)swapChain, 18 * sizeof(uint150_t)); + ::memcpy(g_methodsTable + 18, *(uint150_t**)device, 98 * sizeof(uint150_t)); + +#if KIERO_USE_MINHOOK + MH_Initialize(); +#endif + + swapChain->Release(); + swapChain = NULL; + + device->Release(); + device = NULL; + + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + + g_renderType = RenderType::D3D10; + + return Status::Success; +#endif + } + else if (_renderType == RenderType::D3D11) + { +#if KIERO_INCLUDE_D3D11 + HMODULE libD3D11; + if ((libD3D11 = ::GetModuleHandle(KIERO_TEXT("d3d11.dll"))) == NULL) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::ModuleNotFoundError; + } + + void* D3D11CreateDeviceAndSwapChain; + if ((D3D11CreateDeviceAndSwapChain = ::GetProcAddress(libD3D11, "D3D11CreateDeviceAndSwapChain")) == NULL) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + D3D_FEATURE_LEVEL featureLevel; + const D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_11_0 }; + + DXGI_RATIONAL refreshRate; + refreshRate.Numerator = 60; + refreshRate.Denominator = 1; + + DXGI_MODE_DESC bufferDesc; + bufferDesc.Width = 100; + bufferDesc.Height = 100; + bufferDesc.RefreshRate = refreshRate; + bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + + DXGI_SAMPLE_DESC sampleDesc; + sampleDesc.Count = 1; + sampleDesc.Quality = 0; + + DXGI_SWAP_CHAIN_DESC swapChainDesc; + swapChainDesc.BufferDesc = bufferDesc; + swapChainDesc.SampleDesc = sampleDesc; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = 1; + swapChainDesc.OutputWindow = window; + swapChainDesc.Windowed = 1; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + + IDXGISwapChain* swapChain; + ID3D11Device* device; + ID3D11DeviceContext* context; + + if (((long(__stdcall*)( + IDXGIAdapter*, + D3D_DRIVER_TYPE, + HMODULE, + UINT, + const D3D_FEATURE_LEVEL*, + UINT, + UINT, + const DXGI_SWAP_CHAIN_DESC*, + IDXGISwapChain**, + ID3D11Device**, + D3D_FEATURE_LEVEL*, + ID3D11DeviceContext**))(D3D11CreateDeviceAndSwapChain))(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, featureLevels, 2, D3D11_SDK_VERSION, &swapChainDesc, &swapChain, &device, &featureLevel, &context) < 0) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + g_methodsTable = (uint150_t*)::calloc(205, sizeof(uint150_t)); + ::memcpy(g_methodsTable, *(uint150_t**)swapChain, 18 * sizeof(uint150_t)); + ::memcpy(g_methodsTable + 18, *(uint150_t**)device, 43 * sizeof(uint150_t)); + ::memcpy(g_methodsTable + 18 + 43, *(uint150_t**)context, 144 * sizeof(uint150_t)); + +#if KIERO_USE_MINHOOK + MH_Initialize(); +#endif + + swapChain->Release(); + swapChain = NULL; + + device->Release(); + device = NULL; + + context->Release(); + context = NULL; + + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + + g_renderType = RenderType::D3D11; + + return Status::Success; +#endif + } + else if (_renderType == RenderType::D3D12) + { +#if KIERO_INCLUDE_D3D12 + HMODULE libDXGI; + HMODULE libD3D12; + if ((libDXGI = ::GetModuleHandle(KIERO_TEXT("dxgi.dll"))) == NULL || (libD3D12 = ::GetModuleHandle(KIERO_TEXT("d3d12.dll"))) == NULL) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::ModuleNotFoundError; + } + + void* CreateDXGIFactory; + if ((CreateDXGIFactory = ::GetProcAddress(libDXGI, "CreateDXGIFactory")) == NULL) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + IDXGIFactory* factory; + if (((long(__stdcall*)(const IID&, void**))(CreateDXGIFactory))(__uuidof(IDXGIFactory), (void**)&factory) < 0) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + IDXGIAdapter* adapter; + if (factory->EnumAdapters(0, &adapter) == DXGI_ERROR_NOT_FOUND) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + void* D3D12CreateDevice; + if ((D3D12CreateDevice = ::GetProcAddress(libD3D12, "D3D12CreateDevice")) == NULL) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + ID3D12Device* device; + if (((long(__stdcall*)(IUnknown*, D3D_FEATURE_LEVEL, const IID&, void**))(D3D12CreateDevice))(adapter, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), (void**)&device) < 0) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + D3D12_COMMAND_QUEUE_DESC queueDesc; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + queueDesc.Priority = 0; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.NodeMask = 0; + + ID3D12CommandQueue* commandQueue; + if (device->CreateCommandQueue(&queueDesc, __uuidof(ID3D12CommandQueue), (void**)&commandQueue) < 0) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + ID3D12CommandAllocator* commandAllocator; + if (device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&commandAllocator) < 0) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + ID3D12GraphicsCommandList* commandList; + if (device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, commandAllocator, NULL, __uuidof(ID3D12GraphicsCommandList), (void**)&commandList) < 0) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + DXGI_RATIONAL refreshRate; + refreshRate.Numerator = 60; + refreshRate.Denominator = 1; + + DXGI_MODE_DESC bufferDesc; + bufferDesc.Width = 100; + bufferDesc.Height = 100; + bufferDesc.RefreshRate = refreshRate; + bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + + DXGI_SAMPLE_DESC sampleDesc; + sampleDesc.Count = 1; + sampleDesc.Quality = 0; + + DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; + swapChainDesc.BufferDesc = bufferDesc; + swapChainDesc.SampleDesc = sampleDesc; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = 2; + swapChainDesc.OutputWindow = window; + swapChainDesc.Windowed = 1; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + + IDXGISwapChain* swapChain; + if (factory->CreateSwapChain(commandQueue, &swapChainDesc, &swapChain) < 0) + { + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + return Status::UnknownError; + } + + g_methodsTable = (uint150_t*)::calloc(150, sizeof(uint150_t)); + ::memcpy(g_methodsTable, *(uint150_t**)device, 44 * sizeof(uint150_t)); + ::memcpy(g_methodsTable + 44, *(uint150_t**)commandQueue, 19 * sizeof(uint150_t)); + ::memcpy(g_methodsTable + 44 + 19, *(uint150_t**)commandAllocator, 9 * sizeof(uint150_t)); + ::memcpy(g_methodsTable + 44 + 19 + 9, *(uint150_t**)commandList, 60 * sizeof(uint150_t)); + ::memcpy(g_methodsTable + 44 + 19 + 9 + 60, *(uint150_t**)swapChain, 18 * sizeof(uint150_t)); + +#if KIERO_USE_MINHOOK + MH_Initialize(); +#endif + + device->Release(); + device = NULL; + + commandQueue->Release(); + commandQueue = NULL; + + commandAllocator->Release(); + commandAllocator = NULL; + + commandList->Release(); + commandList = NULL; + + swapChain->Release(); + swapChain = NULL; + + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + + g_renderType = RenderType::D3D12; + + return Status::Success; +#endif + } + + ::DestroyWindow(window); + ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); + + return Status::NotSupportedError; + } + else if (_renderType != RenderType::Auto) + { + if (_renderType == RenderType::OpenGL) + { +#if KIERO_INCLUDE_OPENGL + HMODULE libOpenGL32; + if ((libOpenGL32 = ::GetModuleHandle(KIERO_TEXT("opengl32.dll"))) == NULL) + { + return Status::ModuleNotFoundError; + } + + const char* const methodsNames[] = { + "glAccum", "glAlphaFunc", "glAreTexturesResident", "glArrayElement", "glBegin", "glBindTexture", "glBitmap", "glBlendFunc", "glCallList", "glCallLists", "glClear", "glClearAccum", + "glClearColor", "glClearDepth", "glClearIndex", "glClearStencil", "glClipPlane", "glColor3b", "glColor3bv", "glColor3d", "glColor3dv", "glColor3f", "glColor3fv", "glColor3i", "glColor3iv", + "glColor3s", "glColor3sv", "glColor3ub", "glColor3ubv", "glColor3ui", "glColor3uiv", "glColor3us", "glColor3usv", "glColor4b", "glColor4bv", "glColor4d", "glColor4dv", "glColor4f", + "glColor4fv", "glColor4i", "glColor4iv", "glColor4s", "glColor4sv", "glColor4ub", "glColor4ubv", "glColor4ui", "glColor4uiv", "glColor4us", "glColor4usv", "glColorMask", "glColorMaterial", + "glColorPointer", "glCopyPixels", "glCopyTexImage1D", "glCopyTexImage2D", "glCopyTexSubImage1D", "glCopyTexSubImage2D", "glCullFaceglCullFace", "glDeleteLists", "glDeleteTextures", + "glDepthFunc", "glDepthMask", "glDepthRange", "glDisable", "glDisableClientState", "glDrawArrays", "glDrawBuffer", "glDrawElements", "glDrawPixels", "glEdgeFlag", "glEdgeFlagPointer", + "glEdgeFlagv", "glEnable", "glEnableClientState", "glEnd", "glEndList", "glEvalCoord1d", "glEvalCoord1dv", "glEvalCoord1f", "glEvalCoord1fv", "glEvalCoord2d", "glEvalCoord2dv", + "glEvalCoord2f", "glEvalCoord2fv", "glEvalMesh1", "glEvalMesh2", "glEvalPoint1", "glEvalPoint2", "glFeedbackBuffer", "glFinish", "glFlush", "glFogf", "glFogfv", "glFogi", "glFogiv", + "glFrontFace", "glFrustum", "glGenLists", "glGenTextures", "glGetBooleanv", "glGetClipPlane", "glGetDoublev", "glGetError", "glGetFloatv", "glGetIntegerv", "glGetLightfv", "glGetLightiv", + "glGetMapdv", "glGetMapfv", "glGetMapiv", "glGetMaterialfv", "glGetMaterialiv", "glGetPixelMapfv", "glGetPixelMapuiv", "glGetPixelMapusv", "glGetPointerv", "glGetPolygonStipple", + "glGetString", "glGetTexEnvfv", "glGetTexEnviv", "glGetTexGendv", "glGetTexGenfv", "glGetTexGeniv", "glGetTexImage", "glGetTexLevelParameterfv", "glGetTexLevelParameteriv", + "glGetTexParameterfv", "glGetTexParameteriv", "glHint", "glIndexMask", "glIndexPointer", "glIndexd", "glIndexdv", "glIndexf", "glIndexfv", "glIndexi", "glIndexiv", "glIndexs", "glIndexsv", + "glIndexub", "glIndexubv", "glInitNames", "glInterleavedArrays", "glIsEnabled", "glIsList", "glIsTexture", "glLightModelf", "glLightModelfv", "glLightModeli", "glLightModeliv", "glLightf", + "glLightfv", "glLighti", "glLightiv", "glLineStipple", "glLineWidth", "glListBase", "glLoadIdentity", "glLoadMatrixd", "glLoadMatrixf", "glLoadName", "glLogicOp", "glMap1d", "glMap1f", + "glMap2d", "glMap2f", "glMapGrid1d", "glMapGrid1f", "glMapGrid2d", "glMapGrid2f", "glMaterialf", "glMaterialfv", "glMateriali", "glMaterialiv", "glMatrixMode", "glMultMatrixd", + "glMultMatrixf", "glNewList", "glNormal3b", "glNormal3bv", "glNormal3d", "glNormal3dv", "glNormal3f", "glNormal3fv", "glNormal3i", "glNormal3iv", "glNormal3s", "glNormal3sv", + "glNormalPointer", "glOrtho", "glPassThrough", "glPixelMapfv", "glPixelMapuiv", "glPixelMapusv", "glPixelStoref", "glPixelStorei", "glPixelTransferf", "glPixelTransferi", "glPixelZoom", + "glPointSize", "glPolygonMode", "glPolygonOffset", "glPolygonStipple", "glPopAttrib", "glPopClientAttrib", "glPopMatrix", "glPopName", "glPrioritizeTextures", "glPushAttrib", + "glPushClientAttrib", "glPushMatrix", "glPushName", "glRasterPos2d", "glRasterPos2dv", "glRasterPos2f", "glRasterPos2fv", "glRasterPos2i", "glRasterPos2iv", "glRasterPos2s", + "glRasterPos2sv", "glRasterPos3d", "glRasterPos3dv", "glRasterPos3f", "glRasterPos3fv", "glRasterPos3i", "glRasterPos3iv", "glRasterPos3s", "glRasterPos3sv", "glRasterPos4d", + "glRasterPos4dv", "glRasterPos4f", "glRasterPos4fv", "glRasterPos4i", "glRasterPos4iv", "glRasterPos4s", "glRasterPos4sv", "glReadBuffer", "glReadPixels", "glRectd", "glRectdv", "glRectf", + "glRectfv", "glRecti", "glRectiv", "glRects", "glRectsv", "glRenderMode", "glRotated", "glRotatef", "glScaled", "glScalef", "glScissor", "glSelectBuffer", "glShadeModel", "glStencilFunc", + "glStencilMask", "glStencilOp", "glTexCoord1d", "glTexCoord1dv", "glTexCoord1f", "glTexCoord1fv", "glTexCoord1i", "glTexCoord1iv", "glTexCoord1s", "glTexCoord1sv", "glTexCoord2d", + "glTexCoord2dv", "glTexCoord2f", "glTexCoord2fv", "glTexCoord2i", "glTexCoord2iv", "glTexCoord2s", "glTexCoord2sv", "glTexCoord3d", "glTexCoord3dv", "glTexCoord3f", "glTexCoord3fv", + "glTexCoord3i", "glTexCoord3iv", "glTexCoord3s", "glTexCoord3sv", "glTexCoord4d", "glTexCoord4dv", "glTexCoord4f", "glTexCoord4fv", "glTexCoord4i", "glTexCoord4iv", "glTexCoord4s", + "glTexCoord4sv", "glTexCoordPointer", "glTexEnvf", "glTexEnvfv", "glTexEnvi", "glTexEnviv", "glTexGend", "glTexGendv", "glTexGenf", "glTexGenfv", "glTexGeni", "glTexGeniv", "glTexImage1D", + "glTexImage2D", "glTexParameterf", "glTexParameterfv", "glTexParameteri", "glTexParameteriv", "glTexSubImage1D", "glTexSubImage2D", "glTranslated", "glTranslatef", "glVertex2d", + "glVertex2dv", "glVertex2f", "glVertex2fv", "glVertex2i", "glVertex2iv", "glVertex2s", "glVertex2sv", "glVertex3d", "glVertex3dv", "glVertex3f", "glVertex3fv", "glVertex3i", "glVertex3iv", + "glVertex3s", "glVertex3sv", "glVertex4d", "glVertex4dv", "glVertex4f", "glVertex4fv", "glVertex4i", "glVertex4iv", "glVertex4s", "glVertex4sv", "glVertexPointer", "glViewport" + }; + + size_t size = KIERO_ARRAY_SIZE(methodsNames); + + g_methodsTable = (uint150_t*)::calloc(size, sizeof(uint150_t)); + + for (int i = 0; i < size; i++) + { + g_methodsTable[i] = (uint150_t)::GetProcAddress(libOpenGL32, methodsNames[i]); + } + +#if KIERO_USE_MINHOOK + MH_Initialize(); +#endif + + g_renderType = RenderType::OpenGL; + + return Status::Success; +#endif + } + else if (_renderType == RenderType::Vulkan) + { +#if KIERO_INCLUDE_VULKAN + HMODULE libVulkan; + if ((libVulkan = GetModuleHandle(KIERO_TEXT("vulkan-1.dll"))) == NULL) + { + return Status::ModuleNotFoundError; + } + + const char* const methodsNames[] = { + "vkCreateInstance", "vkDestroyInstance", "vkEnumeratePhysicalDevices", "vkGetPhysicalDeviceFeatures", "vkGetPhysicalDeviceFormatProperties", "vkGetPhysicalDeviceImageFormatProperties", + "vkGetPhysicalDeviceProperties", "vkGetPhysicalDeviceQueueFamilyProperties", "vkGetPhysicalDeviceMemoryProperties", "vkGetInstanceProcAddr", "vkGetDeviceProcAddr", "vkCreateDevice", + "vkDestroyDevice", "vkEnumerateInstanceExtensionProperties", "vkEnumerateDeviceExtensionProperties", "vkEnumerateDeviceLayerProperties", "vkGetDeviceQueue", "vkQueueSubmit", "vkQueueWaitIdle", + "vkDeviceWaitIdle", "vkAllocateMemory", "vkFreeMemory", "vkMapMemory", "vkUnmapMemory", "vkFlushMappedMemoryRanges", "vkInvalidateMappedMemoryRanges", "vkGetDeviceMemoryCommitment", + "vkBindBufferMemory", "vkBindImageMemory", "vkGetBufferMemoryRequirements", "vkGetImageMemoryRequirements", "vkGetImageSparseMemoryRequirements", "vkGetPhysicalDeviceSparseImageFormatProperties", + "vkQueueBindSparse", "vkCreateFence", "vkDestroyFence", "vkResetFences", "vkGetFenceStatus", "vkWaitForFences", "vkCreateSemaphore", "vkDestroySemaphore", "vkCreateEvent", "vkDestroyEvent", + "vkGetEventStatus", "vkSetEvent", "vkResetEvent", "vkCreateQueryPool", "vkDestroyQueryPool", "vkGetQueryPoolResults", "vkCreateBuffer", "vkDestroyBuffer", "vkCreateBufferView", "vkDestroyBufferView", + "vkCreateImage", "vkDestroyImage", "vkGetImageSubresourceLayout", "vkCreateImageView", "vkDestroyImageView", "vkCreateShaderModule", "vkDestroyShaderModule", "vkCreatePipelineCache", + "vkDestroyPipelineCache", "vkGetPipelineCacheData", "vkMergePipelineCaches", "vkCreateGraphicsPipelines", "vkCreateComputePipelines", "vkDestroyPipeline", "vkCreatePipelineLayout", + "vkDestroyPipelineLayout", "vkCreateSampler", "vkDestroySampler", "vkCreateDescriptorSetLayout", "vkDestroyDescriptorSetLayout", "vkCreateDescriptorPool", "vkDestroyDescriptorPool", + "vkResetDescriptorPool", "vkAllocateDescriptorSets", "vkFreeDescriptorSets", "vkUpdateDescriptorSets", "vkCreateFramebuffer", "vkDestroyFramebuffer", "vkCreateRenderPass", "vkDestroyRenderPass", + "vkGetRenderAreaGranularity", "vkCreateCommandPool", "vkDestroyCommandPool", "vkResetCommandPool", "vkAllocateCommandBuffers", "vkFreeCommandBuffers", "vkBeginCommandBuffer", "vkEndCommandBuffer", + "vkResetCommandBuffer", "vkCmdBindPipeline", "vkCmdSetViewport", "vkCmdSetScissor", "vkCmdSetLineWidth", "vkCmdSetDepthBias", "vkCmdSetBlendConstants", "vkCmdSetDepthBounds", + "vkCmdSetStencilCompareMask", "vkCmdSetStencilWriteMask", "vkCmdSetStencilReference", "vkCmdBindDescriptorSets", "vkCmdBindIndexBuffer", "vkCmdBindVertexBuffers", "vkCmdDraw", "vkCmdDrawIndexed", + "vkCmdDrawIndirect", "vkCmdDrawIndexedIndirect", "vkCmdDispatch", "vkCmdDispatchIndirect", "vkCmdCopyBuffer", "vkCmdCopyImage", "vkCmdBlitImage", "vkCmdCopyBufferToImage", "vkCmdCopyImageToBuffer", + "vkCmdUpdateBuffer", "vkCmdFillBuffer", "vkCmdClearColorImage", "vkCmdClearDepthStencilImage", "vkCmdClearAttachments", "vkCmdResolveImage", "vkCmdSetEvent", "vkCmdResetEvent", "vkCmdWaitEvents", + "vkCmdPipelineBarrier", "vkCmdBeginQuery", "vkCmdEndQuery", "vkCmdResetQueryPool", "vkCmdWriteTimestamp", "vkCmdCopyQueryPoolResults", "vkCmdPushConstants", "vkCmdBeginRenderPass", "vkCmdNextSubpass", + "vkCmdEndRenderPass", "vkCmdExecuteCommands" + }; + + size_t size = KIERO_ARRAY_SIZE(methodsNames); + + g_methodsTable = (uint150_t*)::calloc(size, sizeof(uint150_t)); + + for (int i = 0; i < size; i++) + { + g_methodsTable[i] = (uint150_t)::GetProcAddress(libVulkan, methodsNames[i]); + } + +#if KIERO_USE_MINHOOK + MH_Initialize(); +#endif + + g_renderType = RenderType::Vulkan; + + return Status::Success; +#endif + } + + return Status::NotSupportedError; + } + else + { + RenderType::Enum type = RenderType::None; + + if (::GetModuleHandle(KIERO_TEXT("d3d9.dll")) != NULL) + { + type = RenderType::D3D9; + } + else if (::GetModuleHandle(KIERO_TEXT("d3d10.dll")) != NULL) + { + type = RenderType::D3D10; + } + else if (::GetModuleHandle(KIERO_TEXT("d3d11.dll")) != NULL) + { + type = RenderType::D3D11; + } + else if (::GetModuleHandle(KIERO_TEXT("d3d12.dll")) != NULL) + { + type = RenderType::D3D12; + } + else if (::GetModuleHandle(KIERO_TEXT("opengl32.dll")) != NULL) + { + type = RenderType::OpenGL; + } + else if (::GetModuleHandle(KIERO_TEXT("vulkan-1.dll")) != NULL) + { + type = RenderType::Vulkan; + } + else + { + return Status::NotSupportedError; + } + + return init(type); + } + } + + return Status::Success; +} + +void kiero::shutdown() +{ + if (g_renderType != RenderType::None) + { +#if KIERO_USE_MINHOOK + MH_DisableHook(MH_ALL_HOOKS); +#endif + + ::free(g_methodsTable); + g_methodsTable = NULL; + g_renderType = RenderType::None; + } +} + +kiero::Status::Enum kiero::bind(uint16_t _index, void** _original, void* _function) +{ + // TODO: Need own detour function + + assert(_original != NULL && _function != NULL); + + if (g_renderType != RenderType::None) + { +#if KIERO_USE_MINHOOK + void* target = (void*)g_methodsTable[_index]; + if (MH_CreateHook(target, _function, _original) != MH_OK || MH_EnableHook(target) != MH_OK) + { + return Status::UnknownError; + } +#endif + + return Status::Success; + } + + return Status::NotInitializedError; +} + +void kiero::unbind(uint16_t _index) +{ + if (g_renderType != RenderType::None) + { +#if KIERO_USE_MINHOOK + MH_DisableHook((void*)g_methodsTable[_index]); +#endif + } +} + +kiero::RenderType::Enum kiero::getRenderType() +{ + return g_renderType; +} + +uint150_t* kiero::getMethodsTable() +{ + return g_methodsTable; +} \ No newline at end of file diff --git a/src/win/kiero.h b/src/win/kiero.h new file mode 100644 index 00000000..ec36bddb --- /dev/null +++ b/src/win/kiero.h @@ -0,0 +1,78 @@ +#ifndef __KIERO_H__ +#define __KIERO_H__ + +#include + +#define KIERO_VERSION "1.2.10" + +#define KIERO_INCLUDE_D3D9 0 // 1 if you need D3D9 hook +#define KIERO_INCLUDE_D3D10 0 // 1 if you need D3D10 hook +#define KIERO_INCLUDE_D3D11 0 // 1 if you need D3D11 hook +#define KIERO_INCLUDE_D3D12 0 // 1 if you need D3D12 hook +#define KIERO_INCLUDE_OPENGL 0 // 1 if you need OpenGL hook +#define KIERO_INCLUDE_VULKAN 1 // 1 if you need Vulkan hook +#define KIERO_USE_MINHOOK 0 // 1 if you will use kiero::bind function + +#define KIERO_ARCH_X64 0 +#define KIERO_ARCH_X86 0 + +#if defined(_M_X64) +# undef KIERO_ARCH_X64 +# define KIERO_ARCH_X64 1 +#else +# undef KIERO_ARCH_X86 +# define KIERO_ARCH_X86 1 +#endif + +#if KIERO_ARCH_X64 +typedef uint64_t uint150_t; +#else +typedef uint32_t uint150_t; +#endif + +namespace kiero +{ + struct Status + { + enum Enum + { + UnknownError = -1, + NotSupportedError = -2, + ModuleNotFoundError = -3, + + AlreadyInitializedError = -4, + NotInitializedError = -5, + + Success = 0, + }; + }; + + struct RenderType + { + enum Enum + { + None, + + D3D9, + D3D10, + D3D11, + D3D12, + + OpenGL, + Vulkan, + + Auto + }; + }; + + Status::Enum init(RenderType::Enum renderType); + void shutdown(); + + Status::Enum bind(uint16_t index, void** original, void* function); + void unbind(uint16_t index); + + RenderType::Enum getRenderType(); + uint150_t* getMethodsTable(); +} + +#endif // __KIERO_H__ \ No newline at end of file diff --git a/src/win/main.cpp b/src/win/main.cpp index 08cd9882..fd031b44 100644 --- a/src/win/main.cpp +++ b/src/win/main.cpp @@ -1,3 +1,4 @@ +#include "kiero.h" #include "windows.h" #include @@ -13,6 +14,7 @@ void ConsoleSetup() int MainThread(){ ConsoleSetup(); + printf("MangoHud Attached!\n"); return 0; } From 9391822da5a528a94a8df034a6e82b96e4ecaf8e Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sat, 5 Sep 2020 11:16:20 +0200 Subject: [PATCH 018/130] Basic d3d12 present hook --- meson.build | 14 +++++++------- src/meson.build | 3 ++- src/win/d3d12_hook.cpp | 19 +++++++++++++++++++ src/win/d3d12_hook.h | 22 ++++++++++++++++++++++ src/win/kiero.cpp | 16 ++++++++++------ src/win/kiero.h | 2 +- src/win/main.cpp | 24 +++++++++++++++++++++--- 7 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 src/win/d3d12_hook.cpp create mode 100644 src/win/d3d12_hook.h diff --git a/meson.build b/meson.build index 6a0dc0d2..d228f892 100644 --- a/meson.build +++ b/meson.build @@ -171,15 +171,15 @@ if is_unixy else dep_dl = cc.find_library('dl') endif +# check for linking with rt by default + if cc.has_function('clock_gettime') + dep_rt = null_dep + else + dep_rt = cc.find_library('rt') + endif else dep_dl = null_dep -endif - -# check for linking with rt by default -if cc.has_function('clock_gettime') dep_rt = null_dep -else - dep_rt = cc.find_library('rt') endif if dep_vulkan.found() @@ -222,7 +222,7 @@ dearimgui_dep = dearimgui_sp.get_variable('dearimgui_dep') if ['windows', 'mingw'].contains(host_machine.system()) subdir('modules/minhook') windows_deps = [ - minhook_dep + minhook_dep, ] else windows_deps = null_dep diff --git a/src/meson.build b/src/meson.build index 933c4be2..7a1c5adf 100644 --- a/src/meson.build +++ b/src/meson.build @@ -31,7 +31,8 @@ opengl_files = [] if ['windows', 'mingw'].contains(host_machine.system()) vklayer_files += files( 'win/main.cpp', - 'win/kiero.cpp' + 'win/kiero.cpp', + 'win/d3d12_hook.cpp', ) endif diff --git a/src/win/d3d12_hook.cpp b/src/win/d3d12_hook.cpp new file mode 100644 index 00000000..dd212b79 --- /dev/null +++ b/src/win/d3d12_hook.cpp @@ -0,0 +1,19 @@ +#include "kiero.h" +#include "d3d12_hook.h" +#include +#include +#include + +typedef long(__fastcall* PresentD3D12) (IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags); +PresentD3D12 oPresentD3D12; + +long __fastcall hkPresent12(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT Flags){ + printf("d3d12 present\n"); + return oPresentD3D12(pSwapChain, SyncInterval, Flags); +} + +void impl::d3d12::init() +{ + auto ret = kiero::bind(140, (void**)&oPresentD3D12, reinterpret_cast(hkPresent12)); + assert(ret == kiero::Status::Success); +} \ No newline at end of file diff --git a/src/win/d3d12_hook.h b/src/win/d3d12_hook.h new file mode 100644 index 00000000..e024bca4 --- /dev/null +++ b/src/win/d3d12_hook.h @@ -0,0 +1,22 @@ +#include +#include +#include +#ifdef _MSC_VER + #include +#else + #include "/usr/include/wine/windows/d3d12.h" +#endif +#ifndef __D3D12_IMPL_H__ +#define __D3D12_IMPL_H__ + +namespace impl +{ + namespace d3d12 + { + void init(); + void uninit(); + } +} + + +#endif // __D3D12_IMPL_H__ \ No newline at end of file diff --git a/src/win/kiero.cpp b/src/win/kiero.cpp index 103c038e..c4ffca88 100644 --- a/src/win/kiero.cpp +++ b/src/win/kiero.cpp @@ -1,6 +1,7 @@ #include "kiero.h" #include #include +#include #if KIERO_INCLUDE_D3D9 # include @@ -19,7 +20,11 @@ #if KIERO_INCLUDE_D3D12 # include -# include +#ifdef _MSC_VER + #include +#else + #include "/usr/include/wine/windows/d3d12.h" +#endif #endif #if KIERO_INCLUDE_OPENGL @@ -374,8 +379,8 @@ kiero::Status::Enum kiero::init(RenderType::Enum _renderType) return Status::ModuleNotFoundError; } - void* CreateDXGIFactory; - if ((CreateDXGIFactory = ::GetProcAddress(libDXGI, "CreateDXGIFactory")) == NULL) + auto CreateDXGIFactory = reinterpret_cast(::GetProcAddress(libDXGI, "CreateDXGIFactory")); + if (!CreateDXGIFactory) { ::DestroyWindow(window); ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); @@ -398,8 +403,8 @@ kiero::Status::Enum kiero::init(RenderType::Enum _renderType) return Status::UnknownError; } - void* D3D12CreateDevice; - if ((D3D12CreateDevice = ::GetProcAddress(libD3D12, "D3D12CreateDevice")) == NULL) + auto D3D12CreateDevice = reinterpret_cast(::GetProcAddress(libD3D12, "D3D12CreateDevice")); + if (!D3D12CreateDevice) { ::DestroyWindow(window); ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); @@ -508,7 +513,6 @@ kiero::Status::Enum kiero::init(RenderType::Enum _renderType) ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); g_renderType = RenderType::D3D12; - return Status::Success; #endif } diff --git a/src/win/kiero.h b/src/win/kiero.h index ec36bddb..cc8e8e4f 100644 --- a/src/win/kiero.h +++ b/src/win/kiero.h @@ -8,7 +8,7 @@ #define KIERO_INCLUDE_D3D9 0 // 1 if you need D3D9 hook #define KIERO_INCLUDE_D3D10 0 // 1 if you need D3D10 hook #define KIERO_INCLUDE_D3D11 0 // 1 if you need D3D11 hook -#define KIERO_INCLUDE_D3D12 0 // 1 if you need D3D12 hook +#define KIERO_INCLUDE_D3D12 1 // 1 if you need D3D12 hook #define KIERO_INCLUDE_OPENGL 0 // 1 if you need OpenGL hook #define KIERO_INCLUDE_VULKAN 1 // 1 if you need Vulkan hook #define KIERO_USE_MINHOOK 0 // 1 if you will use kiero::bind function diff --git a/src/win/main.cpp b/src/win/main.cpp index fd031b44..26f7293e 100644 --- a/src/win/main.cpp +++ b/src/win/main.cpp @@ -1,6 +1,10 @@ -#include "kiero.h" #include "windows.h" #include +#include "kiero.h" + +#if KIERO_INCLUDE_D3D12 +# include "d3d12_hook.h" +#endif void ConsoleSetup() { @@ -12,10 +16,24 @@ void ConsoleSetup() freopen("CONIN$", "r", stdin); } -int MainThread(){ +int MainThread() +{ ConsoleSetup(); printf("MangoHud Attached!\n"); - return 0; + if (kiero::init(kiero::RenderType::Auto) == kiero::Status::Success) + { + switch (kiero::getRenderType()) + { +#if KIERO_INCLUDE_D3D12 + case kiero::RenderType::D3D12: + impl::d3d12::init(); + break; +#endif + } + + return 1; + } + return 0; } BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID) From 1263b8d95466a9db9866f228390d79eb9390f7a2 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sun, 6 Sep 2020 07:50:31 +0200 Subject: [PATCH 019/130] Build with windows_deps --- meson.build | 1 + src/meson.build | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index d228f892..e3be9dab 100644 --- a/meson.build +++ b/meson.build @@ -221,6 +221,7 @@ dearimgui_dep = dearimgui_sp.get_variable('dearimgui_dep') if ['windows', 'mingw'].contains(host_machine.system()) subdir('modules/minhook') + inc_common += ( include_directories('modules/minhook/include')) windows_deps = [ minhook_dep, ] diff --git a/src/meson.build b/src/meson.build index 7a1c5adf..660edb55 100644 --- a/src/meson.build +++ b/src/meson.build @@ -153,7 +153,8 @@ vklayer_mesa_overlay = shared_library( dep_dl, dep_rt, dep_pthread, - dep_vulkan], + dep_vulkan, + windows_deps], include_directories : [inc_common], link_args : link_args, install_dir : libdir_mangohud, From 896a6117a217dab9674c136e9551fbd300a57073 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sun, 6 Sep 2020 07:53:51 +0200 Subject: [PATCH 020/130] Actually use minhook for kiero --- src/win/kiero.cpp | 2 +- src/win/kiero.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/win/kiero.cpp b/src/win/kiero.cpp index c4ffca88..61f77189 100644 --- a/src/win/kiero.cpp +++ b/src/win/kiero.cpp @@ -36,7 +36,7 @@ #endif #if KIERO_USE_MINHOOK -# include "minhook/include/MinHook.h" +# include "MinHook.h" #endif #ifdef _UNICODE diff --git a/src/win/kiero.h b/src/win/kiero.h index cc8e8e4f..3d275226 100644 --- a/src/win/kiero.h +++ b/src/win/kiero.h @@ -11,7 +11,7 @@ #define KIERO_INCLUDE_D3D12 1 // 1 if you need D3D12 hook #define KIERO_INCLUDE_OPENGL 0 // 1 if you need OpenGL hook #define KIERO_INCLUDE_VULKAN 1 // 1 if you need Vulkan hook -#define KIERO_USE_MINHOOK 0 // 1 if you will use kiero::bind function +#define KIERO_USE_MINHOOK 1 // 1 if you will use kiero::bind function #define KIERO_ARCH_X64 0 #define KIERO_ARCH_X86 0 From 968f3ab20ccbab6492cebf9be00d0362db7aa965 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sun, 6 Sep 2020 07:54:10 +0200 Subject: [PATCH 021/130] Cleaning up d3d12 hook --- src/win/d3d12_hook.cpp | 1 - src/win/d3d12_hook.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/win/d3d12_hook.cpp b/src/win/d3d12_hook.cpp index dd212b79..c0e9f3d0 100644 --- a/src/win/d3d12_hook.cpp +++ b/src/win/d3d12_hook.cpp @@ -2,7 +2,6 @@ #include "d3d12_hook.h" #include #include -#include typedef long(__fastcall* PresentD3D12) (IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags); PresentD3D12 oPresentD3D12; diff --git a/src/win/d3d12_hook.h b/src/win/d3d12_hook.h index e024bca4..7b4de721 100644 --- a/src/win/d3d12_hook.h +++ b/src/win/d3d12_hook.h @@ -14,7 +14,6 @@ namespace impl namespace d3d12 { void init(); - void uninit(); } } From 1c5baef9921a813c79e61aa28ae2de973298cef2 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sun, 6 Sep 2020 07:56:29 +0200 Subject: [PATCH 022/130] Move try_log into update_hud() and fix formatting --- src/overlay.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/overlay.cpp b/src/overlay.cpp index dfb59d0d..9bd9985d 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -928,23 +928,27 @@ void update_hud_info(struct swapchain_stats& sw_stats, struct overlay_params& pa now - sw_stats.last_present_time; } - frametime = now - sw_stats.last_present_time; - if (elapsed >= params.fps_sampling_period) { + frametime = now - sw_stats.last_present_time; + if (elapsed >= params.fps_sampling_period) { - std::thread(update_hw_info, std::ref(sw_stats), std::ref(params), vendorID).detach(); - sw_stats.fps = fps; + std::thread(update_hw_info, std::ref(sw_stats), std::ref(params), vendorID).detach(); + sw_stats.fps = fps; - if (params.enabled[OVERLAY_PARAM_ENABLED_time]) { - std::time_t t = std::time(nullptr); - std::stringstream time; - time << std::put_time(std::localtime(&t), params.time_format.c_str()); - sw_stats.time = time.str(); - } + if (params.enabled[OVERLAY_PARAM_ENABLED_time]) { + std::time_t t = std::time(nullptr); + std::stringstream time; + time << std::put_time(std::localtime(&t), params.time_format.c_str()); + sw_stats.time = time.str(); + } - sw_stats.n_frames_since_update = 0; - sw_stats.last_fps_update = now; + sw_stats.n_frames_since_update = 0; + sw_stats.last_fps_update = now; - } + } + + if (params.log_interval == 0){ + logger->try_log(); + } sw_stats.last_present_time = now; sw_stats.n_frames++; @@ -1194,9 +1198,6 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& static int tableCols = 2; static float ralign_width = 0, old_scale = 0; window_size = ImVec2(300, params.height); - if (params.log_interval == 0){ - logger->try_log(); - } if (old_scale != params.font_scale) { ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; From c3fc0f10b028e3c2a121279d6d7dc8d29cbe9db3 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sun, 6 Sep 2020 10:30:57 +0200 Subject: [PATCH 023/130] Start separating vulkan, keybinds, overlay and font --- src/font.cpp | 78 ++ src/keybinds.cpp | 84 ++ src/meson.build | 11 +- src/overlay.cpp | 3063 +--------------------------------------------- src/overlay.h | 1 + src/vulkan.cpp | 2907 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 3084 insertions(+), 3060 deletions(-) create mode 100644 src/font.cpp create mode 100644 src/keybinds.cpp create mode 100644 src/vulkan.cpp diff --git a/src/font.cpp b/src/font.cpp new file mode 100644 index 00000000..691d3882 --- /dev/null +++ b/src/font.cpp @@ -0,0 +1,78 @@ +#include "overlay.h" +#include "file_utils.h" +#include "font_default.h" + +void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& text_font) +{ + auto& io = ImGui::GetIO(); + ImGui::GetIO().FontGlobalScale = params.font_scale; // set here too so ImGui::CalcTextSize is correct + float font_size = params.font_size; + if (font_size < FLT_EPSILON) + font_size = 24; + + float font_size_text = params.font_size_text; + if (font_size_text < FLT_EPSILON) + font_size_text = font_size; + if(params.render_mango) + font_size = 42; + static const ImWchar default_range[] = + { + 0x0020, 0x00FF, // Basic Latin + Latin Supplement + //0x0100, 0x017F, // Latin Extended-A + //0x2103, 0x2103, // Degree Celsius + //0x2109, 0x2109, // Degree Fahrenheit + 0, + }; + + ImVector glyph_ranges; + ImFontGlyphRangesBuilder builder; + builder.AddRanges(io.Fonts->GetGlyphRangesDefault()); + if (params.font_glyph_ranges & FG_KOREAN) + builder.AddRanges(io.Fonts->GetGlyphRangesKorean()); + if (params.font_glyph_ranges & FG_CHINESE_FULL) + builder.AddRanges(io.Fonts->GetGlyphRangesChineseFull()); + if (params.font_glyph_ranges & FG_CHINESE_SIMPLIFIED) + builder.AddRanges(io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); + if (params.font_glyph_ranges & FG_JAPANESE) + builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Not exactly Shift JIS compatible? + if (params.font_glyph_ranges & FG_CYRILLIC) + builder.AddRanges(io.Fonts->GetGlyphRangesCyrillic()); + if (params.font_glyph_ranges & FG_THAI) + builder.AddRanges(io.Fonts->GetGlyphRangesThai()); + if (params.font_glyph_ranges & FG_VIETNAMESE) + builder.AddRanges(io.Fonts->GetGlyphRangesVietnamese()); + if (params.font_glyph_ranges & FG_LATIN_EXT_A) { + static const ImWchar latin_ext_a[] { 0x0100, 0x017F, 0 }; + builder.AddRanges(latin_ext_a); + } + if (params.font_glyph_ranges & FG_LATIN_EXT_B) { + static const ImWchar latin_ext_b[] { 0x0180, 0x024F, 0 }; + builder.AddRanges(latin_ext_b); + } + builder.BuildRanges(&glyph_ranges); + + // If both font_file and text_font_file are the same then just use "default" font + bool same_font = (params.font_file == params.font_file_text || params.font_file_text.empty()); + bool same_size = (font_size == font_size_text); + + // ImGui takes ownership of the data, no need to free it + if (!params.font_file.empty() && file_exists(params.font_file)) { + io.Fonts->AddFontFromFileTTF(params.font_file.c_str(), font_size, nullptr, same_font && same_size ? glyph_ranges.Data : default_range); + small_font = io.Fonts->AddFontFromFileTTF(params.font_file.c_str(), font_size * 0.55f, nullptr, default_range); + } else { + const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); + io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_size, nullptr, default_range); + small_font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_size * 0.55f, nullptr, default_range); + } + + auto font_file_text = params.font_file_text; + if (font_file_text.empty()) + font_file_text = params.font_file; + + if ((!same_font || !same_size) && file_exists(font_file_text)) + text_font = io.Fonts->AddFontFromFileTTF(font_file_text.c_str(), font_size_text, nullptr, glyph_ranges.Data); + else + text_font = io.Fonts->Fonts[0]; + + io.Fonts->Build(); +} \ No newline at end of file diff --git a/src/keybinds.cpp b/src/keybinds.cpp new file mode 100644 index 00000000..d9550480 --- /dev/null +++ b/src/keybinds.cpp @@ -0,0 +1,84 @@ +#include "overlay.h" +#include "timing.hpp" +#include "logging.h" +#include "keybinds.h" + +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 + 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 >= keyPressDelay){ +#ifdef HAVE_X11 + pressed = keys_are_pressed(params.toggle_logging); +#else + pressed = false; +#endif + if (pressed && (now - logger->last_log_end() > 11s)) { + last_f2_press = now; + + if (logger->is_active()) { + logger->stop_logging(); + } else { + logger->start_logging(); + std::thread(update_hw_info, std::ref(sw_stats), std::ref(params), + vendorID) + .detach(); + benchmark.fps_data.clear(); + } + } + } + + if (elapsedF12 >= keyPressDelay){ +#ifdef HAVE_X11 + pressed = keys_are_pressed(params.toggle_hud); +#else + pressed = false; +#endif + if (pressed){ + last_f12_press = now; + params.no_display = !params.no_display; + } + } + + if (elapsedReloadCfg >= keyPressDelay){ +#ifdef HAVE_X11 + pressed = keys_are_pressed(params.reload_cfg); +#else + pressed = false; +#endif + if (pressed){ + parse_overlay_config(¶ms, getenv("MANGOHUD_CONFIG")); + reload_cfg_press = now; + } + } + + if (params.permit_upload && elapsedUpload >= keyPressDelay){ +#ifdef HAVE_X11 + pressed = keys_are_pressed(params.upload_log); +#else + pressed = false; +#endif + if (pressed){ + last_upload_press = now; + logger->upload_last_log(); + } + } + if (params.permit_upload && elapsedUpload >= keyPressDelay){ +#ifdef HAVE_X11 + pressed = keys_are_pressed(params.upload_logs); +#else + pressed = false; +#endif + if (pressed){ + last_upload_press = now; + logger->upload_last_logs(); + } + } +} \ No newline at end of file diff --git a/src/meson.build b/src/meson.build index 660edb55..1c9936a7 100644 --- a/src/meson.build +++ b/src/meson.build @@ -26,19 +26,24 @@ foreach s : ['overlay.frag', 'overlay.vert'] command : [glslang, '-V', '-x', '-o', '@OUTPUT@', '@INPUT@']) endforeach -vklayer_files = [] +vklayer_files = files( + 'overlay.cpp', + 'font.cpp', + 'keybinds.cpp' +) opengl_files = [] if ['windows', 'mingw'].contains(host_machine.system()) vklayer_files += files( 'win/main.cpp', 'win/kiero.cpp', 'win/d3d12_hook.cpp', + 'win/d3d_shared.cpp' ) endif if is_unixy - vklayer_files = files( - 'overlay.cpp', + vklayer_files += files( + 'vulkan.cpp', 'overlay_params.cpp', 'font_unispace.c', 'blacklist.cpp', diff --git a/src/overlay.cpp b/src/overlay.cpp index 9bd9985d..8bb70117 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -1,760 +1,13 @@ -/* - * Copyright © 2019 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "imgui.h" - +#include +#include +#include #include "overlay.h" -#include "font_default.h" - -// #include "util/debug.h" -#include -#include "mesa/util/macros.h" -#include "mesa/util/os_time.h" -#include "mesa/util/os_socket.h" - -#include "vk_enum_to_str.h" -#include - -#include "string_utils.h" -#include "file_utils.h" -#include "gpu.h" #include "logging.h" -#include "keybinds.h" #include "cpu.h" +#include "gpu.h" #include "memory.h" -#include "notify.h" -#include "blacklist.h" -#include "version.h" -#include "pci_ids.h" #include "timing.hpp" - -#ifdef HAVE_DBUS -#include "dbus_info.h" -float g_overflow = 50.f /* 3333ms * 0.5 / 16.6667 / 2 (to edge and back) */; -#endif - -bool open = false; -string gpuString,wineVersion,wineProcess; -float offset_x, offset_y, hudSpacing; -int hudFirstRow, hudSecondRow; -struct fps_limit fps_limit_stats {}; -VkPhysicalDeviceDriverProperties driverProps = {}; -int32_t deviceID; -struct benchmark_stats benchmark; - -/* Mapped from VkInstace/VkPhysicalDevice */ -struct instance_data { - struct vk_instance_dispatch_table vtable; - VkInstance instance; - struct overlay_params params; - uint32_t api_version; - string engineName, engineVersion; - notify_thread notifier; -}; - -/* Mapped from VkDevice */ -struct queue_data; -struct device_data { - struct instance_data *instance; - - PFN_vkSetDeviceLoaderData set_device_loader_data; - - struct vk_device_dispatch_table vtable; - VkPhysicalDevice physical_device; - VkDevice device; - - VkPhysicalDeviceProperties properties; - - struct queue_data *graphic_queue; - - std::vector queues; -}; - -/* Mapped from VkCommandBuffer */ -struct queue_data; -struct command_buffer_data { - struct device_data *device; - - VkCommandBufferLevel level; - - VkCommandBuffer cmd_buffer; - - struct queue_data *queue_data; -}; - -/* Mapped from VkQueue */ -struct queue_data { - struct device_data *device; - - VkQueue queue; - VkQueueFlags flags; - uint32_t family_index; -}; - -struct overlay_draw { - VkCommandBuffer command_buffer; - - VkSemaphore cross_engine_semaphore; - - VkSemaphore semaphore; - VkFence fence; - - VkBuffer vertex_buffer; - VkDeviceMemory vertex_buffer_mem; - VkDeviceSize vertex_buffer_size; - - VkBuffer index_buffer; - VkDeviceMemory index_buffer_mem; - VkDeviceSize index_buffer_size; -}; - -/* Mapped from VkSwapchainKHR */ -struct swapchain_data { - struct device_data *device; - - VkSwapchainKHR swapchain; - unsigned width, height; - VkFormat format; - - std::vector images; - std::vector image_views; - std::vector framebuffers; - - VkRenderPass render_pass; - - VkDescriptorPool descriptor_pool; - VkDescriptorSetLayout descriptor_layout; - VkDescriptorSet descriptor_set; - - VkSampler font_sampler; - - VkPipelineLayout pipeline_layout; - VkPipeline pipeline; - - VkCommandPool command_pool; - - std::list draws; /* List of struct overlay_draw */ - - bool font_uploaded; - VkImage font_image; - VkImageView font_image_view; - VkDeviceMemory font_mem; - VkBuffer upload_font_buffer; - VkDeviceMemory upload_font_buffer_mem; - - /**/ - ImGuiContext* imgui_context; - ImVec2 window_size; - - struct swapchain_stats sw_stats; -}; - -// single global lock, for simplicity -std::mutex global_lock; -typedef std::lock_guard scoped_lock; -std::unordered_map vk_object_to_data; - -thread_local ImGuiContext* __MesaImGui; - -#define HKEY(obj) ((uint64_t)(obj)) -#define FIND(type, obj) (reinterpret_cast(find_object_data(HKEY(obj)))) - -static void *find_object_data(uint64_t obj) -{ - scoped_lock lk(global_lock); - return vk_object_to_data[obj]; -} - -static void map_object(uint64_t obj, void *data) -{ - scoped_lock lk(global_lock); - vk_object_to_data[obj] = data; -} - -static void unmap_object(uint64_t obj) -{ - scoped_lock lk(global_lock); - vk_object_to_data.erase(obj); -} - -/**/ - -#define VK_CHECK(expr) \ - do { \ - VkResult __result = (expr); \ - if (__result != VK_SUCCESS) { \ - fprintf(stderr, "'%s' line %i failed with %s\n", \ - #expr, __LINE__, vk_Result_to_str(__result)); \ - } \ - } while (0) - -/**/ - -#define CHAR_CELSIUS "\xe2\x84\x83" -#define CHAR_FAHRENHEIT "\xe2\x84\x89" - -void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& text_font) -{ - auto& io = ImGui::GetIO(); - ImGui::GetIO().FontGlobalScale = params.font_scale; // set here too so ImGui::CalcTextSize is correct - float font_size = params.font_size; - if (font_size < FLT_EPSILON) - font_size = 24; - - float font_size_text = params.font_size_text; - if (font_size_text < FLT_EPSILON) - font_size_text = font_size; - if(params.render_mango) - font_size = 42; - static const ImWchar default_range[] = - { - 0x0020, 0x00FF, // Basic Latin + Latin Supplement - //0x0100, 0x017F, // Latin Extended-A - //0x2103, 0x2103, // Degree Celsius - //0x2109, 0x2109, // Degree Fahrenheit - 0, - }; - - ImVector glyph_ranges; - ImFontGlyphRangesBuilder builder; - builder.AddRanges(io.Fonts->GetGlyphRangesDefault()); - if (params.font_glyph_ranges & FG_KOREAN) - builder.AddRanges(io.Fonts->GetGlyphRangesKorean()); - if (params.font_glyph_ranges & FG_CHINESE_FULL) - builder.AddRanges(io.Fonts->GetGlyphRangesChineseFull()); - if (params.font_glyph_ranges & FG_CHINESE_SIMPLIFIED) - builder.AddRanges(io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); - if (params.font_glyph_ranges & FG_JAPANESE) - builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Not exactly Shift JIS compatible? - if (params.font_glyph_ranges & FG_CYRILLIC) - builder.AddRanges(io.Fonts->GetGlyphRangesCyrillic()); - if (params.font_glyph_ranges & FG_THAI) - builder.AddRanges(io.Fonts->GetGlyphRangesThai()); - if (params.font_glyph_ranges & FG_VIETNAMESE) - builder.AddRanges(io.Fonts->GetGlyphRangesVietnamese()); - if (params.font_glyph_ranges & FG_LATIN_EXT_A) { - static const ImWchar latin_ext_a[] { 0x0100, 0x017F, 0 }; - builder.AddRanges(latin_ext_a); - } - if (params.font_glyph_ranges & FG_LATIN_EXT_B) { - static const ImWchar latin_ext_b[] { 0x0180, 0x024F, 0 }; - builder.AddRanges(latin_ext_b); - } - builder.BuildRanges(&glyph_ranges); - - // If both font_file and text_font_file are the same then just use "default" font - bool same_font = (params.font_file == params.font_file_text || params.font_file_text.empty()); - bool same_size = (font_size == font_size_text); - - // ImGui takes ownership of the data, no need to free it - if (!params.font_file.empty() && file_exists(params.font_file)) { - io.Fonts->AddFontFromFileTTF(params.font_file.c_str(), font_size, nullptr, same_font && same_size ? glyph_ranges.Data : default_range); - small_font = io.Fonts->AddFontFromFileTTF(params.font_file.c_str(), font_size * 0.55f, nullptr, default_range); - } else { - const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); - io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_size, nullptr, default_range); - small_font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_size * 0.55f, nullptr, default_range); - } - - auto font_file_text = params.font_file_text; - if (font_file_text.empty()) - font_file_text = params.font_file; - - if ((!same_font || !same_size) && file_exists(font_file_text)) - text_font = io.Fonts->AddFontFromFileTTF(font_file_text.c_str(), font_size_text, nullptr, glyph_ranges.Data); - else - text_font = io.Fonts->Fonts[0]; - - io.Fonts->Build(); -} - -static VkLayerInstanceCreateInfo *get_instance_chain_info(const VkInstanceCreateInfo *pCreateInfo, - VkLayerFunction func) -{ - vk_foreach_struct(item, pCreateInfo->pNext) { - if (item->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && - ((VkLayerInstanceCreateInfo *) item)->function == func) - return (VkLayerInstanceCreateInfo *) item; - } - unreachable("instance chain info not found"); - return NULL; -} - -static VkLayerDeviceCreateInfo *get_device_chain_info(const VkDeviceCreateInfo *pCreateInfo, - VkLayerFunction func) -{ - vk_foreach_struct(item, pCreateInfo->pNext) { - if (item->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && - ((VkLayerDeviceCreateInfo *) item)->function == func) - return (VkLayerDeviceCreateInfo *)item; - } - unreachable("device chain info not found"); - return NULL; -} - -/**/ - -static struct instance_data *new_instance_data(VkInstance instance) -{ - struct instance_data *data = new instance_data(); - data->instance = instance; - data->params = {}; - data->params.control = -1; - map_object(HKEY(data->instance), data); - return data; -} - -static void destroy_instance_data(struct instance_data *data) -{ - if (data->params.control >= 0) - os_socket_close(data->params.control); - unmap_object(HKEY(data->instance)); - delete data; -} - -static void instance_data_map_physical_devices(struct instance_data *instance_data, - bool map) -{ - uint32_t physicalDeviceCount = 0; - instance_data->vtable.EnumeratePhysicalDevices(instance_data->instance, - &physicalDeviceCount, - NULL); - - std::vector physicalDevices(physicalDeviceCount); - instance_data->vtable.EnumeratePhysicalDevices(instance_data->instance, - &physicalDeviceCount, - physicalDevices.data()); - - for (uint32_t i = 0; i < physicalDeviceCount; i++) { - if (map) - map_object(HKEY(physicalDevices[i]), instance_data); - else - unmap_object(HKEY(physicalDevices[i])); - } -} - -/**/ -static struct device_data *new_device_data(VkDevice device, struct instance_data *instance) -{ - struct device_data *data = new device_data(); - data->instance = instance; - data->device = device; - map_object(HKEY(data->device), data); - return data; -} - -static struct queue_data *new_queue_data(VkQueue queue, - const VkQueueFamilyProperties *family_props, - uint32_t family_index, - struct device_data *device_data) -{ - struct queue_data *data = new queue_data(); - data->device = device_data; - data->queue = queue; - data->flags = family_props->queueFlags; - data->family_index = family_index; - map_object(HKEY(data->queue), data); - - if (data->flags & VK_QUEUE_GRAPHICS_BIT) - device_data->graphic_queue = data; - - return data; -} - -static void destroy_queue(struct queue_data *data) -{ - unmap_object(HKEY(data->queue)); - delete data; -} - -static void device_map_queues(struct device_data *data, - const VkDeviceCreateInfo *pCreateInfo) -{ - uint32_t n_queues = 0; - for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) - n_queues += pCreateInfo->pQueueCreateInfos[i].queueCount; - data->queues.resize(n_queues); - - struct instance_data *instance_data = data->instance; - uint32_t n_family_props; - instance_data->vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device, - &n_family_props, - NULL); - std::vector family_props(n_family_props); - instance_data->vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device, - &n_family_props, - family_props.data()); - - uint32_t queue_index = 0; - for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) { - for (uint32_t j = 0; j < pCreateInfo->pQueueCreateInfos[i].queueCount; j++) { - VkQueue queue; - data->vtable.GetDeviceQueue(data->device, - pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex, - j, &queue); - - VK_CHECK(data->set_device_loader_data(data->device, queue)); - - data->queues[queue_index++] = - new_queue_data(queue, &family_props[pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex], - pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex, data); - } - } -} - -static void device_unmap_queues(struct device_data *data) -{ - for (auto q : data->queues) - destroy_queue(q); -} - -static void destroy_device_data(struct device_data *data) -{ - unmap_object(HKEY(data->device)); - delete data; -} - -/**/ -static struct command_buffer_data *new_command_buffer_data(VkCommandBuffer cmd_buffer, - VkCommandBufferLevel level, - struct device_data *device_data) -{ - struct command_buffer_data *data = new command_buffer_data(); - data->device = device_data; - data->cmd_buffer = cmd_buffer; - data->level = level; - map_object(HKEY(data->cmd_buffer), data); - return data; -} - -static void destroy_command_buffer_data(struct command_buffer_data *data) -{ - unmap_object(HKEY(data->cmd_buffer)); - delete data; -} - -/**/ -static struct swapchain_data *new_swapchain_data(VkSwapchainKHR swapchain, - struct device_data *device_data) -{ - struct instance_data *instance_data = device_data->instance; - struct swapchain_data *data = new swapchain_data(); - data->device = device_data; - data->swapchain = swapchain; - data->window_size = ImVec2(instance_data->params.width, instance_data->params.height); - map_object(HKEY(data->swapchain), data); - return data; -} - -static void destroy_swapchain_data(struct swapchain_data *data) -{ - unmap_object(HKEY(data->swapchain)); - delete data; -} - -struct overlay_draw *get_overlay_draw(struct swapchain_data *data) -{ - struct device_data *device_data = data->device; - struct overlay_draw *draw = data->draws.empty() ? - nullptr : data->draws.front(); - - VkSemaphoreCreateInfo sem_info = {}; - sem_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - - if (draw && device_data->vtable.GetFenceStatus(device_data->device, draw->fence) == VK_SUCCESS) { - VK_CHECK(device_data->vtable.ResetFences(device_data->device, - 1, &draw->fence)); - data->draws.pop_front(); - data->draws.push_back(draw); - return draw; - } - - draw = new overlay_draw(); - - VkCommandBufferAllocateInfo cmd_buffer_info = {}; - cmd_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - cmd_buffer_info.commandPool = data->command_pool; - cmd_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - cmd_buffer_info.commandBufferCount = 1; - VK_CHECK(device_data->vtable.AllocateCommandBuffers(device_data->device, - &cmd_buffer_info, - &draw->command_buffer)); - VK_CHECK(device_data->set_device_loader_data(device_data->device, - draw->command_buffer)); - - - VkFenceCreateInfo fence_info = {}; - fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - VK_CHECK(device_data->vtable.CreateFence(device_data->device, - &fence_info, - NULL, - &draw->fence)); - - VK_CHECK(device_data->vtable.CreateSemaphore(device_data->device, &sem_info, - NULL, &draw->semaphore)); - VK_CHECK(device_data->vtable.CreateSemaphore(device_data->device, &sem_info, - NULL, &draw->cross_engine_semaphore)); - - data->draws.push_back(draw); - - return draw; -} - -void init_cpu_stats(overlay_params& params) -{ - auto& enabled = params.enabled; - enabled[OVERLAY_PARAM_ENABLED_cpu_stats] = cpuStats.Init() - && enabled[OVERLAY_PARAM_ENABLED_cpu_stats]; - enabled[OVERLAY_PARAM_ENABLED_cpu_temp] = cpuStats.GetCpuFile() - && enabled[OVERLAY_PARAM_ENABLED_cpu_temp]; -} - -struct PCI_BUS { - int domain; - int bus; - int slot; - int func; -}; - -void init_gpu_stats(uint32_t& vendorID, overlay_params& params) -{ - //if (!params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats]) - // return; - - PCI_BUS pci; - bool pci_bus_parsed = false; - const char *pci_dev = nullptr; - if (!params.pci_dev.empty()) - pci_dev = params.pci_dev.c_str(); - - // for now just checks if pci bus parses correctly, if at all necessary - if (pci_dev) { - if (sscanf(pci_dev, "%04x:%02x:%02x.%x", - &pci.domain, &pci.bus, - &pci.slot, &pci.func) == 4) { - pci_bus_parsed = true; - // reformat back to sysfs file name's and nvml's expected format - // so config file param's value format doesn't have to be as strict - std::stringstream ss; - ss << std::hex - << std::setw(4) << std::setfill('0') << pci.domain << ":" - << std::setw(2) << pci.bus << ":" - << std::setw(2) << pci.slot << "." - << std::setw(1) << pci.func; - params.pci_dev = ss.str(); - pci_dev = params.pci_dev.c_str(); -#ifndef NDEBUG - std::cerr << "MANGOHUD: PCI device ID: '" << pci_dev << "'\n"; -#endif - } else { - std::cerr << "MANGOHUD: Failed to parse PCI device ID: '" << pci_dev << "'\n"; - std::cerr << "MANGOHUD: Specify it as 'domain:bus:slot.func'\n"; - } - } - - // NVIDIA or Intel but maybe has Optimus - if (vendorID == 0x8086 - || vendorID == 0x10de) { - - bool nvSuccess = false; -#ifdef HAVE_NVML - nvSuccess = checkNVML(pci_dev) && getNVMLInfo(); -#endif -#ifdef HAVE_XNVCTRL - if (!nvSuccess) - nvSuccess = checkXNVCtrl(); -#endif - - if(not nvSuccess) { - params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] = false; - } - else { - vendorID = 0x10de; - } - } - - if (vendorID == 0x8086 || vendorID == 0x1002 - || gpu.find("Radeon") != std::string::npos - || gpu.find("AMD") != std::string::npos) { - string path; - string drm = "/sys/class/drm/"; - - auto dirs = ls(drm.c_str(), "card"); - for (auto& dir : dirs) { - path = drm + dir; - -#ifndef NDEBUG - std::cerr << "amdgpu path check: " << path << "/device/vendor" << std::endl; -#endif - string device = read_line(path + "/device/device"); - deviceID = strtol(device.c_str(), NULL, 16); - string line = read_line(path + "/device/vendor"); - trim(line); - if (line != "0x1002" || !file_exists(path + "/device/gpu_busy_percent")) - continue; - - path += "/device"; - if (pci_bus_parsed && pci_dev) { - string pci_device = read_symlink(path.c_str()); -#ifndef NDEBUG - std::cerr << "PCI device symlink: " << pci_device << "\n"; -#endif - if (!ends_with(pci_device, pci_dev)) { - std::cerr << "MANGOHUD: skipping GPU, no PCI ID match\n"; - continue; - } - } - -#ifndef NDEBUG - std::cerr << "using amdgpu path: " << path << std::endl; -#endif - - if (!amdgpu.busy) - amdgpu.busy = fopen((path + "/gpu_busy_percent").c_str(), "r"); - if (!amdgpu.vram_total) - amdgpu.vram_total = fopen((path + "/mem_info_vram_total").c_str(), "r"); - if (!amdgpu.vram_used) - amdgpu.vram_used = fopen((path + "/mem_info_vram_used").c_str(), "r"); - - path += "/hwmon/"; - string tempFolder; - if (find_folder(path, "hwmon", tempFolder)) { - if (!amdgpu.core_clock) - amdgpu.core_clock = fopen((path + tempFolder + "/freq1_input").c_str(), "r"); - if (!amdgpu.memory_clock) - amdgpu.memory_clock = fopen((path + tempFolder + "/freq2_input").c_str(), "r"); - if (!amdgpu.temp) - amdgpu.temp = fopen((path + tempFolder + "/temp1_input").c_str(), "r"); - if (!amdgpu.power_usage) - amdgpu.power_usage = fopen((path + tempFolder + "/power1_average").c_str(), "r"); - - vendorID = 0x1002; - break; - } - } - - // don't bother then - if (!amdgpu.busy && !amdgpu.temp && !amdgpu.vram_total && !amdgpu.vram_used) { - params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] = false; - } - } - if (!params.permit_upload) - printf("MANGOHUD: Uploading is disabled (permit_upload = 0)\n"); -} - -void init_system_info(){ - const char* ld_preload = getenv("LD_PRELOAD"); - if (ld_preload) - unsetenv("LD_PRELOAD"); - - ram = exec("cat /proc/meminfo | grep 'MemTotal' | awk '{print $2}'"); - trim(ram); - cpu = exec("cat /proc/cpuinfo | grep 'model name' | tail -n1 | sed 's/^.*: //' | sed 's/([^)]*)/()/g' | tr -d '(/)'"); - trim(cpu); - kernel = exec("uname -r"); - trim(kernel); - os = exec("cat /etc/*-release | grep 'PRETTY_NAME' | cut -d '=' -f 2-"); - os.erase(remove(os.begin(), os.end(), '\"' ), os.end()); - trim(os); - gpu = exec("lspci | grep VGA | head -n1 | awk -vRS=']' -vFS='[' '{print $2}' | sed '/^$/d' | tail -n1"); - trim(gpu); - driver = exec("glxinfo | grep 'OpenGL version' | sed 's/^.*: //' | cut -d' ' --output-delimiter=$'\n' -f1- | grep -v '(' | grep -v ')' | tr '\n' ' ' | cut -c 1-"); - trim(driver); - -// Get WINE version - - wineProcess = get_exe_path(); - auto n = wineProcess.find_last_of('/'); - string preloader = wineProcess.substr(n + 1); - if (preloader == "wine-preloader" || preloader == "wine64-preloader") { - // Check if using Proton - if (wineProcess.find("/dist/bin/wine") != std::string::npos) { - stringstream ss; - ss << dirname((char*)wineProcess.c_str()) << "/../../version"; - string protonVersion = ss.str(); - ss.str(""); ss.clear(); - ss << read_line(protonVersion); - std::getline(ss, wineVersion, ' '); // skip first number string - std::getline(ss, wineVersion, ' '); - trim(wineVersion); - string toReplace = "proton-"; - size_t pos = wineVersion.find(toReplace); - if (pos != std::string::npos) { - // If found replace - wineVersion.replace(pos, toReplace.length(), "Proton "); - } - else { - // If not found insert for non official proton builds - wineVersion.insert(0, "Proton "); - } - } - else { - char *dir = dirname((char*)wineProcess.c_str()); - stringstream findVersion; - findVersion << "\"" << dir << "/wine\" --version"; - const char *wine_env = getenv("WINELOADERNOEXEC"); - if (wine_env) - unsetenv("WINELOADERNOEXEC"); - wineVersion = exec(findVersion.str()); - std::cout << "WINE VERSION = " << wineVersion << "\n"; - if (wine_env) - setenv("WINELOADERNOEXEC", wine_env, 1); - } - } - else { - wineVersion = ""; - } - - //driver = itox(device_data->properties.driverVersion); - - if (ld_preload) - setenv("LD_PRELOAD", ld_preload, 1); -#ifndef NDEBUG - std::cout << "Ram:" << ram << "\n" - << "Cpu:" << cpu << "\n" - << "Kernel:" << kernel << "\n" - << "Os:" << os << "\n" - << "Gpu:" << gpu << "\n" - << "Driver:" << driver << std::endl; -#endif - parse_pciids(); -} +#include "mesa/util/macros.h" void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& params, uint32_t vendorID) { @@ -794,125 +47,6 @@ void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& par logger->notify_data_valid(); } -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 - 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 >= keyPressDelay){ -#ifdef HAVE_X11 - pressed = keys_are_pressed(params.toggle_logging); -#else - pressed = false; -#endif - if (pressed && (now - logger->last_log_end() > 11s)) { - last_f2_press = now; - - if (logger->is_active()) { - logger->stop_logging(); - } else { - logger->start_logging(); - std::thread(update_hw_info, std::ref(sw_stats), std::ref(params), - vendorID) - .detach(); - benchmark.fps_data.clear(); - } - } - } - - if (elapsedF12 >= keyPressDelay){ -#ifdef HAVE_X11 - pressed = keys_are_pressed(params.toggle_hud); -#else - pressed = false; -#endif - if (pressed){ - last_f12_press = now; - params.no_display = !params.no_display; - } - } - - if (elapsedReloadCfg >= keyPressDelay){ -#ifdef HAVE_X11 - pressed = keys_are_pressed(params.reload_cfg); -#else - pressed = false; -#endif - if (pressed){ - parse_overlay_config(¶ms, getenv("MANGOHUD_CONFIG")); - reload_cfg_press = now; - } - } - - if (params.permit_upload && elapsedUpload >= keyPressDelay){ -#ifdef HAVE_X11 - pressed = keys_are_pressed(params.upload_log); -#else - pressed = false; -#endif - if (pressed){ - last_upload_press = now; - logger->upload_last_log(); - } - } - if (params.permit_upload && elapsedUpload >= keyPressDelay){ -#ifdef HAVE_X11 - pressed = keys_are_pressed(params.upload_logs); -#else - pressed = false; -#endif - if (pressed){ - last_upload_press = now; - logger->upload_last_logs(); - } - } -} - -void calculate_benchmark_data(void *params_void){ - overlay_params *params = reinterpret_cast(params_void); - - vector sorted = benchmark.fps_data; - sort(sorted.begin(), sorted.end()); - benchmark.percentile_data.clear(); - - benchmark.total = 0.f; - for (auto fps_ : sorted){ - benchmark.total = benchmark.total + fps_; - } - - size_t max_label_size = 0; - - for (std::string percentile : params->benchmark_percentiles) { - float result; - - // special case handling for a mean-based average - if (percentile == "AVG") { - result = benchmark.total / sorted.size(); - } else { - // the percentiles are already validated when they're parsed from the config. - float fraction = parse_float(percentile) / 100; - - result = sorted[(fraction * sorted.size()) - 1]; - percentile += "%"; - } - - if (percentile.length() > max_label_size) - max_label_size = percentile.length(); - - benchmark.percentile_data.push_back({percentile, result}); - } - - for (auto& entry : benchmark.percentile_data) { - entry.first.append(max_label_size - entry.first.length(), ' '); - } -} - void update_hud_info(struct swapchain_stats& sw_stats, struct overlay_params& params, uint32_t vendorID){ if(not logger) logger = std::make_unique(¶ms); uint32_t f_idx = sw_stats.n_frames % ARRAY_SIZE(sw_stats.frames_stats); @@ -953,2189 +87,4 @@ void update_hud_info(struct swapchain_stats& sw_stats, struct overlay_params& pa sw_stats.last_present_time = now; sw_stats.n_frames++; sw_stats.n_frames_since_update++; -} - -static void snapshot_swapchain_frame(struct swapchain_data *data) -{ - struct device_data *device_data = data->device; - struct instance_data *instance_data = device_data->instance; - update_hud_info(data->sw_stats, instance_data->params, device_data->properties.vendorID); - check_keybinds(data->sw_stats, instance_data->params, device_data->properties.vendorID); - - // not currently used - // if (instance_data->params.control >= 0) { - // control_client_check(device_data); - // process_control_socket(instance_data); - // } -} - -static float get_time_stat(void *_data, int _idx) -{ - struct swapchain_stats *data = (struct swapchain_stats *) _data; - if ((ARRAY_SIZE(data->frames_stats) - _idx) > data->n_frames) - return 0.0f; - int idx = ARRAY_SIZE(data->frames_stats) + - data->n_frames < ARRAY_SIZE(data->frames_stats) ? - _idx - data->n_frames : - _idx + data->n_frames; - idx %= ARRAY_SIZE(data->frames_stats); - /* Time stats are in us. */ - return data->frames_stats[idx].stats[data->stat_selector] / data->time_dividor; -} - -void position_layer(struct swapchain_stats& data, struct overlay_params& params, ImVec2 window_size) -{ - unsigned width = ImGui::GetIO().DisplaySize.x; - unsigned height = ImGui::GetIO().DisplaySize.y; - float margin = 10.0f; - if (params.offset_x > 0 || params.offset_y > 0) - margin = 0.0f; - - ImGui::SetNextWindowBgAlpha(params.background_alpha); - ImGui::SetNextWindowSize(window_size, ImGuiCond_Always); - ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8,-3)); - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, params.alpha); - switch (params.position) { - case LAYER_POSITION_TOP_LEFT: - data.main_window_pos = ImVec2(margin + params.offset_x, margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - case LAYER_POSITION_TOP_RIGHT: - data.main_window_pos = ImVec2(width - window_size.x - margin + params.offset_x, margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - case LAYER_POSITION_BOTTOM_LEFT: - data.main_window_pos = ImVec2(margin + params.offset_x, height - window_size.y - margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - case LAYER_POSITION_BOTTOM_RIGHT: - data.main_window_pos = ImVec2(width - window_size.x - margin + params.offset_x, height - window_size.y - margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - case LAYER_POSITION_TOP_CENTER: - data.main_window_pos = ImVec2((width / 2) - (window_size.x / 2), margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - } -} - -static void right_aligned_text(float off_x, const char *fmt, ...) -{ - ImVec2 pos = ImGui::GetCursorPos(); - char buffer[32] {}; - - va_list args; - va_start(args, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, args); - va_end(args); - - ImVec2 sz = ImGui::CalcTextSize(buffer); - ImGui::SetCursorPosX(pos.x + off_x - sz.x); - ImGui::Text("%s", buffer); -} - -float get_ticker_limited_pos(float pos, float tw, float& left_limit, float& right_limit) -{ - float cw = ImGui::GetContentRegionAvailWidth(); - float new_pos_x = ImGui::GetCursorPosX(); - left_limit = cw - tw + new_pos_x; - right_limit = new_pos_x; - - if (cw < tw) { - new_pos_x += pos; - // acts as a delay before it starts scrolling again - if (new_pos_x < left_limit) - return left_limit; - else if (new_pos_x > right_limit) - return right_limit; - else - return new_pos_x; - } - return new_pos_x; -} - -#ifdef HAVE_DBUS -static void render_mpris_metadata(struct overlay_params& params, mutexed_metadata& meta, uint64_t frame_timing, bool is_main) -{ - if (meta.meta.valid) { - auto color = ImGui::ColorConvertU32ToFloat4(params.media_player_color); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8,0)); - ImGui::Dummy(ImVec2(0.0f, 20.0f)); - //ImGui::PushFont(data.font1); - - if (meta.ticker.needs_recalc) { - meta.ticker.tw0 = ImGui::CalcTextSize(meta.meta.title.c_str()).x; - meta.ticker.tw1 = ImGui::CalcTextSize(meta.meta.artists.c_str()).x; - meta.ticker.tw2 = ImGui::CalcTextSize(meta.meta.album.c_str()).x; - meta.ticker.longest = std::max(std::max( - meta.ticker.tw0, - meta.ticker.tw1), - meta.ticker.tw2); - meta.ticker.needs_recalc = false; - } - - float new_pos, left_limit = 0, right_limit = 0; - get_ticker_limited_pos(meta.ticker.pos, meta.ticker.longest, left_limit, right_limit); - - if (meta.ticker.pos < left_limit - g_overflow * .5f) { - meta.ticker.dir = -1; - meta.ticker.pos = (left_limit - g_overflow * .5f) + 1.f /* random */; - } else if (meta.ticker.pos > right_limit + g_overflow) { - meta.ticker.dir = 1; - meta.ticker.pos = (right_limit + g_overflow) - 1.f /* random */; - } - - meta.ticker.pos -= .5f * (frame_timing / 16666.7f) * meta.ticker.dir; - - for (auto order : params.media_player_order) { - switch (order) { - case MP_ORDER_TITLE: - { - new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw0, left_limit, right_limit); - ImGui::SetCursorPosX(new_pos); - ImGui::TextColored(color, "%s", meta.meta.title.c_str()); - } - break; - case MP_ORDER_ARTIST: - { - new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw1, left_limit, right_limit); - ImGui::SetCursorPosX(new_pos); - ImGui::TextColored(color, "%s", meta.meta.artists.c_str()); - } - break; - case MP_ORDER_ALBUM: - { - //ImGui::NewLine(); - if (!meta.meta.album.empty()) { - new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw2, left_limit, right_limit); - ImGui::SetCursorPosX(new_pos); - ImGui::TextColored(color, "%s", meta.meta.album.c_str()); - } - } - break; - default: break; - } - } - - if (!meta.meta.playing) { - ImGui::TextColored(color, "(paused)"); - } - - //ImGui::PopFont(); - ImGui::PopStyleVar(); - } -} -#endif - -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 = (2 + benchmark.percentile_data.size()) * params.font_size + 10.0f + 58; - ImGui::SetNextWindowSize(ImVec2(window_size.x, benchHeight), ImGuiCond_Always); - if (height - (window_size.y + data.main_window_pos.y + 5) < benchHeight) - ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y - benchHeight - 5), ImGuiCond_Always); - else - ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y + window_size.y + 5), ImGuiCond_Always); - - float display_time = std::chrono::duration(now - logger->last_log_end()).count(); - static float display_for = 10.0f; - float alpha; - if(params.background_alpha != 0){ - if (display_for >= display_time){ - alpha = display_time * params.background_alpha; - if (alpha >= params.background_alpha){ - ImGui::SetNextWindowBgAlpha(params.background_alpha); - }else{ - ImGui::SetNextWindowBgAlpha(alpha); - } - } else { - alpha = 6.0 - display_time * params.background_alpha; - if (alpha >= params.background_alpha){ - ImGui::SetNextWindowBgAlpha(params.background_alpha); - }else{ - ImGui::SetNextWindowBgAlpha(alpha); - } - } - } else { - if (display_for >= display_time){ - alpha = display_time * 0.0001; - ImGui::SetNextWindowBgAlpha(params.background_alpha); - } else { - alpha = 6.0 - display_time * 0.0001; - ImGui::SetNextWindowBgAlpha(params.background_alpha); - } - } - ImGui::Begin("Benchmark", &open, ImGuiWindowFlags_NoDecoration); - static const char* finished = "Logging Finished"; - ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(finished).x / 2)); - 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", std::chrono::duration(logger->last_log_end() - logger->last_log_begin()).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.percentile_data){ - char buffer[20]; - snprintf(buffer, sizeof(buffer), "%s %.1f", data_.first.c_str(), data_.second); - ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(buffer).x / 2)); - ImGui::TextColored(ImVec4(1.0, 1.0, 1.0, alpha / params.background_alpha), "%s %.1f", data_.first.c_str(), data_.second); - } - float max = *max_element(benchmark.fps_data.begin(), benchmark.fps_data.end()); - ImVec4 plotColor = data.colors.frametime; - plotColor.w = alpha / params.background_alpha; - ImGui::PushStyleColor(ImGuiCol_PlotLines, plotColor); - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0, 0.0, 0.0, alpha / params.background_alpha)); - ImGui::Dummy(ImVec2(0.0f, 8.0f)); - if (params.enabled[OVERLAY_PARAM_ENABLED_histogram]) - ImGui::PlotHistogram("", benchmark.fps_data.data(), benchmark.fps_data.size(), 0, "", 0.0f, max + 10, ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); - else - ImGui::PlotLines("", benchmark.fps_data.data(), benchmark.fps_data.size(), 0, "", 0.0f, max + 10, ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); - ImGui::PopStyleColor(2); - ImGui::End(); -} - -void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan){ - static int tableCols = 2; - static float ralign_width = 0, old_scale = 0; - window_size = ImVec2(300, params.height); - - if (old_scale != params.font_scale) { - ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; - old_scale = params.font_scale; - } - ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); - ImGui::BeginTable("hud", tableCols); - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats]){ - ImGui::TableNextRow(); - const char* gpu_text; - if (params.gpu_text.empty()) - gpu_text = "GPU"; - else - gpu_text = params.gpu_text.c_str(); - ImGui::TextColored(data.colors.gpu, "%s", gpu_text); - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::Text("%%"); - } - if(params.enabled[OVERLAY_PARAM_ENABLED_cpu_stats]){ - ImGui::TableNextRow(); - const char* cpu_text; - if (params.cpu_text.empty()) - cpu_text = "CPU"; - else - cpu_text = params.cpu_text.c_str(); - ImGui::TextColored(data.colors.cpu, "%s", cpu_text); - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); - ImGui::SameLine(0, 1.0f); - ImGui::Text("%%"); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_fps]){ - ImGui::TableNextRow(); - ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%.0f", data.fps); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("FPS"); - ImGui::PopFont(); - } - ImGui::EndTable(); - if (params.enabled[OVERLAY_PARAM_ENABLED_frame_timing]){ - ImGui::Dummy(ImVec2(0.0f, 8.0f)); - ImGui::PushFont(data.font1); - ImGui::TextColored(data.colors.engine, "%s", "Frametime"); - ImGui::PopFont(); - - char hash[40]; - snprintf(hash, sizeof(hash), "##%s", overlay_param_names[OVERLAY_PARAM_ENABLED_frame_timing]); - data.stat_selector = OVERLAY_PLOTS_frame_timing; - data.time_dividor = 1000.0f; - - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); - double min_time = 0.0f; - double max_time = 50.0f; - ImGui::PlotLines(hash, get_time_stat, &data, - ARRAY_SIZE(data.frames_stats), 0, - NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); - - ImGui::PopStyleColor(); - } - if(logger->is_active()) - ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(data.main_window_pos.x + window_size.x - 15, data.main_window_pos.y + 15), 10, params.engine_color, 20); - ImGui::End(); - window_size = ImVec2(window_size.x, 200); -} - -void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan) -{ - ImGui::GetIO().FontGlobalScale = params.font_scale; - if(not logger) logger = std::make_unique(¶ms); - uint32_t f_idx = (data.n_frames - 1) % ARRAY_SIZE(data.frames_stats); - uint64_t frame_timing = data.frames_stats[f_idx].stats[OVERLAY_PLOTS_frame_timing]; - static float ralign_width = 0, old_scale = 0; - window_size = ImVec2(params.width, params.height); - unsigned height = ImGui::GetIO().DisplaySize.y; - auto now = Clock::now(); - if (params.log_interval == 0){ - logger->try_log(); - } - - if (old_scale != params.font_scale) { - ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; - old_scale = params.font_scale; - } - - if (!params.no_display){ - ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); - if (params.enabled[OVERLAY_PARAM_ENABLED_version]){ - ImGui::Text("%s", MANGOHUD_VERSION); - ImGui::Dummy(ImVec2(0, 8.0f)); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_time]){ - ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.00f), "%s", data.time.c_str()); - } - ImGui::BeginTable("hud", params.tableCols); - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats]){ - ImGui::TableNextRow(); - const char* gpu_text; - if (params.gpu_text.empty()) - gpu_text = "GPU"; - else - gpu_text = params.gpu_text.c_str(); - ImGui::TextColored(data.colors.gpu, "%s", gpu_text); - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::Text("%%"); - // ImGui::SameLine(150); - // ImGui::Text("%s", "%"); - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_temp]){ - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", gpu_info.temp); - ImGui::SameLine(0, 1.0f); - ImGui::Text("°C"); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock] || params.enabled[OVERLAY_PARAM_ENABLED_gpu_power]) - ImGui::TableNextRow(); - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock]){ - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", gpu_info.CoreClock); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("MHz"); - ImGui::PopFont(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_power]) { - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", gpu_info.powerUsage); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("W"); - ImGui::PopFont(); - } - } - if(params.enabled[OVERLAY_PARAM_ENABLED_cpu_stats]){ - ImGui::TableNextRow(); - const char* cpu_text; - if (params.cpu_text.empty()) - cpu_text = "CPU"; - else - cpu_text = params.cpu_text.c_str(); - ImGui::TextColored(data.colors.cpu, "%s", cpu_text); - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); - ImGui::SameLine(0, 1.0f); - ImGui::Text("%%"); - // ImGui::SameLine(150); - // ImGui::Text("%s", "%"); - - if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_temp]){ - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); - ImGui::SameLine(0, 1.0f); - ImGui::Text("°C"); - } - } - - if (params.enabled[OVERLAY_PARAM_ENABLED_core_load]){ - int i = 0; - for (const CPUData &cpuData : cpuStats.GetCPUData()) - { - ImGui::TableNextRow(); - ImGui::TextColored(data.colors.cpu, "CPU"); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::TextColored(data.colors.cpu,"%i", i); - ImGui::PopFont(); - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", int(cpuData.percent)); - ImGui::SameLine(0, 1.0f); - ImGui::Text("%%"); - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", cpuData.mhz); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("MHz"); - ImGui::PopFont(); - i++; - } - } - if (params.enabled[OVERLAY_PARAM_ENABLED_io_read] || params.enabled[OVERLAY_PARAM_ENABLED_io_write]){ - auto sampling = params.fps_sampling_period; - ImGui::TableNextRow(); - if (params.enabled[OVERLAY_PARAM_ENABLED_io_read] && !params.enabled[OVERLAY_PARAM_ENABLED_io_write]) - ImGui::TextColored(data.colors.io, "IO RD"); - else if (params.enabled[OVERLAY_PARAM_ENABLED_io_read] && params.enabled[OVERLAY_PARAM_ENABLED_io_write]) - ImGui::TextColored(data.colors.io, "IO RW"); - else if (params.enabled[OVERLAY_PARAM_ENABLED_io_write] && !params.enabled[OVERLAY_PARAM_ENABLED_io_read]) - ImGui::TextColored(data.colors.io, "IO WR"); - - if (params.enabled[OVERLAY_PARAM_ENABLED_io_read]){ - ImGui::TableNextCell(); - float val = data.io.diff.read * 1000000 / sampling; - right_aligned_text(ralign_width, val < 100 ? "%.1f" : "%.f", val); - ImGui::SameLine(0,1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("MiB/s"); - ImGui::PopFont(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_io_write]){ - ImGui::TableNextCell(); - float val = data.io.diff.write * 1000000 / sampling; - right_aligned_text(ralign_width, val < 100 ? "%.1f" : "%.f", val); - ImGui::SameLine(0,1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("MiB/s"); - ImGui::PopFont(); - } - } - if (params.enabled[OVERLAY_PARAM_ENABLED_vram]){ - ImGui::TableNextRow(); - ImGui::TextColored(data.colors.vram, "VRAM"); - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%.1f", gpu_info.memoryUsed); - ImGui::SameLine(0,1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("GiB"); - ImGui::PopFont(); - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_mem_clock]){ - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", gpu_info.MemClock); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("MHz"); - ImGui::PopFont(); - } - } - if (params.enabled[OVERLAY_PARAM_ENABLED_ram]){ - ImGui::TableNextRow(); - ImGui::TextColored(data.colors.ram, "RAM"); - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%.1f", memused); - ImGui::SameLine(0,1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("GiB"); - ImGui::PopFont(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_fps]){ - ImGui::TableNextRow(); - ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%.0f", data.fps); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("FPS"); - ImGui::PopFont(); - ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%.1f", 1000 / data.fps); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("ms"); - ImGui::PopFont(); - } - if (!params.enabled[OVERLAY_PARAM_ENABLED_fps] && params.enabled[OVERLAY_PARAM_ENABLED_engine_version]){ - ImGui::TableNextRow(); - ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); - } - ImGui::EndTable(); - if (params.enabled[OVERLAY_PARAM_ENABLED_engine_version]){ - ImGui::PushFont(data.font1); - ImGui::Dummy(ImVec2(0, 8.0f)); - if (is_vulkan) { - if ((data.engineName == "DXVK" || data.engineName == "VKD3D")){ - ImGui::TextColored(data.colors.engine, - "%s/%d.%d.%d", data.engineVersion.c_str(), - data.version_vk.major, - data.version_vk.minor, - data.version_vk.patch); - } else { - ImGui::TextColored(data.colors.engine, - "%d.%d.%d", - data.version_vk.major, - data.version_vk.minor, - data.version_vk.patch); - } - } else { - ImGui::TextColored(data.colors.engine, - "%d.%d%s", data.version_gl.major, data.version_gl.minor, - data.version_gl.is_gles ? " ES" : ""); - } - // ImGui::SameLine(); - ImGui::PopFont(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_name] && !data.gpuName.empty()){ - ImGui::PushFont(data.font1); - ImGui::Dummy(ImVec2(0.0,5.0f)); - ImGui::TextColored(data.colors.engine, - "%s", data.gpuName.c_str()); - ImGui::PopFont(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_vulkan_driver] && !data.driverName.empty()){ - ImGui::PushFont(data.font1); - ImGui::Dummy(ImVec2(0.0,5.0f)); - ImGui::TextColored(data.colors.engine, - "%s", data.driverName.c_str()); - ImGui::PopFont(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_arch]){ - ImGui::PushFont(data.font1); - ImGui::Dummy(ImVec2(0.0,5.0f)); - ImGui::TextColored(data.colors.engine, "%s", "" MANGOHUD_ARCH); - ImGui::PopFont(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_wine]){ - if (!wineVersion.empty()){ - //ImGui::TextColored(data.colors.wine, "%s", "WINE"); - ImGui::PushFont(data.font1); - ImGui::Dummy(ImVec2(0.0,5.0f)); - ImGui::TextColored(data.colors.wine, "%s", wineVersion.c_str()); - ImGui::PopFont(); - } - } - if (params.enabled[OVERLAY_PARAM_ENABLED_frame_timing]){ - ImGui::Dummy(ImVec2(0.0f, params.font_size * params.font_scale / 2)); - ImGui::PushFont(data.font1); - ImGui::TextColored(data.colors.engine, "%s", "Frametime"); - ImGui::PopFont(); - - char hash[40]; - snprintf(hash, sizeof(hash), "##%s", overlay_param_names[OVERLAY_PARAM_ENABLED_frame_timing]); - data.stat_selector = OVERLAY_PLOTS_frame_timing; - data.time_dividor = 1000.0f; - - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); - double min_time = 0.0f; - double max_time = 50.0f; - if (params.enabled[OVERLAY_PARAM_ENABLED_histogram]){ - ImGui::PlotHistogram(hash, get_time_stat, &data, - ARRAY_SIZE(data.frames_stats), 0, - NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth() - params.font_size * params.font_scale * 2.2, 50)); - } else { - ImGui::PlotLines(hash, get_time_stat, &data, - ARRAY_SIZE(data.frames_stats), 0, - NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth() - params.font_size * params.font_scale * 2.2, 50)); - } - ImGui::PopStyleColor(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_frame_timing]){ - ImGui::SameLine(0,1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("%.1f ms", 1000 / data.fps); //frame_timing / 1000.f); - ImGui::PopFont(); - } - -#ifdef HAVE_DBUS - ImFont scaled_font = *data.font_text; - scaled_font.Scale = params.font_scale_media_player; - ImGui::PushFont(&scaled_font); - { - std::lock_guard lck(main_metadata.mtx); - render_mpris_metadata(params, main_metadata, frame_timing, true); - } - //render_mpris_metadata(params, generic_mpris, frame_timing, false); - ImGui::PopFont(); -#endif - - if(logger->is_active()) - 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((now - logger->last_log_end()) < 12s) - render_benchmark(data, params, window_size, height, now); - } -} - -static void compute_swapchain_display(struct swapchain_data *data) -{ - struct device_data *device_data = data->device; - struct instance_data *instance_data = device_data->instance; - - ImGui::SetCurrentContext(data->imgui_context); - ImGui::NewFrame(); - { - scoped_lock lk(instance_data->notifier.mutex); - position_layer(data->sw_stats, instance_data->params, data->window_size); - if(instance_data->params.render_mango) - render_mango(data->sw_stats, instance_data->params, data->window_size, true); - else - render_imgui(data->sw_stats, instance_data->params, data->window_size, true); - } - ImGui::PopStyleVar(3); - - ImGui::EndFrame(); - ImGui::Render(); - -} - -static uint32_t vk_memory_type(struct device_data *data, - VkMemoryPropertyFlags properties, - uint32_t type_bits) -{ - VkPhysicalDeviceMemoryProperties prop; - data->instance->vtable.GetPhysicalDeviceMemoryProperties(data->physical_device, &prop); - for (uint32_t i = 0; i < prop.memoryTypeCount; i++) - if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<device; - /* Descriptor set */ - VkDescriptorImageInfo desc_image[1] = {}; - desc_image[0].sampler = data->font_sampler; - desc_image[0].imageView = image_view; - desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - VkWriteDescriptorSet write_desc[1] = {}; - write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_desc[0].dstSet = set; - write_desc[0].descriptorCount = 1; - write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - write_desc[0].pImageInfo = desc_image; - device_data->vtable.UpdateDescriptorSets(device_data->device, 1, write_desc, 0, NULL); -} - -static void upload_image_data(struct device_data *device_data, - VkCommandBuffer command_buffer, - void *pixels, - VkDeviceSize upload_size, - uint32_t width, - uint32_t height, - VkBuffer& upload_buffer, - VkDeviceMemory& upload_buffer_mem, - VkImage image) -{ - /* Upload buffer */ - VkBufferCreateInfo buffer_info = {}; - buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_info.size = upload_size; - buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK(device_data->vtable.CreateBuffer(device_data->device, &buffer_info, - NULL, &upload_buffer)); - VkMemoryRequirements upload_buffer_req; - device_data->vtable.GetBufferMemoryRequirements(device_data->device, - upload_buffer, - &upload_buffer_req); - VkMemoryAllocateInfo upload_alloc_info = {}; - upload_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - upload_alloc_info.allocationSize = upload_buffer_req.size; - upload_alloc_info.memoryTypeIndex = vk_memory_type(device_data, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - upload_buffer_req.memoryTypeBits); - VK_CHECK(device_data->vtable.AllocateMemory(device_data->device, - &upload_alloc_info, - NULL, - &upload_buffer_mem)); - VK_CHECK(device_data->vtable.BindBufferMemory(device_data->device, - upload_buffer, - upload_buffer_mem, 0)); - - /* Upload to Buffer */ - char* map = NULL; - VK_CHECK(device_data->vtable.MapMemory(device_data->device, - upload_buffer_mem, - 0, upload_size, 0, (void**)(&map))); - memcpy(map, pixels, upload_size); - VkMappedMemoryRange range[1] = {}; - range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range[0].memory = upload_buffer_mem; - range[0].size = upload_size; - VK_CHECK(device_data->vtable.FlushMappedMemoryRanges(device_data->device, 1, range)); - device_data->vtable.UnmapMemory(device_data->device, - upload_buffer_mem); - - /* Copy buffer to image */ - VkImageMemoryBarrier copy_barrier[1] = {}; - copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - copy_barrier[0].image = image; - copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_barrier[0].subresourceRange.levelCount = 1; - copy_barrier[0].subresourceRange.layerCount = 1; - device_data->vtable.CmdPipelineBarrier(command_buffer, - VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, 0, NULL, 0, NULL, - 1, copy_barrier); - - VkBufferImageCopy region = {}; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = 1; - region.imageExtent.width = width; - region.imageExtent.height = height; - region.imageExtent.depth = 1; - device_data->vtable.CmdCopyBufferToImage(command_buffer, - upload_buffer, - image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, ®ion); - - VkImageMemoryBarrier use_barrier[1] = {}; - use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - use_barrier[0].image = image; - use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - use_barrier[0].subresourceRange.levelCount = 1; - use_barrier[0].subresourceRange.layerCount = 1; - device_data->vtable.CmdPipelineBarrier(command_buffer, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - 0, - 0, NULL, - 0, NULL, - 1, use_barrier); -} - -static VkDescriptorSet create_image_with_desc(struct swapchain_data *data, - uint32_t width, - uint32_t height, - VkFormat format, - VkImage& image, - VkDeviceMemory& image_mem, - VkImageView& image_view) -{ - struct device_data *device_data = data->device; - - VkImageCreateInfo image_info = {}; - image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_info.imageType = VK_IMAGE_TYPE_2D; - image_info.format = format; - image_info.extent.width = width; - image_info.extent.height = height; - image_info.extent.depth = 1; - image_info.mipLevels = 1; - image_info.arrayLayers = 1; - image_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VK_CHECK(device_data->vtable.CreateImage(device_data->device, &image_info, - NULL, &image)); - VkMemoryRequirements font_image_req; - device_data->vtable.GetImageMemoryRequirements(device_data->device, - image, &font_image_req); - VkMemoryAllocateInfo image_alloc_info = {}; - image_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - image_alloc_info.allocationSize = font_image_req.size; - image_alloc_info.memoryTypeIndex = vk_memory_type(device_data, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - font_image_req.memoryTypeBits); - VK_CHECK(device_data->vtable.AllocateMemory(device_data->device, &image_alloc_info, - NULL, &image_mem)); - VK_CHECK(device_data->vtable.BindImageMemory(device_data->device, - image, - image_mem, 0)); - - /* Font image view */ - VkImageViewCreateInfo view_info = {}; - view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - view_info.image = image; - view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - view_info.format = format; - view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - view_info.subresourceRange.levelCount = 1; - view_info.subresourceRange.layerCount = 1; - VK_CHECK(device_data->vtable.CreateImageView(device_data->device, &view_info, - NULL, &image_view)); - - VkDescriptorSet descriptor_set; - - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorPool = data->descriptor_pool; - alloc_info.descriptorSetCount = 1; - alloc_info.pSetLayouts = &data->descriptor_layout; - VK_CHECK(device_data->vtable.AllocateDescriptorSets(device_data->device, - &alloc_info, - &descriptor_set)); - - update_image_descriptor(data, image_view, descriptor_set); - return descriptor_set; -} - -static void ensure_swapchain_fonts(struct swapchain_data *data, - VkCommandBuffer command_buffer) -{ - struct device_data *device_data = data->device; - if (data->font_uploaded) - return; - - data->font_uploaded = true; - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); - size_t upload_size = width * height * 1 * sizeof(char); - upload_image_data(device_data, command_buffer, pixels, upload_size, width, height, data->upload_font_buffer, data->upload_font_buffer_mem, data->font_image); -} - -static void CreateOrResizeBuffer(struct device_data *data, - VkBuffer *buffer, - VkDeviceMemory *buffer_memory, - VkDeviceSize *buffer_size, - size_t new_size, VkBufferUsageFlagBits usage) -{ - if (*buffer != VK_NULL_HANDLE) - data->vtable.DestroyBuffer(data->device, *buffer, NULL); - if (*buffer_memory) - data->vtable.FreeMemory(data->device, *buffer_memory, NULL); - - VkBufferCreateInfo buffer_info = {}; - buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_info.size = new_size; - buffer_info.usage = usage; - buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK(data->vtable.CreateBuffer(data->device, &buffer_info, NULL, buffer)); - - VkMemoryRequirements req; - data->vtable.GetBufferMemoryRequirements(data->device, *buffer, &req); - VkMemoryAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.allocationSize = req.size; - alloc_info.memoryTypeIndex = - vk_memory_type(data, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); - VK_CHECK(data->vtable.AllocateMemory(data->device, &alloc_info, NULL, buffer_memory)); - - VK_CHECK(data->vtable.BindBufferMemory(data->device, *buffer, *buffer_memory, 0)); - *buffer_size = new_size; -} - -static struct overlay_draw *render_swapchain_display(struct swapchain_data *data, - struct queue_data *present_queue, - const VkSemaphore *wait_semaphores, - unsigned n_wait_semaphores, - unsigned image_index) -{ - ImDrawData* draw_data = ImGui::GetDrawData(); - if (draw_data->TotalVtxCount == 0) - return NULL; - - struct device_data *device_data = data->device; - struct overlay_draw *draw = get_overlay_draw(data); - - device_data->vtable.ResetCommandBuffer(draw->command_buffer, 0); - - VkRenderPassBeginInfo render_pass_info = {}; - render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - render_pass_info.renderPass = data->render_pass; - render_pass_info.framebuffer = data->framebuffers[image_index]; - render_pass_info.renderArea.extent.width = data->width; - render_pass_info.renderArea.extent.height = data->height; - - VkCommandBufferBeginInfo buffer_begin_info = {}; - buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - - device_data->vtable.BeginCommandBuffer(draw->command_buffer, &buffer_begin_info); - - ensure_swapchain_fonts(data, draw->command_buffer); - - /* Bounce the image to display back to color attachment layout for - * rendering on top of it. - */ - VkImageMemoryBarrier imb; - imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imb.pNext = nullptr; - imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imb.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - imb.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - imb.image = data->images[image_index]; - imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imb.subresourceRange.baseMipLevel = 0; - imb.subresourceRange.levelCount = 1; - imb.subresourceRange.baseArrayLayer = 0; - imb.subresourceRange.layerCount = 1; - imb.srcQueueFamilyIndex = present_queue->family_index; - imb.dstQueueFamilyIndex = device_data->graphic_queue->family_index; - device_data->vtable.CmdPipelineBarrier(draw->command_buffer, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - 0, /* dependency flags */ - 0, nullptr, /* memory barriers */ - 0, nullptr, /* buffer memory barriers */ - 1, &imb); /* image memory barriers */ - - device_data->vtable.CmdBeginRenderPass(draw->command_buffer, &render_pass_info, - VK_SUBPASS_CONTENTS_INLINE); - - /* Create/Resize vertex & index buffers */ - size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); - size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); - if (draw->vertex_buffer_size < vertex_size) { - CreateOrResizeBuffer(device_data, - &draw->vertex_buffer, - &draw->vertex_buffer_mem, - &draw->vertex_buffer_size, - vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - } - if (draw->index_buffer_size < index_size) { - CreateOrResizeBuffer(device_data, - &draw->index_buffer, - &draw->index_buffer_mem, - &draw->index_buffer_size, - index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); - } - - /* Upload vertex & index data */ - ImDrawVert* vtx_dst = NULL; - ImDrawIdx* idx_dst = NULL; - VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->vertex_buffer_mem, - 0, vertex_size, 0, (void**)(&vtx_dst))); - VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->index_buffer_mem, - 0, index_size, 0, (void**)(&idx_dst))); - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; - memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); - memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); - vtx_dst += cmd_list->VtxBuffer.Size; - idx_dst += cmd_list->IdxBuffer.Size; - } - VkMappedMemoryRange range[2] = {}; - range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range[0].memory = draw->vertex_buffer_mem; - range[0].size = VK_WHOLE_SIZE; - range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range[1].memory = draw->index_buffer_mem; - range[1].size = VK_WHOLE_SIZE; - VK_CHECK(device_data->vtable.FlushMappedMemoryRanges(device_data->device, 2, range)); - device_data->vtable.UnmapMemory(device_data->device, draw->vertex_buffer_mem); - device_data->vtable.UnmapMemory(device_data->device, draw->index_buffer_mem); - - /* Bind pipeline and descriptor sets */ - device_data->vtable.CmdBindPipeline(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, data->pipeline); - -#if 1 // disable if using >1 font textures - VkDescriptorSet desc_set[1] = { - //data->descriptor_set - reinterpret_cast(ImGui::GetIO().Fonts->Fonts[0]->ContainerAtlas->TexID) - }; - device_data->vtable.CmdBindDescriptorSets(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - data->pipeline_layout, 0, 1, desc_set, 0, NULL); -#endif - - /* Bind vertex & index buffers */ - VkBuffer vertex_buffers[1] = { draw->vertex_buffer }; - VkDeviceSize vertex_offset[1] = { 0 }; - device_data->vtable.CmdBindVertexBuffers(draw->command_buffer, 0, 1, vertex_buffers, vertex_offset); - device_data->vtable.CmdBindIndexBuffer(draw->command_buffer, draw->index_buffer, 0, VK_INDEX_TYPE_UINT16); - - /* Setup viewport */ - VkViewport viewport; - viewport.x = 0; - viewport.y = 0; - viewport.width = draw_data->DisplaySize.x; - viewport.height = draw_data->DisplaySize.y; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - device_data->vtable.CmdSetViewport(draw->command_buffer, 0, 1, &viewport); - - - /* Setup scale and translation through push constants : - * - * Our visible imgui space lies from draw_data->DisplayPos (top left) to - * draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin - * is typically (0,0) for single viewport apps. - */ - float scale[2]; - scale[0] = 2.0f / draw_data->DisplaySize.x; - scale[1] = 2.0f / draw_data->DisplaySize.y; - float translate[2]; - translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; - translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; - device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, - VK_SHADER_STAGE_VERTEX_BIT, - sizeof(float) * 0, sizeof(float) * 2, scale); - device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, - VK_SHADER_STAGE_VERTEX_BIT, - sizeof(float) * 2, sizeof(float) * 2, translate); - - // Render the command lists: - int vtx_offset = 0; - int idx_offset = 0; - ImVec2 display_pos = draw_data->DisplayPos; - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) - { - const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - // Apply scissor/clipping rectangle - // FIXME: We could clamp width/height based on clamped min/max values. - VkRect2D scissor; - scissor.offset.x = (int32_t)(pcmd->ClipRect.x - display_pos.x) > 0 ? (int32_t)(pcmd->ClipRect.x - display_pos.x) : 0; - scissor.offset.y = (int32_t)(pcmd->ClipRect.y - display_pos.y) > 0 ? (int32_t)(pcmd->ClipRect.y - display_pos.y) : 0; - scissor.extent.width = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x); - scissor.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // FIXME: Why +1 here? - device_data->vtable.CmdSetScissor(draw->command_buffer, 0, 1, &scissor); -#if 0 //enable if using >1 font textures or use texture array - VkDescriptorSet desc_set[1] = { (VkDescriptorSet)pcmd->TextureId }; - device_data->vtable.CmdBindDescriptorSets(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - data->pipeline_layout, 0, 1, desc_set, 0, NULL); -#endif - // Draw - device_data->vtable.CmdDrawIndexed(draw->command_buffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); - - idx_offset += pcmd->ElemCount; - } - vtx_offset += cmd_list->VtxBuffer.Size; - } - - device_data->vtable.CmdEndRenderPass(draw->command_buffer); - - if (device_data->graphic_queue->family_index != present_queue->family_index) - { - /* Transfer the image back to the present queue family - * image layout was already changed to present by the render pass - */ - imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imb.pNext = nullptr; - imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imb.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - imb.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - imb.image = data->images[image_index]; - imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imb.subresourceRange.baseMipLevel = 0; - imb.subresourceRange.levelCount = 1; - imb.subresourceRange.baseArrayLayer = 0; - imb.subresourceRange.layerCount = 1; - imb.srcQueueFamilyIndex = device_data->graphic_queue->family_index; - imb.dstQueueFamilyIndex = present_queue->family_index; - device_data->vtable.CmdPipelineBarrier(draw->command_buffer, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - 0, /* dependency flags */ - 0, nullptr, /* memory barriers */ - 0, nullptr, /* buffer memory barriers */ - 1, &imb); /* image memory barriers */ - } - - device_data->vtable.EndCommandBuffer(draw->command_buffer); - - /* When presenting on a different queue than where we're drawing the - * overlay *AND* when the application does not provide a semaphore to - * vkQueuePresent, insert our own cross engine synchronization - * semaphore. - */ - if (n_wait_semaphores == 0 && device_data->graphic_queue->queue != present_queue->queue) { - VkPipelineStageFlags stages_wait = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 0; - submit_info.pWaitDstStageMask = &stages_wait; - submit_info.waitSemaphoreCount = 0; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &draw->cross_engine_semaphore; - - device_data->vtable.QueueSubmit(present_queue->queue, 1, &submit_info, VK_NULL_HANDLE); - - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pWaitDstStageMask = &stages_wait; - submit_info.pCommandBuffers = &draw->command_buffer; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &draw->cross_engine_semaphore; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &draw->semaphore; - - device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence); - } else { - // wait in the fragment stage until the swapchain image is ready - std::vector stages_wait(n_wait_semaphores, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &draw->command_buffer; - submit_info.pWaitDstStageMask = stages_wait.data(); - submit_info.waitSemaphoreCount = n_wait_semaphores; - submit_info.pWaitSemaphores = wait_semaphores; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &draw->semaphore; - - device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence); - } - - return draw; -} - -static const uint32_t overlay_vert_spv[] = { -#include "overlay.vert.spv.h" -}; -static const uint32_t overlay_frag_spv[] = { -#include "overlay.frag.spv.h" -}; - -static void setup_swapchain_data_pipeline(struct swapchain_data *data) -{ - struct device_data *device_data = data->device; - VkShaderModule vert_module, frag_module; - - /* Create shader modules */ - VkShaderModuleCreateInfo vert_info = {}; - vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - vert_info.codeSize = sizeof(overlay_vert_spv); - vert_info.pCode = overlay_vert_spv; - VK_CHECK(device_data->vtable.CreateShaderModule(device_data->device, - &vert_info, NULL, &vert_module)); - VkShaderModuleCreateInfo frag_info = {}; - frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - frag_info.codeSize = sizeof(overlay_frag_spv); - frag_info.pCode = (uint32_t*)overlay_frag_spv; - VK_CHECK(device_data->vtable.CreateShaderModule(device_data->device, - &frag_info, NULL, &frag_module)); - - /* Font sampler */ - VkSamplerCreateInfo sampler_info = {}; - sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - sampler_info.magFilter = VK_FILTER_LINEAR; - sampler_info.minFilter = VK_FILTER_LINEAR; - sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.minLod = -1000; - sampler_info.maxLod = 1000; - sampler_info.maxAnisotropy = 1.0f; - VK_CHECK(device_data->vtable.CreateSampler(device_data->device, &sampler_info, - NULL, &data->font_sampler)); - - /* Descriptor pool */ - VkDescriptorPoolSize sampler_pool_size = {}; - sampler_pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - sampler_pool_size.descriptorCount = 1; - VkDescriptorPoolCreateInfo desc_pool_info = {}; - desc_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - desc_pool_info.maxSets = 1; - desc_pool_info.poolSizeCount = 1; - desc_pool_info.pPoolSizes = &sampler_pool_size; - VK_CHECK(device_data->vtable.CreateDescriptorPool(device_data->device, - &desc_pool_info, - NULL, &data->descriptor_pool)); - - /* Descriptor layout */ - VkSampler sampler[1] = { data->font_sampler }; - VkDescriptorSetLayoutBinding binding[1] = {}; - binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - binding[0].descriptorCount = 1; - binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - binding[0].pImmutableSamplers = sampler; - VkDescriptorSetLayoutCreateInfo set_layout_info = {}; - set_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - set_layout_info.bindingCount = 1; - set_layout_info.pBindings = binding; - VK_CHECK(device_data->vtable.CreateDescriptorSetLayout(device_data->device, - &set_layout_info, - NULL, &data->descriptor_layout)); - - /* Descriptor set */ -/* - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorPool = data->descriptor_pool; - alloc_info.descriptorSetCount = 1; - alloc_info.pSetLayouts = &data->descriptor_layout; - VK_CHECK(device_data->vtable.AllocateDescriptorSets(device_data->device, - &alloc_info, - &data->descriptor_set)); -*/ - - /* Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full - * 3d projection matrix - */ - VkPushConstantRange push_constants[1] = {}; - push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - push_constants[0].offset = sizeof(float) * 0; - push_constants[0].size = sizeof(float) * 4; - VkPipelineLayoutCreateInfo layout_info = {}; - layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - layout_info.setLayoutCount = 1; - layout_info.pSetLayouts = &data->descriptor_layout; - layout_info.pushConstantRangeCount = 1; - layout_info.pPushConstantRanges = push_constants; - VK_CHECK(device_data->vtable.CreatePipelineLayout(device_data->device, - &layout_info, - NULL, &data->pipeline_layout)); - - VkPipelineShaderStageCreateInfo stage[2] = {}; - stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - stage[0].module = vert_module; - stage[0].pName = "main"; - stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - stage[1].module = frag_module; - stage[1].pName = "main"; - - VkVertexInputBindingDescription binding_desc[1] = {}; - binding_desc[0].stride = sizeof(ImDrawVert); - binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - VkVertexInputAttributeDescription attribute_desc[3] = {}; - attribute_desc[0].location = 0; - attribute_desc[0].binding = binding_desc[0].binding; - attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; - attribute_desc[0].offset = IM_OFFSETOF(ImDrawVert, pos); - attribute_desc[1].location = 1; - attribute_desc[1].binding = binding_desc[0].binding; - attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; - attribute_desc[1].offset = IM_OFFSETOF(ImDrawVert, uv); - attribute_desc[2].location = 2; - attribute_desc[2].binding = binding_desc[0].binding; - attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; - attribute_desc[2].offset = IM_OFFSETOF(ImDrawVert, col); - - VkPipelineVertexInputStateCreateInfo vertex_info = {}; - vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertex_info.vertexBindingDescriptionCount = 1; - vertex_info.pVertexBindingDescriptions = binding_desc; - vertex_info.vertexAttributeDescriptionCount = 3; - vertex_info.pVertexAttributeDescriptions = attribute_desc; - - VkPipelineInputAssemblyStateCreateInfo ia_info = {}; - ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - - VkPipelineViewportStateCreateInfo viewport_info = {}; - viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewport_info.viewportCount = 1; - viewport_info.scissorCount = 1; - - VkPipelineRasterizationStateCreateInfo raster_info = {}; - raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - raster_info.polygonMode = VK_POLYGON_MODE_FILL; - raster_info.cullMode = VK_CULL_MODE_NONE; - raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - raster_info.lineWidth = 1.0f; - - VkPipelineMultisampleStateCreateInfo ms_info = {}; - ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - - VkPipelineColorBlendAttachmentState color_attachment[1] = {}; - color_attachment[0].blendEnable = VK_TRUE; - color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; - color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; - color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | - VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - - VkPipelineDepthStencilStateCreateInfo depth_info = {}; - depth_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - - VkPipelineColorBlendStateCreateInfo blend_info = {}; - blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - blend_info.attachmentCount = 1; - blend_info.pAttachments = color_attachment; - - VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamic_state = {}; - dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states); - dynamic_state.pDynamicStates = dynamic_states; - - VkGraphicsPipelineCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - info.flags = 0; - info.stageCount = 2; - info.pStages = stage; - info.pVertexInputState = &vertex_info; - info.pInputAssemblyState = &ia_info; - info.pViewportState = &viewport_info; - info.pRasterizationState = &raster_info; - info.pMultisampleState = &ms_info; - info.pDepthStencilState = &depth_info; - info.pColorBlendState = &blend_info; - info.pDynamicState = &dynamic_state; - info.layout = data->pipeline_layout; - info.renderPass = data->render_pass; - VK_CHECK( - device_data->vtable.CreateGraphicsPipelines(device_data->device, VK_NULL_HANDLE, - 1, &info, - NULL, &data->pipeline)); - - device_data->vtable.DestroyShaderModule(device_data->device, vert_module, NULL); - device_data->vtable.DestroyShaderModule(device_data->device, frag_module, NULL); - - create_fonts(device_data->instance->params, data->sw_stats.font1, data->sw_stats.font_text); - - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - - // upload default font to VkImage - io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); - io.Fonts->TexID = (ImTextureID)create_image_with_desc(data, width, height, VK_FORMAT_R8_UNORM, data->font_image, data->font_mem, data->font_image_view); -#ifndef NDEBUG - std::cerr << "MANGOHUD: Default font tex size: " << width << "x" << height << "px (" << (width*height*1) << " bytes)" << "\n"; -#endif - -// if (data->descriptor_set) -// update_image_descriptor(data, data->font_image_view[0], data->descriptor_set); -} - -// Cut from https://github.com/ocornut/imgui/pull/2943 -// Probably move to ImGui -float SRGBToLinear(float in) -{ - if (in <= 0.04045f) - return in / 12.92f; - else - return powf((in + 0.055f) / 1.055f, 2.4f); -} - -float LinearToSRGB(float in) -{ - if (in <= 0.0031308f) - return in * 12.92f; - else - return 1.055f * powf(in, 1.0f / 2.4f) - 0.055f; -} - -ImVec4 SRGBToLinear(ImVec4 col) -{ - col.x = SRGBToLinear(col.x); - col.y = SRGBToLinear(col.y); - col.z = SRGBToLinear(col.z); - // Alpha component is already linear - - return col; -} - -ImVec4 LinearToSRGB(ImVec4 col) -{ - col.x = LinearToSRGB(col.x); - col.y = LinearToSRGB(col.y); - col.z = LinearToSRGB(col.z); - // Alpha component is already linear - - return col; -} - -void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overlay_params& params) -{ - auto convert = [&do_conv](unsigned color) -> ImVec4 { - ImVec4 fc = ImGui::ColorConvertU32ToFloat4(color); - if (do_conv) - return SRGBToLinear(fc); - return fc; - }; - - sw_stats.colors.cpu = convert(params.cpu_color); - sw_stats.colors.gpu = convert(params.gpu_color); - sw_stats.colors.vram = convert(params.vram_color); - sw_stats.colors.ram = convert(params.ram_color); - sw_stats.colors.engine = convert(params.engine_color); - sw_stats.colors.io = convert(params.io_color); - sw_stats.colors.frametime = convert(params.frametime_color); - sw_stats.colors.background = convert(params.background_color); - sw_stats.colors.text = convert(params.text_color); - sw_stats.colors.media_player = convert(params.media_player_color); - sw_stats.colors.wine = convert(params.wine_color); - - ImGuiStyle& style = ImGui::GetStyle(); - style.Colors[ImGuiCol_PlotLines] = convert(params.frametime_color); - style.Colors[ImGuiCol_PlotHistogram] = convert(params.frametime_color); - style.Colors[ImGuiCol_WindowBg] = convert(params.background_color); - style.Colors[ImGuiCol_Text] = convert(params.text_color); - style.CellPadding.y = -2; -} - -// TODO probably needs colorspace check too -static void convert_colors_vk(VkFormat format, struct swapchain_stats& sw_stats, struct overlay_params& params) -{ - bool do_conv = false; - switch (format) { - case VK_FORMAT_R8_SRGB: - case VK_FORMAT_R8G8_SRGB: - case VK_FORMAT_R8G8B8_SRGB: - case VK_FORMAT_B8G8R8_SRGB: - case VK_FORMAT_R8G8B8A8_SRGB: - case VK_FORMAT_B8G8R8A8_SRGB: - case VK_FORMAT_A8B8G8R8_SRGB_PACK32: - case VK_FORMAT_BC1_RGB_SRGB_BLOCK: - case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: - case VK_FORMAT_BC2_SRGB_BLOCK: - case VK_FORMAT_BC3_SRGB_BLOCK: - case VK_FORMAT_BC7_SRGB_BLOCK: - case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: - case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: - case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: - case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: - case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: - case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: - case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: - case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: - case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: - case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: - case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: - case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: - case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: - case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: - case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: - case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: - case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: - case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: - case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: - case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: - case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: - do_conv = true; - break; - default: - break; - } - - convert_colors(do_conv, sw_stats, params); -} - -static void setup_swapchain_data(struct swapchain_data *data, - const VkSwapchainCreateInfoKHR *pCreateInfo) -{ - struct device_data *device_data = data->device; - data->width = pCreateInfo->imageExtent.width; - data->height = pCreateInfo->imageExtent.height; - data->format = pCreateInfo->imageFormat; - - data->imgui_context = ImGui::CreateContext(); - ImGui::SetCurrentContext(data->imgui_context); - - ImGui::GetIO().IniFilename = NULL; - ImGui::GetIO().DisplaySize = ImVec2((float)data->width, (float)data->height); - convert_colors_vk(pCreateInfo->imageFormat, data->sw_stats, device_data->instance->params); - - /* Render pass */ - VkAttachmentDescription attachment_desc = {}; - attachment_desc.format = pCreateInfo->imageFormat; - attachment_desc.samples = VK_SAMPLE_COUNT_1_BIT; - attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachment_desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - attachment_desc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - VkAttachmentReference color_attachment = {}; - color_attachment.attachment = 0; - color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &color_attachment; - VkSubpassDependency dependency = {}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - VkRenderPassCreateInfo render_pass_info = {}; - render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - render_pass_info.attachmentCount = 1; - render_pass_info.pAttachments = &attachment_desc; - render_pass_info.subpassCount = 1; - render_pass_info.pSubpasses = &subpass; - render_pass_info.dependencyCount = 1; - render_pass_info.pDependencies = &dependency; - VK_CHECK(device_data->vtable.CreateRenderPass(device_data->device, - &render_pass_info, - NULL, &data->render_pass)); - - setup_swapchain_data_pipeline(data); - - uint32_t n_images = 0; - VK_CHECK(device_data->vtable.GetSwapchainImagesKHR(device_data->device, - data->swapchain, - &n_images, - NULL)); - - data->images.resize(n_images); - data->image_views.resize(n_images); - data->framebuffers.resize(n_images); - - VK_CHECK(device_data->vtable.GetSwapchainImagesKHR(device_data->device, - data->swapchain, - &n_images, - data->images.data())); - - - if (n_images != data->images.size()) { - data->images.resize(n_images); - data->image_views.resize(n_images); - data->framebuffers.resize(n_images); - } - - /* Image views */ - VkImageViewCreateInfo view_info = {}; - view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - view_info.format = pCreateInfo->imageFormat; - view_info.components.r = VK_COMPONENT_SWIZZLE_R; - view_info.components.g = VK_COMPONENT_SWIZZLE_G; - view_info.components.b = VK_COMPONENT_SWIZZLE_B; - view_info.components.a = VK_COMPONENT_SWIZZLE_A; - view_info.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - for (size_t i = 0; i < data->images.size(); i++) { - view_info.image = data->images[i]; - VK_CHECK(device_data->vtable.CreateImageView(device_data->device, - &view_info, NULL, - &data->image_views[i])); - } - - /* Framebuffers */ - VkImageView attachment[1]; - VkFramebufferCreateInfo fb_info = {}; - fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fb_info.renderPass = data->render_pass; - fb_info.attachmentCount = 1; - fb_info.pAttachments = attachment; - fb_info.width = data->width; - fb_info.height = data->height; - fb_info.layers = 1; - for (size_t i = 0; i < data->image_views.size(); i++) { - attachment[0] = data->image_views[i]; - VK_CHECK(device_data->vtable.CreateFramebuffer(device_data->device, &fb_info, - NULL, &data->framebuffers[i])); - } - - /* Command buffer pool */ - VkCommandPoolCreateInfo cmd_buffer_pool_info = {}; - cmd_buffer_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmd_buffer_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - cmd_buffer_pool_info.queueFamilyIndex = device_data->graphic_queue->family_index; - VK_CHECK(device_data->vtable.CreateCommandPool(device_data->device, - &cmd_buffer_pool_info, - NULL, &data->command_pool)); -} - -static void shutdown_swapchain_data(struct swapchain_data *data) -{ - struct device_data *device_data = data->device; - - for (auto draw : data->draws) { - device_data->vtable.DestroySemaphore(device_data->device, draw->cross_engine_semaphore, NULL); - device_data->vtable.DestroySemaphore(device_data->device, draw->semaphore, NULL); - device_data->vtable.DestroyFence(device_data->device, draw->fence, NULL); - device_data->vtable.DestroyBuffer(device_data->device, draw->vertex_buffer, NULL); - device_data->vtable.DestroyBuffer(device_data->device, draw->index_buffer, NULL); - device_data->vtable.FreeMemory(device_data->device, draw->vertex_buffer_mem, NULL); - device_data->vtable.FreeMemory(device_data->device, draw->index_buffer_mem, NULL); - delete draw; - } - - for (size_t i = 0; i < data->images.size(); i++) { - device_data->vtable.DestroyImageView(device_data->device, data->image_views[i], NULL); - device_data->vtable.DestroyFramebuffer(device_data->device, data->framebuffers[i], NULL); - } - - device_data->vtable.DestroyRenderPass(device_data->device, data->render_pass, NULL); - - device_data->vtable.DestroyCommandPool(device_data->device, data->command_pool, NULL); - - device_data->vtable.DestroyPipeline(device_data->device, data->pipeline, NULL); - device_data->vtable.DestroyPipelineLayout(device_data->device, data->pipeline_layout, NULL); - - device_data->vtable.DestroyDescriptorPool(device_data->device, - data->descriptor_pool, NULL); - device_data->vtable.DestroyDescriptorSetLayout(device_data->device, - data->descriptor_layout, NULL); - - device_data->vtable.DestroySampler(device_data->device, data->font_sampler, NULL); - device_data->vtable.DestroyImageView(device_data->device, data->font_image_view, NULL); - device_data->vtable.DestroyImage(device_data->device, data->font_image, NULL); - device_data->vtable.FreeMemory(device_data->device, data->font_mem, NULL); - - device_data->vtable.DestroyBuffer(device_data->device, data->upload_font_buffer, NULL); - device_data->vtable.FreeMemory(device_data->device, data->upload_font_buffer_mem, NULL); - - ImGui::DestroyContext(data->imgui_context); -} - -static struct overlay_draw *before_present(struct swapchain_data *swapchain_data, - struct queue_data *present_queue, - const VkSemaphore *wait_semaphores, - unsigned n_wait_semaphores, - unsigned imageIndex) -{ - struct overlay_draw *draw = NULL; - - snapshot_swapchain_frame(swapchain_data); - - if (swapchain_data->sw_stats.n_frames > 0) { - compute_swapchain_display(swapchain_data); - draw = render_swapchain_display(swapchain_data, present_queue, - wait_semaphores, n_wait_semaphores, - imageIndex); - } - - return draw; -} - -void get_device_name(int32_t vendorID, int32_t deviceID, struct swapchain_stats& sw_stats) -{ - string desc = pci_ids[vendorID].second[deviceID].desc; - size_t position = desc.find("["); - if (position != std::string::npos) { - desc = desc.substr(position); - string chars = "[]"; - for (char c: chars) - desc.erase(remove(desc.begin(), desc.end(), c), desc.end()); - } - sw_stats.gpuName = desc; - trim(sw_stats.gpuName); -} - -static VkResult overlay_CreateSwapchainKHR( - VkDevice device, - const VkSwapchainCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSwapchainKHR* pSwapchain) -{ - struct device_data *device_data = FIND(struct device_data, device); - array modes = {VK_PRESENT_MODE_FIFO_RELAXED_KHR, - VK_PRESENT_MODE_IMMEDIATE_KHR, - VK_PRESENT_MODE_MAILBOX_KHR, - VK_PRESENT_MODE_FIFO_KHR}; - - if (device_data->instance->params.vsync < 4) - const_cast (pCreateInfo)->presentMode = modes[device_data->instance->params.vsync]; - - VkResult result = device_data->vtable.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); - if (result != VK_SUCCESS) return result; - struct swapchain_data *swapchain_data = new_swapchain_data(*pSwapchain, device_data); - setup_swapchain_data(swapchain_data, pCreateInfo); - - const VkPhysicalDeviceProperties& prop = device_data->properties; - swapchain_data->sw_stats.version_vk.major = VK_VERSION_MAJOR(prop.apiVersion); - swapchain_data->sw_stats.version_vk.minor = VK_VERSION_MINOR(prop.apiVersion); - swapchain_data->sw_stats.version_vk.patch = VK_VERSION_PATCH(prop.apiVersion); - swapchain_data->sw_stats.engineName = device_data->instance->engineName; - swapchain_data->sw_stats.engineVersion = device_data->instance->engineVersion; - - std::stringstream ss; -// ss << prop.deviceName; - if (prop.vendorID == 0x10de) { - ss << " " << ((prop.driverVersion >> 22) & 0x3ff); - ss << "." << ((prop.driverVersion >> 14) & 0x0ff); - ss << "." << std::setw(2) << std::setfill('0') << ((prop.driverVersion >> 6) & 0x0ff); -#ifdef _WIN32 - } else if (prop.vendorID == 0x8086) { - ss << " " << (prop.driverVersion >> 14); - ss << "." << (prop.driverVersion & 0x3fff); - } -#endif - } else { - ss << " " << VK_VERSION_MAJOR(prop.driverVersion); - ss << "." << VK_VERSION_MINOR(prop.driverVersion); - ss << "." << VK_VERSION_PATCH(prop.driverVersion); - } - std::string driverVersion = ss.str(); - - std::string deviceName = prop.deviceName; - get_device_name(prop.vendorID, prop.deviceID, swapchain_data->sw_stats); - if(driverProps.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY){ - swapchain_data->sw_stats.driverName = "NVIDIA"; - } - if(driverProps.driverID == VK_DRIVER_ID_AMD_PROPRIETARY) - swapchain_data->sw_stats.driverName = "AMDGPU-PRO"; - if(driverProps.driverID == VK_DRIVER_ID_AMD_OPEN_SOURCE) - swapchain_data->sw_stats.driverName = "AMDVLK"; - if(driverProps.driverID == VK_DRIVER_ID_MESA_RADV){ - if(deviceName.find("ACO") != std::string::npos){ - swapchain_data->sw_stats.driverName = "RADV/ACO"; - } else { - swapchain_data->sw_stats.driverName = "RADV"; - } - } - - if (!swapchain_data->sw_stats.driverName.empty()) - swapchain_data->sw_stats.driverName += driverVersion; - else - swapchain_data->sw_stats.driverName = prop.deviceName + driverVersion; - - return result; -} - -static void overlay_DestroySwapchainKHR( - VkDevice device, - VkSwapchainKHR swapchain, - const VkAllocationCallbacks* pAllocator) -{ - struct swapchain_data *swapchain_data = - FIND(struct swapchain_data, swapchain); - - shutdown_swapchain_data(swapchain_data); - swapchain_data->device->vtable.DestroySwapchainKHR(device, swapchain, pAllocator); - destroy_swapchain_data(swapchain_data); -} - -void FpsLimiter(struct fps_limit& stats){ - stats.sleepTime = stats.targetFrameTime - (stats.frameStart - stats.frameEnd); - if (stats.sleepTime > stats.frameOverhead) { - 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 = Clock::duration(0); - } -} - -static VkResult overlay_QueuePresentKHR( - VkQueue queue, - const VkPresentInfoKHR* pPresentInfo) -{ - struct queue_data *queue_data = FIND(struct queue_data, queue); - - /* Otherwise we need to add our overlay drawing semaphore to the list of - * semaphores to wait on. If we don't do that the presented picture might - * be have incomplete overlay drawings. - */ - VkResult result = VK_SUCCESS; - for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { - VkSwapchainKHR swapchain = pPresentInfo->pSwapchains[i]; - struct swapchain_data *swapchain_data = - FIND(struct swapchain_data, swapchain); - - uint32_t image_index = pPresentInfo->pImageIndices[i]; - - VkPresentInfoKHR present_info = *pPresentInfo; - present_info.swapchainCount = 1; - present_info.pSwapchains = &swapchain; - present_info.pImageIndices = &image_index; - - struct overlay_draw *draw = before_present(swapchain_data, - queue_data, - pPresentInfo->pWaitSemaphores, - pPresentInfo->waitSemaphoreCount, - image_index); - - /* Because the submission of the overlay draw waits on the semaphores - * handed for present, we don't need to have this present operation - * wait on them as well, we can just wait on the overlay submission - * semaphore. - */ - if (draw) { - present_info.pWaitSemaphores = &draw->semaphore; - present_info.waitSemaphoreCount = 1; - } - - VkResult chain_result = queue_data->device->vtable.QueuePresentKHR(queue, &present_info); - if (pPresentInfo->pResults) - pPresentInfo->pResults[i] = chain_result; - if (chain_result != VK_SUCCESS && result == VK_SUCCESS) - result = chain_result; - } - - 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 = Clock::now(); - } - - return result; -} - -static VkResult overlay_BeginCommandBuffer( - VkCommandBuffer commandBuffer, - const VkCommandBufferBeginInfo* pBeginInfo) -{ - struct command_buffer_data *cmd_buffer_data = - FIND(struct command_buffer_data, commandBuffer); - struct device_data *device_data = cmd_buffer_data->device; - - /* Otherwise record a begin query as first command. */ - VkResult result = device_data->vtable.BeginCommandBuffer(commandBuffer, pBeginInfo); - - return result; -} - -static VkResult overlay_EndCommandBuffer( - VkCommandBuffer commandBuffer) -{ - struct command_buffer_data *cmd_buffer_data = - FIND(struct command_buffer_data, commandBuffer); - struct device_data *device_data = cmd_buffer_data->device; - - return device_data->vtable.EndCommandBuffer(commandBuffer); -} - -static VkResult overlay_ResetCommandBuffer( - VkCommandBuffer commandBuffer, - VkCommandBufferResetFlags flags) -{ - struct command_buffer_data *cmd_buffer_data = - FIND(struct command_buffer_data, commandBuffer); - struct device_data *device_data = cmd_buffer_data->device; - - return device_data->vtable.ResetCommandBuffer(commandBuffer, flags); -} - -static void overlay_CmdExecuteCommands( - VkCommandBuffer commandBuffer, - uint32_t commandBufferCount, - const VkCommandBuffer* pCommandBuffers) -{ - struct command_buffer_data *cmd_buffer_data = - FIND(struct command_buffer_data, commandBuffer); - struct device_data *device_data = cmd_buffer_data->device; - - device_data->vtable.CmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers); -} - -static VkResult overlay_AllocateCommandBuffers( - VkDevice device, - const VkCommandBufferAllocateInfo* pAllocateInfo, - VkCommandBuffer* pCommandBuffers) -{ - struct device_data *device_data = FIND(struct device_data, device); - VkResult result = - device_data->vtable.AllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers); - if (result != VK_SUCCESS) - return result; - - for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) { - new_command_buffer_data(pCommandBuffers[i], pAllocateInfo->level, - device_data); - } - - return result; -} - -static void overlay_FreeCommandBuffers( - VkDevice device, - VkCommandPool commandPool, - uint32_t commandBufferCount, - const VkCommandBuffer* pCommandBuffers) -{ - struct device_data *device_data = FIND(struct device_data, device); - for (uint32_t i = 0; i < commandBufferCount; i++) { - struct command_buffer_data *cmd_buffer_data = - FIND(struct command_buffer_data, pCommandBuffers[i]); - - /* It is legal to free a NULL command buffer*/ - if (!cmd_buffer_data) - continue; - - destroy_command_buffer_data(cmd_buffer_data); - } - - device_data->vtable.FreeCommandBuffers(device, commandPool, - commandBufferCount, pCommandBuffers); -} - -static VkResult overlay_QueueSubmit( - VkQueue queue, - uint32_t submitCount, - const VkSubmitInfo* pSubmits, - VkFence fence) -{ - struct queue_data *queue_data = FIND(struct queue_data, queue); - struct device_data *device_data = queue_data->device; - - return device_data->vtable.QueueSubmit(queue, submitCount, pSubmits, fence); -} - -static VkResult overlay_CreateDevice( - VkPhysicalDevice physicalDevice, - const VkDeviceCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkDevice* pDevice) -{ - struct instance_data *instance_data = - FIND(struct instance_data, physicalDevice); - VkLayerDeviceCreateInfo *chain_info = - get_device_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); - - assert(chain_info->u.pLayerInfo); - PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; - PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; - PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice"); - if (fpCreateDevice == NULL) { - return VK_ERROR_INITIALIZATION_FAILED; - } - - // Advance the link info for the next element on the chain - chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; - - VkPhysicalDeviceFeatures device_features = {}; - VkDeviceCreateInfo device_info = *pCreateInfo; - - std::vector enabled_extensions(device_info.ppEnabledExtensionNames, - device_info.ppEnabledExtensionNames + - device_info.enabledExtensionCount); - - uint32_t extension_count; - instance_data->vtable.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extension_count, nullptr); - - std::vector available_extensions(extension_count); - instance_data->vtable.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extension_count, available_extensions.data()); - - - bool can_get_driver_info = instance_data->api_version < VK_API_VERSION_1_1 ? false : true; - - // VK_KHR_driver_properties became core in 1.2 - if (instance_data->api_version < VK_API_VERSION_1_2 && can_get_driver_info) { - for (auto& extension : available_extensions) { - if (extension.extensionName == std::string(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) { - for (auto& enabled : enabled_extensions) { - if (enabled == std::string(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) - goto DONT; - } - enabled_extensions.push_back(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME); - DONT: - goto FOUND; - } - } - can_get_driver_info = false; - FOUND:; - } - - device_info.enabledExtensionCount = enabled_extensions.size(); - device_info.ppEnabledExtensionNames = enabled_extensions.data(); - - if (pCreateInfo->pEnabledFeatures) - device_features = *(pCreateInfo->pEnabledFeatures); - device_info.pEnabledFeatures = &device_features; - - - VkResult result = fpCreateDevice(physicalDevice, &device_info, pAllocator, pDevice); - if (result != VK_SUCCESS) return result; - - struct device_data *device_data = new_device_data(*pDevice, instance_data); - device_data->physical_device = physicalDevice; - vk_load_device_commands(*pDevice, fpGetDeviceProcAddr, &device_data->vtable); - - instance_data->vtable.GetPhysicalDeviceProperties(device_data->physical_device, - &device_data->properties); - - VkLayerDeviceCreateInfo *load_data_info = - get_device_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK); - device_data->set_device_loader_data = load_data_info->u.pfnSetDeviceLoaderData; - - driverProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; - driverProps.pNext = nullptr; - if (can_get_driver_info) { - VkPhysicalDeviceProperties2 deviceProps = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, &driverProps}; - instance_data->vtable.GetPhysicalDeviceProperties2(device_data->physical_device, &deviceProps); - } - - if (!is_blacklisted()) { - device_map_queues(device_data, pCreateInfo); - - init_gpu_stats(device_data->properties.vendorID, instance_data->params); - init_system_info(); - } - - return result; -} - -static void overlay_DestroyDevice( - VkDevice device, - const VkAllocationCallbacks* pAllocator) -{ - struct device_data *device_data = FIND(struct device_data, device); - if (!is_blacklisted()) - device_unmap_queues(device_data); - device_data->vtable.DestroyDevice(device, pAllocator); - destroy_device_data(device_data); -} - -static VkResult overlay_CreateInstance( - const VkInstanceCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkInstance* pInstance) -{ - VkLayerInstanceCreateInfo *chain_info = - get_instance_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); - - std::string engineName, engineVersion; - if (!is_blacklisted(true)) { - const char* pEngineName = nullptr; - if (pCreateInfo->pApplicationInfo) - pEngineName = pCreateInfo->pApplicationInfo->pEngineName; - if (pEngineName) - engineName = pEngineName; - if (engineName == "DXVK" || engineName == "vkd3d") { - int engineVer = pCreateInfo->pApplicationInfo->engineVersion; - engineVersion = to_string(VK_VERSION_MAJOR(engineVer)) + "." + to_string(VK_VERSION_MINOR(engineVer)) + "." + to_string(VK_VERSION_PATCH(engineVer)); - } - - if (engineName != "DXVK" && engineName != "vkd3d" && engineName != "Feral3D") - engineName = "VULKAN"; - - if (engineName == "vkd3d") - engineName = "VKD3D"; - } - - assert(chain_info->u.pLayerInfo); - PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = - chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; - PFN_vkCreateInstance fpCreateInstance = - (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance"); - if (fpCreateInstance == NULL) { - return VK_ERROR_INITIALIZATION_FAILED; - } - - // Advance the link info for the next element on the chain - chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; - - - VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); - if (result != VK_SUCCESS) return result; - - struct instance_data *instance_data = new_instance_data(*pInstance); - vk_load_instance_commands(instance_data->instance, - fpGetInstanceProcAddr, - &instance_data->vtable); - instance_data_map_physical_devices(instance_data, true); - - if (!is_blacklisted()) { - parse_overlay_config(&instance_data->params, getenv("MANGOHUD_CONFIG")); - instance_data->notifier.params = &instance_data->params; - start_notifier(instance_data->notifier); - - init_cpu_stats(instance_data->params); - - // Adjust height for DXVK/VKD3D version number - if (engineName == "DXVK" || engineName == "VKD3D"){ - if (instance_data->params.font_size){ - instance_data->params.height += instance_data->params.font_size * instance_data->params.font_scale / 2; - } else { - instance_data->params.height += 24 * instance_data->params.font_scale / 2; - } - } - - instance_data->engineName = engineName; - instance_data->engineVersion = engineVersion; - } - - instance_data->api_version = pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0; - - return result; -} - -static void overlay_DestroyInstance( - VkInstance instance, - const VkAllocationCallbacks* pAllocator) -{ - struct instance_data *instance_data = FIND(struct instance_data, instance); - instance_data_map_physical_devices(instance_data, false); - instance_data->vtable.DestroyInstance(instance, pAllocator); - if (!is_blacklisted()) - stop_notifier(instance_data->notifier); - destroy_instance_data(instance_data); -} - -extern "C" VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL overlay_GetDeviceProcAddr(VkDevice dev, - const char *funcName); -static const struct { - const char *name; - void *ptr; -} name_to_funcptr_map[] = { - { "vkGetDeviceProcAddr", (void *) overlay_GetDeviceProcAddr }, -#define ADD_HOOK(fn) { "vk" # fn, (void *) overlay_ ## fn } -#define ADD_ALIAS_HOOK(alias, fn) { "vk" # alias, (void *) overlay_ ## fn } - ADD_HOOK(AllocateCommandBuffers), - ADD_HOOK(FreeCommandBuffers), - ADD_HOOK(ResetCommandBuffer), - ADD_HOOK(BeginCommandBuffer), - ADD_HOOK(EndCommandBuffer), - ADD_HOOK(CmdExecuteCommands), - - ADD_HOOK(CreateSwapchainKHR), - ADD_HOOK(QueuePresentKHR), - ADD_HOOK(DestroySwapchainKHR), - - ADD_HOOK(QueueSubmit), - - ADD_HOOK(CreateDevice), - ADD_HOOK(DestroyDevice), - - ADD_HOOK(CreateInstance), - ADD_HOOK(DestroyInstance), -#undef ADD_HOOK -}; - -static void *find_ptr(const char *name) -{ - std::string f(name); - - if (is_blacklisted() && (f != "vkCreateInstance" && f != "vkDestroyInstance" && f != "vkCreateDevice" && f != "vkDestroyDevice")) - { - return NULL; - } - - for (uint32_t i = 0; i < ARRAY_SIZE(name_to_funcptr_map); i++) { - if (strcmp(name, name_to_funcptr_map[i].name) == 0) - return name_to_funcptr_map[i].ptr; - } - - return NULL; -} - -extern "C" VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL overlay_GetDeviceProcAddr(VkDevice dev, - const char *funcName) -{ - void *ptr = find_ptr(funcName); - if (ptr) return reinterpret_cast(ptr); - - if (dev == NULL) return NULL; - - struct device_data *device_data = FIND(struct device_data, dev); - if (device_data->vtable.GetDeviceProcAddr == NULL) return NULL; - return device_data->vtable.GetDeviceProcAddr(dev, funcName); -} - -extern "C" VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL overlay_GetInstanceProcAddr(VkInstance instance, - const char *funcName) -{ - void *ptr = find_ptr(funcName); - if (ptr) return reinterpret_cast(ptr); - - if (instance == NULL) return NULL; - - struct instance_data *instance_data = FIND(struct instance_data, instance); - if (instance_data->vtable.GetInstanceProcAddr == NULL) return NULL; - return instance_data->vtable.GetInstanceProcAddr(instance, funcName); -} +} \ No newline at end of file diff --git a/src/overlay.h b/src/overlay.h index ee32b5f0..91e30abc 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -83,6 +83,7 @@ extern struct benchmark_stats benchmark; void position_layer(struct swapchain_stats& data, struct overlay_params& params, ImVec2 window_size); void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan); void update_hud_info(struct swapchain_stats& sw_stats, struct overlay_params& params, uint32_t vendorID); +void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& params, uint32_t vendorID); void init_gpu_stats(uint32_t& vendorID, overlay_params& params); void init_cpu_stats(overlay_params& params); void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& params, uint32_t vendorID); diff --git a/src/vulkan.cpp b/src/vulkan.cpp new file mode 100644 index 00000000..51f1d2bd --- /dev/null +++ b/src/vulkan.cpp @@ -0,0 +1,2907 @@ +/* + * Copyright © 2019 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#ifdef _WIN32 +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "imgui.h" + +#include "overlay.h" +#include "font_default.h" + +// #include "util/debug.h" +#include +#include "mesa/util/macros.h" +#include "mesa/util/os_time.h" +#include "mesa/util/os_socket.h" + +#include "vk_enum_to_str.h" +#include + +#include "string_utils.h" +#include "file_utils.h" +#include "gpu.h" +#include "logging.h" +#include "cpu.h" +#include "memory.h" +#include "notify.h" +#include "blacklist.h" +#include "version.h" +#include "pci_ids.h" +#include "timing.hpp" + +#ifdef HAVE_DBUS +#include "dbus_info.h" +float g_overflow = 50.f /* 3333ms * 0.5 / 16.6667 / 2 (to edge and back) */; +#endif + +bool open = false; +string gpuString,wineVersion,wineProcess; +float offset_x, offset_y, hudSpacing; +int hudFirstRow, hudSecondRow; +struct fps_limit fps_limit_stats {}; +VkPhysicalDeviceDriverProperties driverProps = {}; +int32_t deviceID; +struct benchmark_stats benchmark; + +/* Mapped from VkInstace/VkPhysicalDevice */ +struct instance_data { + struct vk_instance_dispatch_table vtable; + VkInstance instance; + struct overlay_params params; + uint32_t api_version; + string engineName, engineVersion; + notify_thread notifier; +}; + +/* Mapped from VkDevice */ +struct queue_data; +struct device_data { + struct instance_data *instance; + + PFN_vkSetDeviceLoaderData set_device_loader_data; + + struct vk_device_dispatch_table vtable; + VkPhysicalDevice physical_device; + VkDevice device; + + VkPhysicalDeviceProperties properties; + + struct queue_data *graphic_queue; + + std::vector queues; +}; + +/* Mapped from VkCommandBuffer */ +struct queue_data; +struct command_buffer_data { + struct device_data *device; + + VkCommandBufferLevel level; + + VkCommandBuffer cmd_buffer; + + struct queue_data *queue_data; +}; + +/* Mapped from VkQueue */ +struct queue_data { + struct device_data *device; + + VkQueue queue; + VkQueueFlags flags; + uint32_t family_index; +}; + +struct overlay_draw { + VkCommandBuffer command_buffer; + + VkSemaphore cross_engine_semaphore; + + VkSemaphore semaphore; + VkFence fence; + + VkBuffer vertex_buffer; + VkDeviceMemory vertex_buffer_mem; + VkDeviceSize vertex_buffer_size; + + VkBuffer index_buffer; + VkDeviceMemory index_buffer_mem; + VkDeviceSize index_buffer_size; +}; + +/* Mapped from VkSwapchainKHR */ +struct swapchain_data { + struct device_data *device; + + VkSwapchainKHR swapchain; + unsigned width, height; + VkFormat format; + + std::vector images; + std::vector image_views; + std::vector framebuffers; + + VkRenderPass render_pass; + + VkDescriptorPool descriptor_pool; + VkDescriptorSetLayout descriptor_layout; + VkDescriptorSet descriptor_set; + + VkSampler font_sampler; + + VkPipelineLayout pipeline_layout; + VkPipeline pipeline; + + VkCommandPool command_pool; + + std::list draws; /* List of struct overlay_draw */ + + bool font_uploaded; + VkImage font_image; + VkImageView font_image_view; + VkDeviceMemory font_mem; + VkBuffer upload_font_buffer; + VkDeviceMemory upload_font_buffer_mem; + + /**/ + ImGuiContext* imgui_context; + ImVec2 window_size; + + struct swapchain_stats sw_stats; +}; + +// single global lock, for simplicity +std::mutex global_lock; +typedef std::lock_guard scoped_lock; +std::unordered_map vk_object_to_data; + +thread_local ImGuiContext* __MesaImGui; + +#define HKEY(obj) ((uint64_t)(obj)) +#define FIND(type, obj) (reinterpret_cast(find_object_data(HKEY(obj)))) + +static void *find_object_data(uint64_t obj) +{ + scoped_lock lk(global_lock); + return vk_object_to_data[obj]; +} + +static void map_object(uint64_t obj, void *data) +{ + scoped_lock lk(global_lock); + vk_object_to_data[obj] = data; +} + +static void unmap_object(uint64_t obj) +{ + scoped_lock lk(global_lock); + vk_object_to_data.erase(obj); +} + +/**/ + +#define VK_CHECK(expr) \ + do { \ + VkResult __result = (expr); \ + if (__result != VK_SUCCESS) { \ + fprintf(stderr, "'%s' line %i failed with %s\n", \ + #expr, __LINE__, vk_Result_to_str(__result)); \ + } \ + } while (0) + +/**/ + +#define CHAR_CELSIUS "\xe2\x84\x83" +#define CHAR_FAHRENHEIT "\xe2\x84\x89" + +static VkLayerInstanceCreateInfo *get_instance_chain_info(const VkInstanceCreateInfo *pCreateInfo, + VkLayerFunction func) +{ + vk_foreach_struct(item, pCreateInfo->pNext) { + if (item->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && + ((VkLayerInstanceCreateInfo *) item)->function == func) + return (VkLayerInstanceCreateInfo *) item; + } + unreachable("instance chain info not found"); + return NULL; +} + +static VkLayerDeviceCreateInfo *get_device_chain_info(const VkDeviceCreateInfo *pCreateInfo, + VkLayerFunction func) +{ + vk_foreach_struct(item, pCreateInfo->pNext) { + if (item->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && + ((VkLayerDeviceCreateInfo *) item)->function == func) + return (VkLayerDeviceCreateInfo *)item; + } + unreachable("device chain info not found"); + return NULL; +} + +/**/ + +static struct instance_data *new_instance_data(VkInstance instance) +{ + struct instance_data *data = new instance_data(); + data->instance = instance; + data->params = {}; + data->params.control = -1; + map_object(HKEY(data->instance), data); + return data; +} + +static void destroy_instance_data(struct instance_data *data) +{ + if (data->params.control >= 0) + os_socket_close(data->params.control); + unmap_object(HKEY(data->instance)); + delete data; +} + +static void instance_data_map_physical_devices(struct instance_data *instance_data, + bool map) +{ + uint32_t physicalDeviceCount = 0; + instance_data->vtable.EnumeratePhysicalDevices(instance_data->instance, + &physicalDeviceCount, + NULL); + + std::vector physicalDevices(physicalDeviceCount); + instance_data->vtable.EnumeratePhysicalDevices(instance_data->instance, + &physicalDeviceCount, + physicalDevices.data()); + + for (uint32_t i = 0; i < physicalDeviceCount; i++) { + if (map) + map_object(HKEY(physicalDevices[i]), instance_data); + else + unmap_object(HKEY(physicalDevices[i])); + } +} + +/**/ +static struct device_data *new_device_data(VkDevice device, struct instance_data *instance) +{ + struct device_data *data = new device_data(); + data->instance = instance; + data->device = device; + map_object(HKEY(data->device), data); + return data; +} + +static struct queue_data *new_queue_data(VkQueue queue, + const VkQueueFamilyProperties *family_props, + uint32_t family_index, + struct device_data *device_data) +{ + struct queue_data *data = new queue_data(); + data->device = device_data; + data->queue = queue; + data->flags = family_props->queueFlags; + data->family_index = family_index; + map_object(HKEY(data->queue), data); + + if (data->flags & VK_QUEUE_GRAPHICS_BIT) + device_data->graphic_queue = data; + + return data; +} + +static void destroy_queue(struct queue_data *data) +{ + unmap_object(HKEY(data->queue)); + delete data; +} + +static void device_map_queues(struct device_data *data, + const VkDeviceCreateInfo *pCreateInfo) +{ + uint32_t n_queues = 0; + for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) + n_queues += pCreateInfo->pQueueCreateInfos[i].queueCount; + data->queues.resize(n_queues); + + struct instance_data *instance_data = data->instance; + uint32_t n_family_props; + instance_data->vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device, + &n_family_props, + NULL); + std::vector family_props(n_family_props); + instance_data->vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device, + &n_family_props, + family_props.data()); + + uint32_t queue_index = 0; + for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) { + for (uint32_t j = 0; j < pCreateInfo->pQueueCreateInfos[i].queueCount; j++) { + VkQueue queue; + data->vtable.GetDeviceQueue(data->device, + pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex, + j, &queue); + + VK_CHECK(data->set_device_loader_data(data->device, queue)); + + data->queues[queue_index++] = + new_queue_data(queue, &family_props[pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex], + pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex, data); + } + } +} + +static void device_unmap_queues(struct device_data *data) +{ + for (auto q : data->queues) + destroy_queue(q); +} + +static void destroy_device_data(struct device_data *data) +{ + unmap_object(HKEY(data->device)); + delete data; +} + +/**/ +static struct command_buffer_data *new_command_buffer_data(VkCommandBuffer cmd_buffer, + VkCommandBufferLevel level, + struct device_data *device_data) +{ + struct command_buffer_data *data = new command_buffer_data(); + data->device = device_data; + data->cmd_buffer = cmd_buffer; + data->level = level; + map_object(HKEY(data->cmd_buffer), data); + return data; +} + +static void destroy_command_buffer_data(struct command_buffer_data *data) +{ + unmap_object(HKEY(data->cmd_buffer)); + delete data; +} + +/**/ +static struct swapchain_data *new_swapchain_data(VkSwapchainKHR swapchain, + struct device_data *device_data) +{ + struct instance_data *instance_data = device_data->instance; + struct swapchain_data *data = new swapchain_data(); + data->device = device_data; + data->swapchain = swapchain; + data->window_size = ImVec2(instance_data->params.width, instance_data->params.height); + map_object(HKEY(data->swapchain), data); + return data; +} + +static void destroy_swapchain_data(struct swapchain_data *data) +{ + unmap_object(HKEY(data->swapchain)); + delete data; +} + +struct overlay_draw *get_overlay_draw(struct swapchain_data *data) +{ + struct device_data *device_data = data->device; + struct overlay_draw *draw = data->draws.empty() ? + nullptr : data->draws.front(); + + VkSemaphoreCreateInfo sem_info = {}; + sem_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + if (draw && device_data->vtable.GetFenceStatus(device_data->device, draw->fence) == VK_SUCCESS) { + VK_CHECK(device_data->vtable.ResetFences(device_data->device, + 1, &draw->fence)); + data->draws.pop_front(); + data->draws.push_back(draw); + return draw; + } + + draw = new overlay_draw(); + + VkCommandBufferAllocateInfo cmd_buffer_info = {}; + cmd_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + cmd_buffer_info.commandPool = data->command_pool; + cmd_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + cmd_buffer_info.commandBufferCount = 1; + VK_CHECK(device_data->vtable.AllocateCommandBuffers(device_data->device, + &cmd_buffer_info, + &draw->command_buffer)); + VK_CHECK(device_data->set_device_loader_data(device_data->device, + draw->command_buffer)); + + + VkFenceCreateInfo fence_info = {}; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + VK_CHECK(device_data->vtable.CreateFence(device_data->device, + &fence_info, + NULL, + &draw->fence)); + + VK_CHECK(device_data->vtable.CreateSemaphore(device_data->device, &sem_info, + NULL, &draw->semaphore)); + VK_CHECK(device_data->vtable.CreateSemaphore(device_data->device, &sem_info, + NULL, &draw->cross_engine_semaphore)); + + data->draws.push_back(draw); + + return draw; +} + +void init_cpu_stats(overlay_params& params) +{ + auto& enabled = params.enabled; + enabled[OVERLAY_PARAM_ENABLED_cpu_stats] = cpuStats.Init() + && enabled[OVERLAY_PARAM_ENABLED_cpu_stats]; + enabled[OVERLAY_PARAM_ENABLED_cpu_temp] = cpuStats.GetCpuFile() + && enabled[OVERLAY_PARAM_ENABLED_cpu_temp]; +} + +struct PCI_BUS { + int domain; + int bus; + int slot; + int func; +}; + +void init_gpu_stats(uint32_t& vendorID, overlay_params& params) +{ + //if (!params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats]) + // return; + + PCI_BUS pci; + bool pci_bus_parsed = false; + const char *pci_dev = nullptr; + if (!params.pci_dev.empty()) + pci_dev = params.pci_dev.c_str(); + + // for now just checks if pci bus parses correctly, if at all necessary + if (pci_dev) { + if (sscanf(pci_dev, "%04x:%02x:%02x.%x", + &pci.domain, &pci.bus, + &pci.slot, &pci.func) == 4) { + pci_bus_parsed = true; + // reformat back to sysfs file name's and nvml's expected format + // so config file param's value format doesn't have to be as strict + std::stringstream ss; + ss << std::hex + << std::setw(4) << std::setfill('0') << pci.domain << ":" + << std::setw(2) << pci.bus << ":" + << std::setw(2) << pci.slot << "." + << std::setw(1) << pci.func; + params.pci_dev = ss.str(); + pci_dev = params.pci_dev.c_str(); +#ifndef NDEBUG + std::cerr << "MANGOHUD: PCI device ID: '" << pci_dev << "'\n"; +#endif + } else { + std::cerr << "MANGOHUD: Failed to parse PCI device ID: '" << pci_dev << "'\n"; + std::cerr << "MANGOHUD: Specify it as 'domain:bus:slot.func'\n"; + } + } + + // NVIDIA or Intel but maybe has Optimus + if (vendorID == 0x8086 + || vendorID == 0x10de) { + + bool nvSuccess = false; +#ifdef HAVE_NVML + nvSuccess = checkNVML(pci_dev) && getNVMLInfo(); +#endif +#ifdef HAVE_XNVCTRL + if (!nvSuccess) + nvSuccess = checkXNVCtrl(); +#endif + + if(not nvSuccess) { + params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] = false; + } + else { + vendorID = 0x10de; + } + } + + if (vendorID == 0x8086 || vendorID == 0x1002 + || gpu.find("Radeon") != std::string::npos + || gpu.find("AMD") != std::string::npos) { + string path; + string drm = "/sys/class/drm/"; + + auto dirs = ls(drm.c_str(), "card"); + for (auto& dir : dirs) { + path = drm + dir; + +#ifndef NDEBUG + std::cerr << "amdgpu path check: " << path << "/device/vendor" << std::endl; +#endif + string device = read_line(path + "/device/device"); + deviceID = strtol(device.c_str(), NULL, 16); + string line = read_line(path + "/device/vendor"); + trim(line); + if (line != "0x1002" || !file_exists(path + "/device/gpu_busy_percent")) + continue; + + path += "/device"; + if (pci_bus_parsed && pci_dev) { + string pci_device = read_symlink(path.c_str()); +#ifndef NDEBUG + std::cerr << "PCI device symlink: " << pci_device << "\n"; +#endif + if (!ends_with(pci_device, pci_dev)) { + std::cerr << "MANGOHUD: skipping GPU, no PCI ID match\n"; + continue; + } + } + +#ifndef NDEBUG + std::cerr << "using amdgpu path: " << path << std::endl; +#endif + + if (!amdgpu.busy) + amdgpu.busy = fopen((path + "/gpu_busy_percent").c_str(), "r"); + if (!amdgpu.vram_total) + amdgpu.vram_total = fopen((path + "/mem_info_vram_total").c_str(), "r"); + if (!amdgpu.vram_used) + amdgpu.vram_used = fopen((path + "/mem_info_vram_used").c_str(), "r"); + + path += "/hwmon/"; + string tempFolder; + if (find_folder(path, "hwmon", tempFolder)) { + if (!amdgpu.core_clock) + amdgpu.core_clock = fopen((path + tempFolder + "/freq1_input").c_str(), "r"); + if (!amdgpu.memory_clock) + amdgpu.memory_clock = fopen((path + tempFolder + "/freq2_input").c_str(), "r"); + if (!amdgpu.temp) + amdgpu.temp = fopen((path + tempFolder + "/temp1_input").c_str(), "r"); + if (!amdgpu.power_usage) + amdgpu.power_usage = fopen((path + tempFolder + "/power1_average").c_str(), "r"); + + vendorID = 0x1002; + break; + } + } + + // don't bother then + if (!amdgpu.busy && !amdgpu.temp && !amdgpu.vram_total && !amdgpu.vram_used) { + params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] = false; + } + } + if (!params.permit_upload) + printf("MANGOHUD: Uploading is disabled (permit_upload = 0)\n"); +} + +void init_system_info(){ + const char* ld_preload = getenv("LD_PRELOAD"); + if (ld_preload) + unsetenv("LD_PRELOAD"); + + ram = exec("cat /proc/meminfo | grep 'MemTotal' | awk '{print $2}'"); + trim(ram); + cpu = exec("cat /proc/cpuinfo | grep 'model name' | tail -n1 | sed 's/^.*: //' | sed 's/([^)]*)/()/g' | tr -d '(/)'"); + trim(cpu); + kernel = exec("uname -r"); + trim(kernel); + os = exec("cat /etc/*-release | grep 'PRETTY_NAME' | cut -d '=' -f 2-"); + os.erase(remove(os.begin(), os.end(), '\"' ), os.end()); + trim(os); + gpu = exec("lspci | grep VGA | head -n1 | awk -vRS=']' -vFS='[' '{print $2}' | sed '/^$/d' | tail -n1"); + trim(gpu); + driver = exec("glxinfo | grep 'OpenGL version' | sed 's/^.*: //' | cut -d' ' --output-delimiter=$'\n' -f1- | grep -v '(' | grep -v ')' | tr '\n' ' ' | cut -c 1-"); + trim(driver); + +// Get WINE version + + wineProcess = get_exe_path(); + auto n = wineProcess.find_last_of('/'); + string preloader = wineProcess.substr(n + 1); + if (preloader == "wine-preloader" || preloader == "wine64-preloader") { + // Check if using Proton + if (wineProcess.find("/dist/bin/wine") != std::string::npos) { + stringstream ss; + ss << dirname((char*)wineProcess.c_str()) << "/../../version"; + string protonVersion = ss.str(); + ss.str(""); ss.clear(); + ss << read_line(protonVersion); + std::getline(ss, wineVersion, ' '); // skip first number string + std::getline(ss, wineVersion, ' '); + trim(wineVersion); + string toReplace = "proton-"; + size_t pos = wineVersion.find(toReplace); + if (pos != std::string::npos) { + // If found replace + wineVersion.replace(pos, toReplace.length(), "Proton "); + } + else { + // If not found insert for non official proton builds + wineVersion.insert(0, "Proton "); + } + } + else { + char *dir = dirname((char*)wineProcess.c_str()); + stringstream findVersion; + findVersion << "\"" << dir << "/wine\" --version"; + const char *wine_env = getenv("WINELOADERNOEXEC"); + if (wine_env) + unsetenv("WINELOADERNOEXEC"); + wineVersion = exec(findVersion.str()); + std::cout << "WINE VERSION = " << wineVersion << "\n"; + if (wine_env) + setenv("WINELOADERNOEXEC", wine_env, 1); + } + } + else { + wineVersion = ""; + } + + //driver = itox(device_data->properties.driverVersion); + + if (ld_preload) + setenv("LD_PRELOAD", ld_preload, 1); +#ifndef NDEBUG + std::cout << "Ram:" << ram << "\n" + << "Cpu:" << cpu << "\n" + << "Kernel:" << kernel << "\n" + << "Os:" << os << "\n" + << "Gpu:" << gpu << "\n" + << "Driver:" << driver << std::endl; +#endif + parse_pciids(); +} + +void calculate_benchmark_data(void *params_void){ + overlay_params *params = reinterpret_cast(params_void); + + vector sorted = benchmark.fps_data; + sort(sorted.begin(), sorted.end()); + benchmark.percentile_data.clear(); + + benchmark.total = 0.f; + for (auto fps_ : sorted){ + benchmark.total = benchmark.total + fps_; + } + + size_t max_label_size = 0; + + for (std::string percentile : params->benchmark_percentiles) { + float result; + + // special case handling for a mean-based average + if (percentile == "AVG") { + result = benchmark.total / sorted.size(); + } else { + // the percentiles are already validated when they're parsed from the config. + float fraction = parse_float(percentile) / 100; + + result = sorted[(fraction * sorted.size()) - 1]; + percentile += "%"; + } + + if (percentile.length() > max_label_size) + max_label_size = percentile.length(); + + benchmark.percentile_data.push_back({percentile, result}); + } + + for (auto& entry : benchmark.percentile_data) { + entry.first.append(max_label_size - entry.first.length(), ' '); + } +} + +static void snapshot_swapchain_frame(struct swapchain_data *data) +{ + struct device_data *device_data = data->device; + struct instance_data *instance_data = device_data->instance; + update_hud_info(data->sw_stats, instance_data->params, device_data->properties.vendorID); + check_keybinds(data->sw_stats, instance_data->params, device_data->properties.vendorID); + + // not currently used + // if (instance_data->params.control >= 0) { + // control_client_check(device_data); + // process_control_socket(instance_data); + // } +} + +static float get_time_stat(void *_data, int _idx) +{ + struct swapchain_stats *data = (struct swapchain_stats *) _data; + if ((ARRAY_SIZE(data->frames_stats) - _idx) > data->n_frames) + return 0.0f; + int idx = ARRAY_SIZE(data->frames_stats) + + data->n_frames < ARRAY_SIZE(data->frames_stats) ? + _idx - data->n_frames : + _idx + data->n_frames; + idx %= ARRAY_SIZE(data->frames_stats); + /* Time stats are in us. */ + return data->frames_stats[idx].stats[data->stat_selector] / data->time_dividor; +} + +void position_layer(struct swapchain_stats& data, struct overlay_params& params, ImVec2 window_size) +{ + unsigned width = ImGui::GetIO().DisplaySize.x; + unsigned height = ImGui::GetIO().DisplaySize.y; + float margin = 10.0f; + if (params.offset_x > 0 || params.offset_y > 0) + margin = 0.0f; + + ImGui::SetNextWindowBgAlpha(params.background_alpha); + ImGui::SetNextWindowSize(window_size, ImGuiCond_Always); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8,-3)); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, params.alpha); + switch (params.position) { + case LAYER_POSITION_TOP_LEFT: + data.main_window_pos = ImVec2(margin + params.offset_x, margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + case LAYER_POSITION_TOP_RIGHT: + data.main_window_pos = ImVec2(width - window_size.x - margin + params.offset_x, margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + case LAYER_POSITION_BOTTOM_LEFT: + data.main_window_pos = ImVec2(margin + params.offset_x, height - window_size.y - margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + case LAYER_POSITION_BOTTOM_RIGHT: + data.main_window_pos = ImVec2(width - window_size.x - margin + params.offset_x, height - window_size.y - margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + case LAYER_POSITION_TOP_CENTER: + data.main_window_pos = ImVec2((width / 2) - (window_size.x / 2), margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + } +} + +static void right_aligned_text(float off_x, const char *fmt, ...) +{ + ImVec2 pos = ImGui::GetCursorPos(); + char buffer[32] {}; + + va_list args; + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + + ImVec2 sz = ImGui::CalcTextSize(buffer); + ImGui::SetCursorPosX(pos.x + off_x - sz.x); + ImGui::Text("%s", buffer); +} + +float get_ticker_limited_pos(float pos, float tw, float& left_limit, float& right_limit) +{ + float cw = ImGui::GetContentRegionAvailWidth(); + float new_pos_x = ImGui::GetCursorPosX(); + left_limit = cw - tw + new_pos_x; + right_limit = new_pos_x; + + if (cw < tw) { + new_pos_x += pos; + // acts as a delay before it starts scrolling again + if (new_pos_x < left_limit) + return left_limit; + else if (new_pos_x > right_limit) + return right_limit; + else + return new_pos_x; + } + return new_pos_x; +} + +#ifdef HAVE_DBUS +static void render_mpris_metadata(struct overlay_params& params, mutexed_metadata& meta, uint64_t frame_timing, bool is_main) +{ + if (meta.meta.valid) { + auto color = ImGui::ColorConvertU32ToFloat4(params.media_player_color); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8,0)); + ImGui::Dummy(ImVec2(0.0f, 20.0f)); + //ImGui::PushFont(data.font1); + + if (meta.ticker.needs_recalc) { + meta.ticker.tw0 = ImGui::CalcTextSize(meta.meta.title.c_str()).x; + meta.ticker.tw1 = ImGui::CalcTextSize(meta.meta.artists.c_str()).x; + meta.ticker.tw2 = ImGui::CalcTextSize(meta.meta.album.c_str()).x; + meta.ticker.longest = std::max(std::max( + meta.ticker.tw0, + meta.ticker.tw1), + meta.ticker.tw2); + meta.ticker.needs_recalc = false; + } + + float new_pos, left_limit = 0, right_limit = 0; + get_ticker_limited_pos(meta.ticker.pos, meta.ticker.longest, left_limit, right_limit); + + if (meta.ticker.pos < left_limit - g_overflow * .5f) { + meta.ticker.dir = -1; + meta.ticker.pos = (left_limit - g_overflow * .5f) + 1.f /* random */; + } else if (meta.ticker.pos > right_limit + g_overflow) { + meta.ticker.dir = 1; + meta.ticker.pos = (right_limit + g_overflow) - 1.f /* random */; + } + + meta.ticker.pos -= .5f * (frame_timing / 16666.7f) * meta.ticker.dir; + + for (auto order : params.media_player_order) { + switch (order) { + case MP_ORDER_TITLE: + { + new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw0, left_limit, right_limit); + ImGui::SetCursorPosX(new_pos); + ImGui::TextColored(color, "%s", meta.meta.title.c_str()); + } + break; + case MP_ORDER_ARTIST: + { + new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw1, left_limit, right_limit); + ImGui::SetCursorPosX(new_pos); + ImGui::TextColored(color, "%s", meta.meta.artists.c_str()); + } + break; + case MP_ORDER_ALBUM: + { + //ImGui::NewLine(); + if (!meta.meta.album.empty()) { + new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw2, left_limit, right_limit); + ImGui::SetCursorPosX(new_pos); + ImGui::TextColored(color, "%s", meta.meta.album.c_str()); + } + } + break; + default: break; + } + } + + if (!meta.meta.playing) { + ImGui::TextColored(color, "(paused)"); + } + + //ImGui::PopFont(); + ImGui::PopStyleVar(); + } +} +#endif + +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 = (2 + benchmark.percentile_data.size()) * params.font_size + 10.0f + 58; + ImGui::SetNextWindowSize(ImVec2(window_size.x, benchHeight), ImGuiCond_Always); + if (height - (window_size.y + data.main_window_pos.y + 5) < benchHeight) + ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y - benchHeight - 5), ImGuiCond_Always); + else + ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y + window_size.y + 5), ImGuiCond_Always); + + float display_time = std::chrono::duration(now - logger->last_log_end()).count(); + static float display_for = 10.0f; + float alpha; + if(params.background_alpha != 0){ + if (display_for >= display_time){ + alpha = display_time * params.background_alpha; + if (alpha >= params.background_alpha){ + ImGui::SetNextWindowBgAlpha(params.background_alpha); + }else{ + ImGui::SetNextWindowBgAlpha(alpha); + } + } else { + alpha = 6.0 - display_time * params.background_alpha; + if (alpha >= params.background_alpha){ + ImGui::SetNextWindowBgAlpha(params.background_alpha); + }else{ + ImGui::SetNextWindowBgAlpha(alpha); + } + } + } else { + if (display_for >= display_time){ + alpha = display_time * 0.0001; + ImGui::SetNextWindowBgAlpha(params.background_alpha); + } else { + alpha = 6.0 - display_time * 0.0001; + ImGui::SetNextWindowBgAlpha(params.background_alpha); + } + } + ImGui::Begin("Benchmark", &open, ImGuiWindowFlags_NoDecoration); + static const char* finished = "Logging Finished"; + ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(finished).x / 2)); + 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", std::chrono::duration(logger->last_log_end() - logger->last_log_begin()).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.percentile_data){ + char buffer[20]; + snprintf(buffer, sizeof(buffer), "%s %.1f", data_.first.c_str(), data_.second); + ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(buffer).x / 2)); + ImGui::TextColored(ImVec4(1.0, 1.0, 1.0, alpha / params.background_alpha), "%s %.1f", data_.first.c_str(), data_.second); + } + float max = *max_element(benchmark.fps_data.begin(), benchmark.fps_data.end()); + ImVec4 plotColor = data.colors.frametime; + plotColor.w = alpha / params.background_alpha; + ImGui::PushStyleColor(ImGuiCol_PlotLines, plotColor); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0, 0.0, 0.0, alpha / params.background_alpha)); + ImGui::Dummy(ImVec2(0.0f, 8.0f)); + if (params.enabled[OVERLAY_PARAM_ENABLED_histogram]) + ImGui::PlotHistogram("", benchmark.fps_data.data(), benchmark.fps_data.size(), 0, "", 0.0f, max + 10, ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); + else + ImGui::PlotLines("", benchmark.fps_data.data(), benchmark.fps_data.size(), 0, "", 0.0f, max + 10, ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); + ImGui::PopStyleColor(2); + ImGui::End(); +} + +void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan){ + static int tableCols = 2; + static float ralign_width = 0, old_scale = 0; + window_size = ImVec2(300, params.height); + + if (old_scale != params.font_scale) { + ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; + old_scale = params.font_scale; + } + ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); + ImGui::BeginTable("hud", tableCols); + if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats]){ + ImGui::TableNextRow(); + const char* gpu_text; + if (params.gpu_text.empty()) + gpu_text = "GPU"; + else + gpu_text = params.gpu_text.c_str(); + ImGui::TextColored(data.colors.gpu, "%s", gpu_text); + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::Text("%%"); + } + if(params.enabled[OVERLAY_PARAM_ENABLED_cpu_stats]){ + ImGui::TableNextRow(); + const char* cpu_text; + if (params.cpu_text.empty()) + cpu_text = "CPU"; + else + cpu_text = params.cpu_text.c_str(); + ImGui::TextColored(data.colors.cpu, "%s", cpu_text); + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); + ImGui::SameLine(0, 1.0f); + ImGui::Text("%%"); + } + if (params.enabled[OVERLAY_PARAM_ENABLED_fps]){ + ImGui::TableNextRow(); + ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%.0f", data.fps); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(data.font1); + ImGui::Text("FPS"); + ImGui::PopFont(); + } + ImGui::EndTable(); + if (params.enabled[OVERLAY_PARAM_ENABLED_frame_timing]){ + ImGui::Dummy(ImVec2(0.0f, 8.0f)); + ImGui::PushFont(data.font1); + ImGui::TextColored(data.colors.engine, "%s", "Frametime"); + ImGui::PopFont(); + + char hash[40]; + snprintf(hash, sizeof(hash), "##%s", overlay_param_names[OVERLAY_PARAM_ENABLED_frame_timing]); + data.stat_selector = OVERLAY_PLOTS_frame_timing; + data.time_dividor = 1000.0f; + + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); + double min_time = 0.0f; + double max_time = 50.0f; + ImGui::PlotLines(hash, get_time_stat, &data, + ARRAY_SIZE(data.frames_stats), 0, + NULL, min_time, max_time, + ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); + + ImGui::PopStyleColor(); + } + if(logger->is_active()) + ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(data.main_window_pos.x + window_size.x - 15, data.main_window_pos.y + 15), 10, params.engine_color, 20); + ImGui::End(); + window_size = ImVec2(window_size.x, 200); +} + +void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan) +{ + ImGui::GetIO().FontGlobalScale = params.font_scale; + if(not logger) logger = std::make_unique(¶ms); + uint32_t f_idx = (data.n_frames - 1) % ARRAY_SIZE(data.frames_stats); + uint64_t frame_timing = data.frames_stats[f_idx].stats[OVERLAY_PLOTS_frame_timing]; + static float ralign_width = 0, old_scale = 0; + window_size = ImVec2(params.width, params.height); + unsigned height = ImGui::GetIO().DisplaySize.y; + auto now = Clock::now(); + if (params.log_interval == 0){ + logger->try_log(); + } + + if (old_scale != params.font_scale) { + ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; + old_scale = params.font_scale; + } + + if (!params.no_display){ + ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); + if (params.enabled[OVERLAY_PARAM_ENABLED_version]){ + ImGui::Text("%s", MANGOHUD_VERSION); + ImGui::Dummy(ImVec2(0, 8.0f)); + } + if (params.enabled[OVERLAY_PARAM_ENABLED_time]){ + ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.00f), "%s", data.time.c_str()); + } + ImGui::BeginTable("hud", params.tableCols); + if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats]){ + ImGui::TableNextRow(); + const char* gpu_text; + if (params.gpu_text.empty()) + gpu_text = "GPU"; + else + gpu_text = params.gpu_text.c_str(); + ImGui::TextColored(data.colors.gpu, "%s", gpu_text); + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::Text("%%"); + // ImGui::SameLine(150); + // ImGui::Text("%s", "%"); + if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_temp]){ + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%i", gpu_info.temp); + ImGui::SameLine(0, 1.0f); + ImGui::Text("°C"); + } + if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock] || params.enabled[OVERLAY_PARAM_ENABLED_gpu_power]) + ImGui::TableNextRow(); + if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock]){ + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%i", gpu_info.CoreClock); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(data.font1); + ImGui::Text("MHz"); + ImGui::PopFont(); + } + if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_power]) { + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%i", gpu_info.powerUsage); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(data.font1); + ImGui::Text("W"); + ImGui::PopFont(); + } + } + if(params.enabled[OVERLAY_PARAM_ENABLED_cpu_stats]){ + ImGui::TableNextRow(); + const char* cpu_text; + if (params.cpu_text.empty()) + cpu_text = "CPU"; + else + cpu_text = params.cpu_text.c_str(); + ImGui::TextColored(data.colors.cpu, "%s", cpu_text); + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); + ImGui::SameLine(0, 1.0f); + ImGui::Text("%%"); + // ImGui::SameLine(150); + // ImGui::Text("%s", "%"); + + if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_temp]){ + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); + ImGui::SameLine(0, 1.0f); + ImGui::Text("°C"); + } + } + + if (params.enabled[OVERLAY_PARAM_ENABLED_core_load]){ + int i = 0; + for (const CPUData &cpuData : cpuStats.GetCPUData()) + { + ImGui::TableNextRow(); + ImGui::TextColored(data.colors.cpu, "CPU"); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(data.font1); + ImGui::TextColored(data.colors.cpu,"%i", i); + ImGui::PopFont(); + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%i", int(cpuData.percent)); + ImGui::SameLine(0, 1.0f); + ImGui::Text("%%"); + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%i", cpuData.mhz); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(data.font1); + ImGui::Text("MHz"); + ImGui::PopFont(); + i++; + } + } + if (params.enabled[OVERLAY_PARAM_ENABLED_io_read] || params.enabled[OVERLAY_PARAM_ENABLED_io_write]){ + auto sampling = params.fps_sampling_period; + ImGui::TableNextRow(); + if (params.enabled[OVERLAY_PARAM_ENABLED_io_read] && !params.enabled[OVERLAY_PARAM_ENABLED_io_write]) + ImGui::TextColored(data.colors.io, "IO RD"); + else if (params.enabled[OVERLAY_PARAM_ENABLED_io_read] && params.enabled[OVERLAY_PARAM_ENABLED_io_write]) + ImGui::TextColored(data.colors.io, "IO RW"); + else if (params.enabled[OVERLAY_PARAM_ENABLED_io_write] && !params.enabled[OVERLAY_PARAM_ENABLED_io_read]) + ImGui::TextColored(data.colors.io, "IO WR"); + + if (params.enabled[OVERLAY_PARAM_ENABLED_io_read]){ + ImGui::TableNextCell(); + float val = data.io.diff.read * 1000000 / sampling; + right_aligned_text(ralign_width, val < 100 ? "%.1f" : "%.f", val); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(data.font1); + ImGui::Text("MiB/s"); + ImGui::PopFont(); + } + if (params.enabled[OVERLAY_PARAM_ENABLED_io_write]){ + ImGui::TableNextCell(); + float val = data.io.diff.write * 1000000 / sampling; + right_aligned_text(ralign_width, val < 100 ? "%.1f" : "%.f", val); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(data.font1); + ImGui::Text("MiB/s"); + ImGui::PopFont(); + } + } + if (params.enabled[OVERLAY_PARAM_ENABLED_vram]){ + ImGui::TableNextRow(); + ImGui::TextColored(data.colors.vram, "VRAM"); + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%.1f", gpu_info.memoryUsed); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(data.font1); + ImGui::Text("GiB"); + ImGui::PopFont(); + if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_mem_clock]){ + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%i", gpu_info.MemClock); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(data.font1); + ImGui::Text("MHz"); + ImGui::PopFont(); + } + } + if (params.enabled[OVERLAY_PARAM_ENABLED_ram]){ + ImGui::TableNextRow(); + ImGui::TextColored(data.colors.ram, "RAM"); + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%.1f", memused); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(data.font1); + ImGui::Text("GiB"); + ImGui::PopFont(); + } + if (params.enabled[OVERLAY_PARAM_ENABLED_fps]){ + ImGui::TableNextRow(); + ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%.0f", data.fps); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(data.font1); + ImGui::Text("FPS"); + ImGui::PopFont(); + ImGui::TableNextCell(); + right_aligned_text(ralign_width, "%.1f", 1000 / data.fps); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(data.font1); + ImGui::Text("ms"); + ImGui::PopFont(); + } + if (!params.enabled[OVERLAY_PARAM_ENABLED_fps] && params.enabled[OVERLAY_PARAM_ENABLED_engine_version]){ + ImGui::TableNextRow(); + ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); + } + ImGui::EndTable(); + if (params.enabled[OVERLAY_PARAM_ENABLED_engine_version]){ + ImGui::PushFont(data.font1); + ImGui::Dummy(ImVec2(0, 8.0f)); + if (is_vulkan) { + if ((data.engineName == "DXVK" || data.engineName == "VKD3D")){ + ImGui::TextColored(data.colors.engine, + "%s/%d.%d.%d", data.engineVersion.c_str(), + data.version_vk.major, + data.version_vk.minor, + data.version_vk.patch); + } else { + ImGui::TextColored(data.colors.engine, + "%d.%d.%d", + data.version_vk.major, + data.version_vk.minor, + data.version_vk.patch); + } + } else { + ImGui::TextColored(data.colors.engine, + "%d.%d%s", data.version_gl.major, data.version_gl.minor, + data.version_gl.is_gles ? " ES" : ""); + } + // ImGui::SameLine(); + ImGui::PopFont(); + } + if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_name] && !data.gpuName.empty()){ + ImGui::PushFont(data.font1); + ImGui::Dummy(ImVec2(0.0,5.0f)); + ImGui::TextColored(data.colors.engine, + "%s", data.gpuName.c_str()); + ImGui::PopFont(); + } + if (params.enabled[OVERLAY_PARAM_ENABLED_vulkan_driver] && !data.driverName.empty()){ + ImGui::PushFont(data.font1); + ImGui::Dummy(ImVec2(0.0,5.0f)); + ImGui::TextColored(data.colors.engine, + "%s", data.driverName.c_str()); + ImGui::PopFont(); + } + if (params.enabled[OVERLAY_PARAM_ENABLED_arch]){ + ImGui::PushFont(data.font1); + ImGui::Dummy(ImVec2(0.0,5.0f)); + ImGui::TextColored(data.colors.engine, "%s", "" MANGOHUD_ARCH); + ImGui::PopFont(); + } + if (params.enabled[OVERLAY_PARAM_ENABLED_wine]){ + if (!wineVersion.empty()){ + //ImGui::TextColored(data.colors.wine, "%s", "WINE"); + ImGui::PushFont(data.font1); + ImGui::Dummy(ImVec2(0.0,5.0f)); + ImGui::TextColored(data.colors.wine, "%s", wineVersion.c_str()); + ImGui::PopFont(); + } + } + if (params.enabled[OVERLAY_PARAM_ENABLED_frame_timing]){ + ImGui::Dummy(ImVec2(0.0f, params.font_size * params.font_scale / 2)); + ImGui::PushFont(data.font1); + ImGui::TextColored(data.colors.engine, "%s", "Frametime"); + ImGui::PopFont(); + + char hash[40]; + snprintf(hash, sizeof(hash), "##%s", overlay_param_names[OVERLAY_PARAM_ENABLED_frame_timing]); + data.stat_selector = OVERLAY_PLOTS_frame_timing; + data.time_dividor = 1000.0f; + + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); + double min_time = 0.0f; + double max_time = 50.0f; + if (params.enabled[OVERLAY_PARAM_ENABLED_histogram]){ + ImGui::PlotHistogram(hash, get_time_stat, &data, + ARRAY_SIZE(data.frames_stats), 0, + NULL, min_time, max_time, + ImVec2(ImGui::GetContentRegionAvailWidth() - params.font_size * params.font_scale * 2.2, 50)); + } else { + ImGui::PlotLines(hash, get_time_stat, &data, + ARRAY_SIZE(data.frames_stats), 0, + NULL, min_time, max_time, + ImVec2(ImGui::GetContentRegionAvailWidth() - params.font_size * params.font_scale * 2.2, 50)); + } + ImGui::PopStyleColor(); + } + if (params.enabled[OVERLAY_PARAM_ENABLED_frame_timing]){ + ImGui::SameLine(0,1.0f); + ImGui::PushFont(data.font1); + ImGui::Text("%.1f ms", 1000 / data.fps); //frame_timing / 1000.f); + ImGui::PopFont(); + } + +#ifdef HAVE_DBUS + ImFont scaled_font = *data.font_text; + scaled_font.Scale = params.font_scale_media_player; + ImGui::PushFont(&scaled_font); + { + std::lock_guard lck(main_metadata.mtx); + render_mpris_metadata(params, main_metadata, frame_timing, true); + } + //render_mpris_metadata(params, generic_mpris, frame_timing, false); + ImGui::PopFont(); +#endif + + if(logger->is_active()) + 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((now - logger->last_log_end()) < 12s) + render_benchmark(data, params, window_size, height, now); + } +} + +static void compute_swapchain_display(struct swapchain_data *data) +{ + struct device_data *device_data = data->device; + struct instance_data *instance_data = device_data->instance; + + ImGui::SetCurrentContext(data->imgui_context); + ImGui::NewFrame(); + { + scoped_lock lk(instance_data->notifier.mutex); + position_layer(data->sw_stats, instance_data->params, data->window_size); + if(instance_data->params.render_mango) + render_mango(data->sw_stats, instance_data->params, data->window_size, true); + else + render_imgui(data->sw_stats, instance_data->params, data->window_size, true); + } + ImGui::PopStyleVar(3); + + ImGui::EndFrame(); + ImGui::Render(); + +} + +static uint32_t vk_memory_type(struct device_data *data, + VkMemoryPropertyFlags properties, + uint32_t type_bits) +{ + VkPhysicalDeviceMemoryProperties prop; + data->instance->vtable.GetPhysicalDeviceMemoryProperties(data->physical_device, &prop); + for (uint32_t i = 0; i < prop.memoryTypeCount; i++) + if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<device; + /* Descriptor set */ + VkDescriptorImageInfo desc_image[1] = {}; + desc_image[0].sampler = data->font_sampler; + desc_image[0].imageView = image_view; + desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet write_desc[1] = {}; + write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_desc[0].dstSet = set; + write_desc[0].descriptorCount = 1; + write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write_desc[0].pImageInfo = desc_image; + device_data->vtable.UpdateDescriptorSets(device_data->device, 1, write_desc, 0, NULL); +} + +static void upload_image_data(struct device_data *device_data, + VkCommandBuffer command_buffer, + void *pixels, + VkDeviceSize upload_size, + uint32_t width, + uint32_t height, + VkBuffer& upload_buffer, + VkDeviceMemory& upload_buffer_mem, + VkImage image) +{ + /* Upload buffer */ + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = upload_size; + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + VK_CHECK(device_data->vtable.CreateBuffer(device_data->device, &buffer_info, + NULL, &upload_buffer)); + VkMemoryRequirements upload_buffer_req; + device_data->vtable.GetBufferMemoryRequirements(device_data->device, + upload_buffer, + &upload_buffer_req); + VkMemoryAllocateInfo upload_alloc_info = {}; + upload_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + upload_alloc_info.allocationSize = upload_buffer_req.size; + upload_alloc_info.memoryTypeIndex = vk_memory_type(device_data, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + upload_buffer_req.memoryTypeBits); + VK_CHECK(device_data->vtable.AllocateMemory(device_data->device, + &upload_alloc_info, + NULL, + &upload_buffer_mem)); + VK_CHECK(device_data->vtable.BindBufferMemory(device_data->device, + upload_buffer, + upload_buffer_mem, 0)); + + /* Upload to Buffer */ + char* map = NULL; + VK_CHECK(device_data->vtable.MapMemory(device_data->device, + upload_buffer_mem, + 0, upload_size, 0, (void**)(&map))); + memcpy(map, pixels, upload_size); + VkMappedMemoryRange range[1] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = upload_buffer_mem; + range[0].size = upload_size; + VK_CHECK(device_data->vtable.FlushMappedMemoryRanges(device_data->device, 1, range)); + device_data->vtable.UnmapMemory(device_data->device, + upload_buffer_mem); + + /* Copy buffer to image */ + VkImageMemoryBarrier copy_barrier[1] = {}; + copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].image = image; + copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy_barrier[0].subresourceRange.levelCount = 1; + copy_barrier[0].subresourceRange.layerCount = 1; + device_data->vtable.CmdPipelineBarrier(command_buffer, + VK_PIPELINE_STAGE_HOST_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, NULL, 0, NULL, + 1, copy_barrier); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = width; + region.imageExtent.height = height; + region.imageExtent.depth = 1; + device_data->vtable.CmdCopyBufferToImage(command_buffer, + upload_buffer, + image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ®ion); + + VkImageMemoryBarrier use_barrier[1] = {}; + use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].image = image; + use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + use_barrier[0].subresourceRange.levelCount = 1; + use_barrier[0].subresourceRange.layerCount = 1; + device_data->vtable.CmdPipelineBarrier(command_buffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + 0, + 0, NULL, + 0, NULL, + 1, use_barrier); +} + +static VkDescriptorSet create_image_with_desc(struct swapchain_data *data, + uint32_t width, + uint32_t height, + VkFormat format, + VkImage& image, + VkDeviceMemory& image_mem, + VkImageView& image_view) +{ + struct device_data *device_data = data->device; + + VkImageCreateInfo image_info = {}; + image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_info.imageType = VK_IMAGE_TYPE_2D; + image_info.format = format; + image_info.extent.width = width; + image_info.extent.height = height; + image_info.extent.depth = 1; + image_info.mipLevels = 1; + image_info.arrayLayers = 1; + image_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VK_CHECK(device_data->vtable.CreateImage(device_data->device, &image_info, + NULL, &image)); + VkMemoryRequirements font_image_req; + device_data->vtable.GetImageMemoryRequirements(device_data->device, + image, &font_image_req); + VkMemoryAllocateInfo image_alloc_info = {}; + image_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + image_alloc_info.allocationSize = font_image_req.size; + image_alloc_info.memoryTypeIndex = vk_memory_type(device_data, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + font_image_req.memoryTypeBits); + VK_CHECK(device_data->vtable.AllocateMemory(device_data->device, &image_alloc_info, + NULL, &image_mem)); + VK_CHECK(device_data->vtable.BindImageMemory(device_data->device, + image, + image_mem, 0)); + + /* Font image view */ + VkImageViewCreateInfo view_info = {}; + view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view_info.image = image; + view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + view_info.format = format; + view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + view_info.subresourceRange.levelCount = 1; + view_info.subresourceRange.layerCount = 1; + VK_CHECK(device_data->vtable.CreateImageView(device_data->device, &view_info, + NULL, &image_view)); + + VkDescriptorSet descriptor_set; + + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = data->descriptor_pool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &data->descriptor_layout; + VK_CHECK(device_data->vtable.AllocateDescriptorSets(device_data->device, + &alloc_info, + &descriptor_set)); + + update_image_descriptor(data, image_view, descriptor_set); + return descriptor_set; +} + +static void ensure_swapchain_fonts(struct swapchain_data *data, + VkCommandBuffer command_buffer) +{ + struct device_data *device_data = data->device; + if (data->font_uploaded) + return; + + data->font_uploaded = true; + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); + size_t upload_size = width * height * 1 * sizeof(char); + upload_image_data(device_data, command_buffer, pixels, upload_size, width, height, data->upload_font_buffer, data->upload_font_buffer_mem, data->font_image); +} + +static void CreateOrResizeBuffer(struct device_data *data, + VkBuffer *buffer, + VkDeviceMemory *buffer_memory, + VkDeviceSize *buffer_size, + size_t new_size, VkBufferUsageFlagBits usage) +{ + if (*buffer != VK_NULL_HANDLE) + data->vtable.DestroyBuffer(data->device, *buffer, NULL); + if (*buffer_memory) + data->vtable.FreeMemory(data->device, *buffer_memory, NULL); + + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = new_size; + buffer_info.usage = usage; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + VK_CHECK(data->vtable.CreateBuffer(data->device, &buffer_info, NULL, buffer)); + + VkMemoryRequirements req; + data->vtable.GetBufferMemoryRequirements(data->device, *buffer, &req); + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = + vk_memory_type(data, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + VK_CHECK(data->vtable.AllocateMemory(data->device, &alloc_info, NULL, buffer_memory)); + + VK_CHECK(data->vtable.BindBufferMemory(data->device, *buffer, *buffer_memory, 0)); + *buffer_size = new_size; +} + +static struct overlay_draw *render_swapchain_display(struct swapchain_data *data, + struct queue_data *present_queue, + const VkSemaphore *wait_semaphores, + unsigned n_wait_semaphores, + unsigned image_index) +{ + ImDrawData* draw_data = ImGui::GetDrawData(); + if (draw_data->TotalVtxCount == 0) + return NULL; + + struct device_data *device_data = data->device; + struct overlay_draw *draw = get_overlay_draw(data); + + device_data->vtable.ResetCommandBuffer(draw->command_buffer, 0); + + VkRenderPassBeginInfo render_pass_info = {}; + render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + render_pass_info.renderPass = data->render_pass; + render_pass_info.framebuffer = data->framebuffers[image_index]; + render_pass_info.renderArea.extent.width = data->width; + render_pass_info.renderArea.extent.height = data->height; + + VkCommandBufferBeginInfo buffer_begin_info = {}; + buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + + device_data->vtable.BeginCommandBuffer(draw->command_buffer, &buffer_begin_info); + + ensure_swapchain_fonts(data, draw->command_buffer); + + /* Bounce the image to display back to color attachment layout for + * rendering on top of it. + */ + VkImageMemoryBarrier imb; + imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imb.pNext = nullptr; + imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imb.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + imb.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + imb.image = data->images[image_index]; + imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imb.subresourceRange.baseMipLevel = 0; + imb.subresourceRange.levelCount = 1; + imb.subresourceRange.baseArrayLayer = 0; + imb.subresourceRange.layerCount = 1; + imb.srcQueueFamilyIndex = present_queue->family_index; + imb.dstQueueFamilyIndex = device_data->graphic_queue->family_index; + device_data->vtable.CmdPipelineBarrier(draw->command_buffer, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + 0, /* dependency flags */ + 0, nullptr, /* memory barriers */ + 0, nullptr, /* buffer memory barriers */ + 1, &imb); /* image memory barriers */ + + device_data->vtable.CmdBeginRenderPass(draw->command_buffer, &render_pass_info, + VK_SUBPASS_CONTENTS_INLINE); + + /* Create/Resize vertex & index buffers */ + size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); + size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + if (draw->vertex_buffer_size < vertex_size) { + CreateOrResizeBuffer(device_data, + &draw->vertex_buffer, + &draw->vertex_buffer_mem, + &draw->vertex_buffer_size, + vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + } + if (draw->index_buffer_size < index_size) { + CreateOrResizeBuffer(device_data, + &draw->index_buffer, + &draw->index_buffer_mem, + &draw->index_buffer_size, + index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + } + + /* Upload vertex & index data */ + ImDrawVert* vtx_dst = NULL; + ImDrawIdx* idx_dst = NULL; + VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->vertex_buffer_mem, + 0, vertex_size, 0, (void**)(&vtx_dst))); + VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->index_buffer_mem, + 0, index_size, 0, (void**)(&idx_dst))); + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); + memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.Size; + idx_dst += cmd_list->IdxBuffer.Size; + } + VkMappedMemoryRange range[2] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = draw->vertex_buffer_mem; + range[0].size = VK_WHOLE_SIZE; + range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[1].memory = draw->index_buffer_mem; + range[1].size = VK_WHOLE_SIZE; + VK_CHECK(device_data->vtable.FlushMappedMemoryRanges(device_data->device, 2, range)); + device_data->vtable.UnmapMemory(device_data->device, draw->vertex_buffer_mem); + device_data->vtable.UnmapMemory(device_data->device, draw->index_buffer_mem); + + /* Bind pipeline and descriptor sets */ + device_data->vtable.CmdBindPipeline(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, data->pipeline); + +#if 1 // disable if using >1 font textures + VkDescriptorSet desc_set[1] = { + //data->descriptor_set + reinterpret_cast(ImGui::GetIO().Fonts->Fonts[0]->ContainerAtlas->TexID) + }; + device_data->vtable.CmdBindDescriptorSets(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + data->pipeline_layout, 0, 1, desc_set, 0, NULL); +#endif + + /* Bind vertex & index buffers */ + VkBuffer vertex_buffers[1] = { draw->vertex_buffer }; + VkDeviceSize vertex_offset[1] = { 0 }; + device_data->vtable.CmdBindVertexBuffers(draw->command_buffer, 0, 1, vertex_buffers, vertex_offset); + device_data->vtable.CmdBindIndexBuffer(draw->command_buffer, draw->index_buffer, 0, VK_INDEX_TYPE_UINT16); + + /* Setup viewport */ + VkViewport viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = draw_data->DisplaySize.x; + viewport.height = draw_data->DisplaySize.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + device_data->vtable.CmdSetViewport(draw->command_buffer, 0, 1, &viewport); + + + /* Setup scale and translation through push constants : + * + * Our visible imgui space lies from draw_data->DisplayPos (top left) to + * draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin + * is typically (0,0) for single viewport apps. + */ + float scale[2]; + scale[0] = 2.0f / draw_data->DisplaySize.x; + scale[1] = 2.0f / draw_data->DisplaySize.y; + float translate[2]; + translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; + translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; + device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, + VK_SHADER_STAGE_VERTEX_BIT, + sizeof(float) * 0, sizeof(float) * 2, scale); + device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, + VK_SHADER_STAGE_VERTEX_BIT, + sizeof(float) * 2, sizeof(float) * 2, translate); + + // Render the command lists: + int vtx_offset = 0; + int idx_offset = 0; + ImVec2 display_pos = draw_data->DisplayPos; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + // Apply scissor/clipping rectangle + // FIXME: We could clamp width/height based on clamped min/max values. + VkRect2D scissor; + scissor.offset.x = (int32_t)(pcmd->ClipRect.x - display_pos.x) > 0 ? (int32_t)(pcmd->ClipRect.x - display_pos.x) : 0; + scissor.offset.y = (int32_t)(pcmd->ClipRect.y - display_pos.y) > 0 ? (int32_t)(pcmd->ClipRect.y - display_pos.y) : 0; + scissor.extent.width = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x); + scissor.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // FIXME: Why +1 here? + device_data->vtable.CmdSetScissor(draw->command_buffer, 0, 1, &scissor); +#if 0 //enable if using >1 font textures or use texture array + VkDescriptorSet desc_set[1] = { (VkDescriptorSet)pcmd->TextureId }; + device_data->vtable.CmdBindDescriptorSets(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + data->pipeline_layout, 0, 1, desc_set, 0, NULL); +#endif + // Draw + device_data->vtable.CmdDrawIndexed(draw->command_buffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); + + idx_offset += pcmd->ElemCount; + } + vtx_offset += cmd_list->VtxBuffer.Size; + } + + device_data->vtable.CmdEndRenderPass(draw->command_buffer); + + if (device_data->graphic_queue->family_index != present_queue->family_index) + { + /* Transfer the image back to the present queue family + * image layout was already changed to present by the render pass + */ + imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imb.pNext = nullptr; + imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imb.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + imb.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + imb.image = data->images[image_index]; + imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imb.subresourceRange.baseMipLevel = 0; + imb.subresourceRange.levelCount = 1; + imb.subresourceRange.baseArrayLayer = 0; + imb.subresourceRange.layerCount = 1; + imb.srcQueueFamilyIndex = device_data->graphic_queue->family_index; + imb.dstQueueFamilyIndex = present_queue->family_index; + device_data->vtable.CmdPipelineBarrier(draw->command_buffer, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + 0, /* dependency flags */ + 0, nullptr, /* memory barriers */ + 0, nullptr, /* buffer memory barriers */ + 1, &imb); /* image memory barriers */ + } + + device_data->vtable.EndCommandBuffer(draw->command_buffer); + + /* When presenting on a different queue than where we're drawing the + * overlay *AND* when the application does not provide a semaphore to + * vkQueuePresent, insert our own cross engine synchronization + * semaphore. + */ + if (n_wait_semaphores == 0 && device_data->graphic_queue->queue != present_queue->queue) { + VkPipelineStageFlags stages_wait = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 0; + submit_info.pWaitDstStageMask = &stages_wait; + submit_info.waitSemaphoreCount = 0; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &draw->cross_engine_semaphore; + + device_data->vtable.QueueSubmit(present_queue->queue, 1, &submit_info, VK_NULL_HANDLE); + + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pWaitDstStageMask = &stages_wait; + submit_info.pCommandBuffers = &draw->command_buffer; + submit_info.waitSemaphoreCount = 1; + submit_info.pWaitSemaphores = &draw->cross_engine_semaphore; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &draw->semaphore; + + device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence); + } else { + // wait in the fragment stage until the swapchain image is ready + std::vector stages_wait(n_wait_semaphores, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &draw->command_buffer; + submit_info.pWaitDstStageMask = stages_wait.data(); + submit_info.waitSemaphoreCount = n_wait_semaphores; + submit_info.pWaitSemaphores = wait_semaphores; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &draw->semaphore; + + device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence); + } + + return draw; +} + +static const uint32_t overlay_vert_spv[] = { +#include "overlay.vert.spv.h" +}; +static const uint32_t overlay_frag_spv[] = { +#include "overlay.frag.spv.h" +}; + +static void setup_swapchain_data_pipeline(struct swapchain_data *data) +{ + struct device_data *device_data = data->device; + VkShaderModule vert_module, frag_module; + + /* Create shader modules */ + VkShaderModuleCreateInfo vert_info = {}; + vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + vert_info.codeSize = sizeof(overlay_vert_spv); + vert_info.pCode = overlay_vert_spv; + VK_CHECK(device_data->vtable.CreateShaderModule(device_data->device, + &vert_info, NULL, &vert_module)); + VkShaderModuleCreateInfo frag_info = {}; + frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + frag_info.codeSize = sizeof(overlay_frag_spv); + frag_info.pCode = (uint32_t*)overlay_frag_spv; + VK_CHECK(device_data->vtable.CreateShaderModule(device_data->device, + &frag_info, NULL, &frag_module)); + + /* Font sampler */ + VkSamplerCreateInfo sampler_info = {}; + sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + sampler_info.magFilter = VK_FILTER_LINEAR; + sampler_info.minFilter = VK_FILTER_LINEAR; + sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.minLod = -1000; + sampler_info.maxLod = 1000; + sampler_info.maxAnisotropy = 1.0f; + VK_CHECK(device_data->vtable.CreateSampler(device_data->device, &sampler_info, + NULL, &data->font_sampler)); + + /* Descriptor pool */ + VkDescriptorPoolSize sampler_pool_size = {}; + sampler_pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + sampler_pool_size.descriptorCount = 1; + VkDescriptorPoolCreateInfo desc_pool_info = {}; + desc_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + desc_pool_info.maxSets = 1; + desc_pool_info.poolSizeCount = 1; + desc_pool_info.pPoolSizes = &sampler_pool_size; + VK_CHECK(device_data->vtable.CreateDescriptorPool(device_data->device, + &desc_pool_info, + NULL, &data->descriptor_pool)); + + /* Descriptor layout */ + VkSampler sampler[1] = { data->font_sampler }; + VkDescriptorSetLayoutBinding binding[1] = {}; + binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + binding[0].descriptorCount = 1; + binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + binding[0].pImmutableSamplers = sampler; + VkDescriptorSetLayoutCreateInfo set_layout_info = {}; + set_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + set_layout_info.bindingCount = 1; + set_layout_info.pBindings = binding; + VK_CHECK(device_data->vtable.CreateDescriptorSetLayout(device_data->device, + &set_layout_info, + NULL, &data->descriptor_layout)); + + /* Descriptor set */ +/* + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = data->descriptor_pool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &data->descriptor_layout; + VK_CHECK(device_data->vtable.AllocateDescriptorSets(device_data->device, + &alloc_info, + &data->descriptor_set)); +*/ + + /* Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full + * 3d projection matrix + */ + VkPushConstantRange push_constants[1] = {}; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[0].offset = sizeof(float) * 0; + push_constants[0].size = sizeof(float) * 4; + VkPipelineLayoutCreateInfo layout_info = {}; + layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_info.setLayoutCount = 1; + layout_info.pSetLayouts = &data->descriptor_layout; + layout_info.pushConstantRangeCount = 1; + layout_info.pPushConstantRanges = push_constants; + VK_CHECK(device_data->vtable.CreatePipelineLayout(device_data->device, + &layout_info, + NULL, &data->pipeline_layout)); + + VkPipelineShaderStageCreateInfo stage[2] = {}; + stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stage[0].module = vert_module; + stage[0].pName = "main"; + stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + stage[1].module = frag_module; + stage[1].pName = "main"; + + VkVertexInputBindingDescription binding_desc[1] = {}; + binding_desc[0].stride = sizeof(ImDrawVert); + binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + VkVertexInputAttributeDescription attribute_desc[3] = {}; + attribute_desc[0].location = 0; + attribute_desc[0].binding = binding_desc[0].binding; + attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[0].offset = IM_OFFSETOF(ImDrawVert, pos); + attribute_desc[1].location = 1; + attribute_desc[1].binding = binding_desc[0].binding; + attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[1].offset = IM_OFFSETOF(ImDrawVert, uv); + attribute_desc[2].location = 2; + attribute_desc[2].binding = binding_desc[0].binding; + attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; + attribute_desc[2].offset = IM_OFFSETOF(ImDrawVert, col); + + VkPipelineVertexInputStateCreateInfo vertex_info = {}; + vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_info.vertexBindingDescriptionCount = 1; + vertex_info.pVertexBindingDescriptions = binding_desc; + vertex_info.vertexAttributeDescriptionCount = 3; + vertex_info.pVertexAttributeDescriptions = attribute_desc; + + VkPipelineInputAssemblyStateCreateInfo ia_info = {}; + ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + VkPipelineViewportStateCreateInfo viewport_info = {}; + viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_info.viewportCount = 1; + viewport_info.scissorCount = 1; + + VkPipelineRasterizationStateCreateInfo raster_info = {}; + raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + raster_info.polygonMode = VK_POLYGON_MODE_FILL; + raster_info.cullMode = VK_CULL_MODE_NONE; + raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + raster_info.lineWidth = 1.0f; + + VkPipelineMultisampleStateCreateInfo ms_info = {}; + ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState color_attachment[1] = {}; + color_attachment[0].blendEnable = VK_TRUE; + color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | + VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineDepthStencilStateCreateInfo depth_info = {}; + depth_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + + VkPipelineColorBlendStateCreateInfo blend_info = {}; + blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + blend_info.attachmentCount = 1; + blend_info.pAttachments = color_attachment; + + VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamic_state = {}; + dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states); + dynamic_state.pDynamicStates = dynamic_states; + + VkGraphicsPipelineCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.flags = 0; + info.stageCount = 2; + info.pStages = stage; + info.pVertexInputState = &vertex_info; + info.pInputAssemblyState = &ia_info; + info.pViewportState = &viewport_info; + info.pRasterizationState = &raster_info; + info.pMultisampleState = &ms_info; + info.pDepthStencilState = &depth_info; + info.pColorBlendState = &blend_info; + info.pDynamicState = &dynamic_state; + info.layout = data->pipeline_layout; + info.renderPass = data->render_pass; + VK_CHECK( + device_data->vtable.CreateGraphicsPipelines(device_data->device, VK_NULL_HANDLE, + 1, &info, + NULL, &data->pipeline)); + + device_data->vtable.DestroyShaderModule(device_data->device, vert_module, NULL); + device_data->vtable.DestroyShaderModule(device_data->device, frag_module, NULL); + + create_fonts(device_data->instance->params, data->sw_stats.font1, data->sw_stats.font_text); + + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + + // upload default font to VkImage + io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); + io.Fonts->TexID = (ImTextureID)create_image_with_desc(data, width, height, VK_FORMAT_R8_UNORM, data->font_image, data->font_mem, data->font_image_view); +#ifndef NDEBUG + std::cerr << "MANGOHUD: Default font tex size: " << width << "x" << height << "px (" << (width*height*1) << " bytes)" << "\n"; +#endif + +// if (data->descriptor_set) +// update_image_descriptor(data, data->font_image_view[0], data->descriptor_set); +} + +// Cut from https://github.com/ocornut/imgui/pull/2943 +// Probably move to ImGui +float SRGBToLinear(float in) +{ + if (in <= 0.04045f) + return in / 12.92f; + else + return powf((in + 0.055f) / 1.055f, 2.4f); +} + +float LinearToSRGB(float in) +{ + if (in <= 0.0031308f) + return in * 12.92f; + else + return 1.055f * powf(in, 1.0f / 2.4f) - 0.055f; +} + +ImVec4 SRGBToLinear(ImVec4 col) +{ + col.x = SRGBToLinear(col.x); + col.y = SRGBToLinear(col.y); + col.z = SRGBToLinear(col.z); + // Alpha component is already linear + + return col; +} + +ImVec4 LinearToSRGB(ImVec4 col) +{ + col.x = LinearToSRGB(col.x); + col.y = LinearToSRGB(col.y); + col.z = LinearToSRGB(col.z); + // Alpha component is already linear + + return col; +} + +void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overlay_params& params) +{ + auto convert = [&do_conv](unsigned color) -> ImVec4 { + ImVec4 fc = ImGui::ColorConvertU32ToFloat4(color); + if (do_conv) + return SRGBToLinear(fc); + return fc; + }; + + sw_stats.colors.cpu = convert(params.cpu_color); + sw_stats.colors.gpu = convert(params.gpu_color); + sw_stats.colors.vram = convert(params.vram_color); + sw_stats.colors.ram = convert(params.ram_color); + sw_stats.colors.engine = convert(params.engine_color); + sw_stats.colors.io = convert(params.io_color); + sw_stats.colors.frametime = convert(params.frametime_color); + sw_stats.colors.background = convert(params.background_color); + sw_stats.colors.text = convert(params.text_color); + sw_stats.colors.media_player = convert(params.media_player_color); + sw_stats.colors.wine = convert(params.wine_color); + + ImGuiStyle& style = ImGui::GetStyle(); + style.Colors[ImGuiCol_PlotLines] = convert(params.frametime_color); + style.Colors[ImGuiCol_PlotHistogram] = convert(params.frametime_color); + style.Colors[ImGuiCol_WindowBg] = convert(params.background_color); + style.Colors[ImGuiCol_Text] = convert(params.text_color); + style.CellPadding.y = -2; +} + +// TODO probably needs colorspace check too +static void convert_colors_vk(VkFormat format, struct swapchain_stats& sw_stats, struct overlay_params& params) +{ + bool do_conv = false; + switch (format) { + case VK_FORMAT_R8_SRGB: + case VK_FORMAT_R8G8_SRGB: + case VK_FORMAT_R8G8B8_SRGB: + case VK_FORMAT_B8G8R8_SRGB: + case VK_FORMAT_R8G8B8A8_SRGB: + case VK_FORMAT_B8G8R8A8_SRGB: + case VK_FORMAT_A8B8G8R8_SRGB_PACK32: + case VK_FORMAT_BC1_RGB_SRGB_BLOCK: + case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: + case VK_FORMAT_BC2_SRGB_BLOCK: + case VK_FORMAT_BC3_SRGB_BLOCK: + case VK_FORMAT_BC7_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: + case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: + case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: + case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: + case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: + case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: + case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: + case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: + case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: + case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: + do_conv = true; + break; + default: + break; + } + + convert_colors(do_conv, sw_stats, params); +} + +static void setup_swapchain_data(struct swapchain_data *data, + const VkSwapchainCreateInfoKHR *pCreateInfo) +{ + struct device_data *device_data = data->device; + data->width = pCreateInfo->imageExtent.width; + data->height = pCreateInfo->imageExtent.height; + data->format = pCreateInfo->imageFormat; + + data->imgui_context = ImGui::CreateContext(); + ImGui::SetCurrentContext(data->imgui_context); + + ImGui::GetIO().IniFilename = NULL; + ImGui::GetIO().DisplaySize = ImVec2((float)data->width, (float)data->height); + convert_colors_vk(pCreateInfo->imageFormat, data->sw_stats, device_data->instance->params); + + /* Render pass */ + VkAttachmentDescription attachment_desc = {}; + attachment_desc.format = pCreateInfo->imageFormat; + attachment_desc.samples = VK_SAMPLE_COUNT_1_BIT; + attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachment_desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachment_desc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + VkAttachmentReference color_attachment = {}; + color_attachment.attachment = 0; + color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &color_attachment; + VkSubpassDependency dependency = {}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcAccessMask = 0; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + VkRenderPassCreateInfo render_pass_info = {}; + render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + render_pass_info.attachmentCount = 1; + render_pass_info.pAttachments = &attachment_desc; + render_pass_info.subpassCount = 1; + render_pass_info.pSubpasses = &subpass; + render_pass_info.dependencyCount = 1; + render_pass_info.pDependencies = &dependency; + VK_CHECK(device_data->vtable.CreateRenderPass(device_data->device, + &render_pass_info, + NULL, &data->render_pass)); + + setup_swapchain_data_pipeline(data); + + uint32_t n_images = 0; + VK_CHECK(device_data->vtable.GetSwapchainImagesKHR(device_data->device, + data->swapchain, + &n_images, + NULL)); + + data->images.resize(n_images); + data->image_views.resize(n_images); + data->framebuffers.resize(n_images); + + VK_CHECK(device_data->vtable.GetSwapchainImagesKHR(device_data->device, + data->swapchain, + &n_images, + data->images.data())); + + + if (n_images != data->images.size()) { + data->images.resize(n_images); + data->image_views.resize(n_images); + data->framebuffers.resize(n_images); + } + + /* Image views */ + VkImageViewCreateInfo view_info = {}; + view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + view_info.format = pCreateInfo->imageFormat; + view_info.components.r = VK_COMPONENT_SWIZZLE_R; + view_info.components.g = VK_COMPONENT_SWIZZLE_G; + view_info.components.b = VK_COMPONENT_SWIZZLE_B; + view_info.components.a = VK_COMPONENT_SWIZZLE_A; + view_info.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; + for (size_t i = 0; i < data->images.size(); i++) { + view_info.image = data->images[i]; + VK_CHECK(device_data->vtable.CreateImageView(device_data->device, + &view_info, NULL, + &data->image_views[i])); + } + + /* Framebuffers */ + VkImageView attachment[1]; + VkFramebufferCreateInfo fb_info = {}; + fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fb_info.renderPass = data->render_pass; + fb_info.attachmentCount = 1; + fb_info.pAttachments = attachment; + fb_info.width = data->width; + fb_info.height = data->height; + fb_info.layers = 1; + for (size_t i = 0; i < data->image_views.size(); i++) { + attachment[0] = data->image_views[i]; + VK_CHECK(device_data->vtable.CreateFramebuffer(device_data->device, &fb_info, + NULL, &data->framebuffers[i])); + } + + /* Command buffer pool */ + VkCommandPoolCreateInfo cmd_buffer_pool_info = {}; + cmd_buffer_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + cmd_buffer_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + cmd_buffer_pool_info.queueFamilyIndex = device_data->graphic_queue->family_index; + VK_CHECK(device_data->vtable.CreateCommandPool(device_data->device, + &cmd_buffer_pool_info, + NULL, &data->command_pool)); +} + +static void shutdown_swapchain_data(struct swapchain_data *data) +{ + struct device_data *device_data = data->device; + + for (auto draw : data->draws) { + device_data->vtable.DestroySemaphore(device_data->device, draw->cross_engine_semaphore, NULL); + device_data->vtable.DestroySemaphore(device_data->device, draw->semaphore, NULL); + device_data->vtable.DestroyFence(device_data->device, draw->fence, NULL); + device_data->vtable.DestroyBuffer(device_data->device, draw->vertex_buffer, NULL); + device_data->vtable.DestroyBuffer(device_data->device, draw->index_buffer, NULL); + device_data->vtable.FreeMemory(device_data->device, draw->vertex_buffer_mem, NULL); + device_data->vtable.FreeMemory(device_data->device, draw->index_buffer_mem, NULL); + delete draw; + } + + for (size_t i = 0; i < data->images.size(); i++) { + device_data->vtable.DestroyImageView(device_data->device, data->image_views[i], NULL); + device_data->vtable.DestroyFramebuffer(device_data->device, data->framebuffers[i], NULL); + } + + device_data->vtable.DestroyRenderPass(device_data->device, data->render_pass, NULL); + + device_data->vtable.DestroyCommandPool(device_data->device, data->command_pool, NULL); + + device_data->vtable.DestroyPipeline(device_data->device, data->pipeline, NULL); + device_data->vtable.DestroyPipelineLayout(device_data->device, data->pipeline_layout, NULL); + + device_data->vtable.DestroyDescriptorPool(device_data->device, + data->descriptor_pool, NULL); + device_data->vtable.DestroyDescriptorSetLayout(device_data->device, + data->descriptor_layout, NULL); + + device_data->vtable.DestroySampler(device_data->device, data->font_sampler, NULL); + device_data->vtable.DestroyImageView(device_data->device, data->font_image_view, NULL); + device_data->vtable.DestroyImage(device_data->device, data->font_image, NULL); + device_data->vtable.FreeMemory(device_data->device, data->font_mem, NULL); + + device_data->vtable.DestroyBuffer(device_data->device, data->upload_font_buffer, NULL); + device_data->vtable.FreeMemory(device_data->device, data->upload_font_buffer_mem, NULL); + + ImGui::DestroyContext(data->imgui_context); +} + +static struct overlay_draw *before_present(struct swapchain_data *swapchain_data, + struct queue_data *present_queue, + const VkSemaphore *wait_semaphores, + unsigned n_wait_semaphores, + unsigned imageIndex) +{ + struct overlay_draw *draw = NULL; + + snapshot_swapchain_frame(swapchain_data); + + if (swapchain_data->sw_stats.n_frames > 0) { + compute_swapchain_display(swapchain_data); + draw = render_swapchain_display(swapchain_data, present_queue, + wait_semaphores, n_wait_semaphores, + imageIndex); + } + + return draw; +} + +void get_device_name(int32_t vendorID, int32_t deviceID, struct swapchain_stats& sw_stats) +{ + string desc = pci_ids[vendorID].second[deviceID].desc; + size_t position = desc.find("["); + if (position != std::string::npos) { + desc = desc.substr(position); + string chars = "[]"; + for (char c: chars) + desc.erase(remove(desc.begin(), desc.end(), c), desc.end()); + } + sw_stats.gpuName = desc; + trim(sw_stats.gpuName); +} + +static VkResult overlay_CreateSwapchainKHR( + VkDevice device, + const VkSwapchainCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSwapchainKHR* pSwapchain) +{ + struct device_data *device_data = FIND(struct device_data, device); + array modes = {VK_PRESENT_MODE_FIFO_RELAXED_KHR, + VK_PRESENT_MODE_IMMEDIATE_KHR, + VK_PRESENT_MODE_MAILBOX_KHR, + VK_PRESENT_MODE_FIFO_KHR}; + + if (device_data->instance->params.vsync < 4) + const_cast (pCreateInfo)->presentMode = modes[device_data->instance->params.vsync]; + + VkResult result = device_data->vtable.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); + if (result != VK_SUCCESS) return result; + struct swapchain_data *swapchain_data = new_swapchain_data(*pSwapchain, device_data); + setup_swapchain_data(swapchain_data, pCreateInfo); + + const VkPhysicalDeviceProperties& prop = device_data->properties; + swapchain_data->sw_stats.version_vk.major = VK_VERSION_MAJOR(prop.apiVersion); + swapchain_data->sw_stats.version_vk.minor = VK_VERSION_MINOR(prop.apiVersion); + swapchain_data->sw_stats.version_vk.patch = VK_VERSION_PATCH(prop.apiVersion); + swapchain_data->sw_stats.engineName = device_data->instance->engineName; + swapchain_data->sw_stats.engineVersion = device_data->instance->engineVersion; + + std::stringstream ss; +// ss << prop.deviceName; + if (prop.vendorID == 0x10de) { + ss << " " << ((prop.driverVersion >> 22) & 0x3ff); + ss << "." << ((prop.driverVersion >> 14) & 0x0ff); + ss << "." << std::setw(2) << std::setfill('0') << ((prop.driverVersion >> 6) & 0x0ff); +#ifdef _WIN32 + } else if (prop.vendorID == 0x8086) { + ss << " " << (prop.driverVersion >> 14); + ss << "." << (prop.driverVersion & 0x3fff); + } +#endif + } else { + ss << " " << VK_VERSION_MAJOR(prop.driverVersion); + ss << "." << VK_VERSION_MINOR(prop.driverVersion); + ss << "." << VK_VERSION_PATCH(prop.driverVersion); + } + std::string driverVersion = ss.str(); + + std::string deviceName = prop.deviceName; + get_device_name(prop.vendorID, prop.deviceID, swapchain_data->sw_stats); + if(driverProps.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY){ + swapchain_data->sw_stats.driverName = "NVIDIA"; + } + if(driverProps.driverID == VK_DRIVER_ID_AMD_PROPRIETARY) + swapchain_data->sw_stats.driverName = "AMDGPU-PRO"; + if(driverProps.driverID == VK_DRIVER_ID_AMD_OPEN_SOURCE) + swapchain_data->sw_stats.driverName = "AMDVLK"; + if(driverProps.driverID == VK_DRIVER_ID_MESA_RADV){ + if(deviceName.find("ACO") != std::string::npos){ + swapchain_data->sw_stats.driverName = "RADV/ACO"; + } else { + swapchain_data->sw_stats.driverName = "RADV"; + } + } + + if (!swapchain_data->sw_stats.driverName.empty()) + swapchain_data->sw_stats.driverName += driverVersion; + else + swapchain_data->sw_stats.driverName = prop.deviceName + driverVersion; + + return result; +} + +static void overlay_DestroySwapchainKHR( + VkDevice device, + VkSwapchainKHR swapchain, + const VkAllocationCallbacks* pAllocator) +{ + struct swapchain_data *swapchain_data = + FIND(struct swapchain_data, swapchain); + + shutdown_swapchain_data(swapchain_data); + swapchain_data->device->vtable.DestroySwapchainKHR(device, swapchain, pAllocator); + destroy_swapchain_data(swapchain_data); +} + +void FpsLimiter(struct fps_limit& stats){ + stats.sleepTime = stats.targetFrameTime - (stats.frameStart - stats.frameEnd); + if (stats.sleepTime > stats.frameOverhead) { + 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 = Clock::duration(0); + } +} + +static VkResult overlay_QueuePresentKHR( + VkQueue queue, + const VkPresentInfoKHR* pPresentInfo) +{ + struct queue_data *queue_data = FIND(struct queue_data, queue); + + /* Otherwise we need to add our overlay drawing semaphore to the list of + * semaphores to wait on. If we don't do that the presented picture might + * be have incomplete overlay drawings. + */ + VkResult result = VK_SUCCESS; + for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { + VkSwapchainKHR swapchain = pPresentInfo->pSwapchains[i]; + struct swapchain_data *swapchain_data = + FIND(struct swapchain_data, swapchain); + + uint32_t image_index = pPresentInfo->pImageIndices[i]; + + VkPresentInfoKHR present_info = *pPresentInfo; + present_info.swapchainCount = 1; + present_info.pSwapchains = &swapchain; + present_info.pImageIndices = &image_index; + + struct overlay_draw *draw = before_present(swapchain_data, + queue_data, + pPresentInfo->pWaitSemaphores, + pPresentInfo->waitSemaphoreCount, + image_index); + + /* Because the submission of the overlay draw waits on the semaphores + * handed for present, we don't need to have this present operation + * wait on them as well, we can just wait on the overlay submission + * semaphore. + */ + if (draw) { + present_info.pWaitSemaphores = &draw->semaphore; + present_info.waitSemaphoreCount = 1; + } + + VkResult chain_result = queue_data->device->vtable.QueuePresentKHR(queue, &present_info); + if (pPresentInfo->pResults) + pPresentInfo->pResults[i] = chain_result; + if (chain_result != VK_SUCCESS && result == VK_SUCCESS) + result = chain_result; + } + + 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 = Clock::now(); + } + + return result; +} + +static VkResult overlay_BeginCommandBuffer( + VkCommandBuffer commandBuffer, + const VkCommandBufferBeginInfo* pBeginInfo) +{ + struct command_buffer_data *cmd_buffer_data = + FIND(struct command_buffer_data, commandBuffer); + struct device_data *device_data = cmd_buffer_data->device; + + /* Otherwise record a begin query as first command. */ + VkResult result = device_data->vtable.BeginCommandBuffer(commandBuffer, pBeginInfo); + + return result; +} + +static VkResult overlay_EndCommandBuffer( + VkCommandBuffer commandBuffer) +{ + struct command_buffer_data *cmd_buffer_data = + FIND(struct command_buffer_data, commandBuffer); + struct device_data *device_data = cmd_buffer_data->device; + + return device_data->vtable.EndCommandBuffer(commandBuffer); +} + +static VkResult overlay_ResetCommandBuffer( + VkCommandBuffer commandBuffer, + VkCommandBufferResetFlags flags) +{ + struct command_buffer_data *cmd_buffer_data = + FIND(struct command_buffer_data, commandBuffer); + struct device_data *device_data = cmd_buffer_data->device; + + return device_data->vtable.ResetCommandBuffer(commandBuffer, flags); +} + +static void overlay_CmdExecuteCommands( + VkCommandBuffer commandBuffer, + uint32_t commandBufferCount, + const VkCommandBuffer* pCommandBuffers) +{ + struct command_buffer_data *cmd_buffer_data = + FIND(struct command_buffer_data, commandBuffer); + struct device_data *device_data = cmd_buffer_data->device; + + device_data->vtable.CmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers); +} + +static VkResult overlay_AllocateCommandBuffers( + VkDevice device, + const VkCommandBufferAllocateInfo* pAllocateInfo, + VkCommandBuffer* pCommandBuffers) +{ + struct device_data *device_data = FIND(struct device_data, device); + VkResult result = + device_data->vtable.AllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers); + if (result != VK_SUCCESS) + return result; + + for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) { + new_command_buffer_data(pCommandBuffers[i], pAllocateInfo->level, + device_data); + } + + return result; +} + +static void overlay_FreeCommandBuffers( + VkDevice device, + VkCommandPool commandPool, + uint32_t commandBufferCount, + const VkCommandBuffer* pCommandBuffers) +{ + struct device_data *device_data = FIND(struct device_data, device); + for (uint32_t i = 0; i < commandBufferCount; i++) { + struct command_buffer_data *cmd_buffer_data = + FIND(struct command_buffer_data, pCommandBuffers[i]); + + /* It is legal to free a NULL command buffer*/ + if (!cmd_buffer_data) + continue; + + destroy_command_buffer_data(cmd_buffer_data); + } + + device_data->vtable.FreeCommandBuffers(device, commandPool, + commandBufferCount, pCommandBuffers); +} + +static VkResult overlay_QueueSubmit( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo* pSubmits, + VkFence fence) +{ + struct queue_data *queue_data = FIND(struct queue_data, queue); + struct device_data *device_data = queue_data->device; + + return device_data->vtable.QueueSubmit(queue, submitCount, pSubmits, fence); +} + +static VkResult overlay_CreateDevice( + VkPhysicalDevice physicalDevice, + const VkDeviceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDevice* pDevice) +{ + struct instance_data *instance_data = + FIND(struct instance_data, physicalDevice); + VkLayerDeviceCreateInfo *chain_info = + get_device_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); + + assert(chain_info->u.pLayerInfo); + PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; + PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; + PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice"); + if (fpCreateDevice == NULL) { + return VK_ERROR_INITIALIZATION_FAILED; + } + + // Advance the link info for the next element on the chain + chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; + + VkPhysicalDeviceFeatures device_features = {}; + VkDeviceCreateInfo device_info = *pCreateInfo; + + std::vector enabled_extensions(device_info.ppEnabledExtensionNames, + device_info.ppEnabledExtensionNames + + device_info.enabledExtensionCount); + + uint32_t extension_count; + instance_data->vtable.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extension_count, nullptr); + + std::vector available_extensions(extension_count); + instance_data->vtable.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extension_count, available_extensions.data()); + + + bool can_get_driver_info = instance_data->api_version < VK_API_VERSION_1_1 ? false : true; + + // VK_KHR_driver_properties became core in 1.2 + if (instance_data->api_version < VK_API_VERSION_1_2 && can_get_driver_info) { + for (auto& extension : available_extensions) { + if (extension.extensionName == std::string(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) { + for (auto& enabled : enabled_extensions) { + if (enabled == std::string(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) + goto DONT; + } + enabled_extensions.push_back(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME); + DONT: + goto FOUND; + } + } + can_get_driver_info = false; + FOUND:; + } + + device_info.enabledExtensionCount = enabled_extensions.size(); + device_info.ppEnabledExtensionNames = enabled_extensions.data(); + + if (pCreateInfo->pEnabledFeatures) + device_features = *(pCreateInfo->pEnabledFeatures); + device_info.pEnabledFeatures = &device_features; + + + VkResult result = fpCreateDevice(physicalDevice, &device_info, pAllocator, pDevice); + if (result != VK_SUCCESS) return result; + + struct device_data *device_data = new_device_data(*pDevice, instance_data); + device_data->physical_device = physicalDevice; + vk_load_device_commands(*pDevice, fpGetDeviceProcAddr, &device_data->vtable); + + instance_data->vtable.GetPhysicalDeviceProperties(device_data->physical_device, + &device_data->properties); + + VkLayerDeviceCreateInfo *load_data_info = + get_device_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK); + device_data->set_device_loader_data = load_data_info->u.pfnSetDeviceLoaderData; + + driverProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; + driverProps.pNext = nullptr; + if (can_get_driver_info) { + VkPhysicalDeviceProperties2 deviceProps = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, &driverProps}; + instance_data->vtable.GetPhysicalDeviceProperties2(device_data->physical_device, &deviceProps); + } + + if (!is_blacklisted()) { + device_map_queues(device_data, pCreateInfo); + + init_gpu_stats(device_data->properties.vendorID, instance_data->params); + init_system_info(); + } + + return result; +} + +static void overlay_DestroyDevice( + VkDevice device, + const VkAllocationCallbacks* pAllocator) +{ + struct device_data *device_data = FIND(struct device_data, device); + if (!is_blacklisted()) + device_unmap_queues(device_data); + device_data->vtable.DestroyDevice(device, pAllocator); + destroy_device_data(device_data); +} + +static VkResult overlay_CreateInstance( + const VkInstanceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkInstance* pInstance) +{ + VkLayerInstanceCreateInfo *chain_info = + get_instance_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); + + std::string engineName, engineVersion; + if (!is_blacklisted(true)) { + const char* pEngineName = nullptr; + if (pCreateInfo->pApplicationInfo) + pEngineName = pCreateInfo->pApplicationInfo->pEngineName; + if (pEngineName) + engineName = pEngineName; + if (engineName == "DXVK" || engineName == "vkd3d") { + int engineVer = pCreateInfo->pApplicationInfo->engineVersion; + engineVersion = to_string(VK_VERSION_MAJOR(engineVer)) + "." + to_string(VK_VERSION_MINOR(engineVer)) + "." + to_string(VK_VERSION_PATCH(engineVer)); + } + + if (engineName != "DXVK" && engineName != "vkd3d" && engineName != "Feral3D") + engineName = "VULKAN"; + + if (engineName == "vkd3d") + engineName = "VKD3D"; + } + + assert(chain_info->u.pLayerInfo); + PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = + chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; + PFN_vkCreateInstance fpCreateInstance = + (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance"); + if (fpCreateInstance == NULL) { + return VK_ERROR_INITIALIZATION_FAILED; + } + + // Advance the link info for the next element on the chain + chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; + + + VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); + if (result != VK_SUCCESS) return result; + + struct instance_data *instance_data = new_instance_data(*pInstance); + vk_load_instance_commands(instance_data->instance, + fpGetInstanceProcAddr, + &instance_data->vtable); + instance_data_map_physical_devices(instance_data, true); + + if (!is_blacklisted()) { + parse_overlay_config(&instance_data->params, getenv("MANGOHUD_CONFIG")); + instance_data->notifier.params = &instance_data->params; + start_notifier(instance_data->notifier); + + init_cpu_stats(instance_data->params); + + // Adjust height for DXVK/VKD3D version number + if (engineName == "DXVK" || engineName == "VKD3D"){ + if (instance_data->params.font_size){ + instance_data->params.height += instance_data->params.font_size * instance_data->params.font_scale / 2; + } else { + instance_data->params.height += 24 * instance_data->params.font_scale / 2; + } + } + + instance_data->engineName = engineName; + instance_data->engineVersion = engineVersion; + } + + instance_data->api_version = pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : VK_API_VERSION_1_0; + + return result; +} + +static void overlay_DestroyInstance( + VkInstance instance, + const VkAllocationCallbacks* pAllocator) +{ + struct instance_data *instance_data = FIND(struct instance_data, instance); + instance_data_map_physical_devices(instance_data, false); + instance_data->vtable.DestroyInstance(instance, pAllocator); + if (!is_blacklisted()) + stop_notifier(instance_data->notifier); + destroy_instance_data(instance_data); +} + +extern "C" VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL overlay_GetDeviceProcAddr(VkDevice dev, + const char *funcName); +static const struct { + const char *name; + void *ptr; +} name_to_funcptr_map[] = { + { "vkGetDeviceProcAddr", (void *) overlay_GetDeviceProcAddr }, +#define ADD_HOOK(fn) { "vk" # fn, (void *) overlay_ ## fn } +#define ADD_ALIAS_HOOK(alias, fn) { "vk" # alias, (void *) overlay_ ## fn } + ADD_HOOK(AllocateCommandBuffers), + ADD_HOOK(FreeCommandBuffers), + ADD_HOOK(ResetCommandBuffer), + ADD_HOOK(BeginCommandBuffer), + ADD_HOOK(EndCommandBuffer), + ADD_HOOK(CmdExecuteCommands), + + ADD_HOOK(CreateSwapchainKHR), + ADD_HOOK(QueuePresentKHR), + ADD_HOOK(DestroySwapchainKHR), + + ADD_HOOK(QueueSubmit), + + ADD_HOOK(CreateDevice), + ADD_HOOK(DestroyDevice), + + ADD_HOOK(CreateInstance), + ADD_HOOK(DestroyInstance), +#undef ADD_HOOK +}; + +static void *find_ptr(const char *name) +{ + std::string f(name); + + if (is_blacklisted() && (f != "vkCreateInstance" && f != "vkDestroyInstance" && f != "vkCreateDevice" && f != "vkDestroyDevice")) + { + return NULL; + } + + for (uint32_t i = 0; i < ARRAY_SIZE(name_to_funcptr_map); i++) { + if (strcmp(name, name_to_funcptr_map[i].name) == 0) + return name_to_funcptr_map[i].ptr; + } + + return NULL; +} + +extern "C" VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL overlay_GetDeviceProcAddr(VkDevice dev, + const char *funcName) +{ + void *ptr = find_ptr(funcName); + if (ptr) return reinterpret_cast(ptr); + + if (dev == NULL) return NULL; + + struct device_data *device_data = FIND(struct device_data, dev); + if (device_data->vtable.GetDeviceProcAddr == NULL) return NULL; + return device_data->vtable.GetDeviceProcAddr(dev, funcName); +} + +extern "C" VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL overlay_GetInstanceProcAddr(VkInstance instance, + const char *funcName) +{ + void *ptr = find_ptr(funcName); + if (ptr) return reinterpret_cast(ptr); + + if (instance == NULL) return NULL; + + struct instance_data *instance_data = FIND(struct instance_data, instance); + if (instance_data->vtable.GetInstanceProcAddr == NULL) return NULL; + return instance_data->vtable.GetInstanceProcAddr(instance, funcName); +} From 785b37534df9ed5fc6b5ae44100ee3cd60d1ab38 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sun, 6 Sep 2020 10:56:24 +0200 Subject: [PATCH 024/130] win32 file_utils --- src/file_utils_win32.cpp | 67 ++++++++++++++++++++++++++++++++++++++++ src/meson.build | 1 + 2 files changed, 68 insertions(+) create mode 100644 src/file_utils_win32.cpp diff --git a/src/file_utils_win32.cpp b/src/file_utils_win32.cpp new file mode 100644 index 00000000..211ddd89 --- /dev/null +++ b/src/file_utils_win32.cpp @@ -0,0 +1,67 @@ +#include "file_utils.h" +#include "string_utils.h" +#include +#include +#include + +std::string read_line(const std::string& filename) +{ + std::string line; + std::ifstream file(filename); + std::getline(file, line); + return line; +} + +bool find_folder(const char* root, const char* prefix, std::string& dest) +{ + return false; +} + +bool find_folder(const std::string& root, const std::string& prefix, std::string& dest) +{ + return find_folder(root.c_str(), prefix.c_str(), dest); +} + +std::vector ls(const char* root, const char* prefix, LS_FLAGS flags) +{ + std::vector list; + return list; +} + +bool file_exists(const std::string& path) +{ + return false; +} + +bool dir_exists(const std::string& path) +{ + return false; +} + +std::string get_exe_path() +{ + return std::string(); +} + +bool get_wine_exe_name(std::string& name, bool keep_ext) +{ + return false; +} + +std::string get_home_dir() +{ + std::string path; + return path; +} + +std::string get_data_dir() +{ + std::string path; + return path; +} + +std::string get_config_dir() +{ + std::string path; + return path; +} diff --git a/src/meson.build b/src/meson.build index 1c9936a7..cbecba49 100644 --- a/src/meson.build +++ b/src/meson.build @@ -34,6 +34,7 @@ vklayer_files = files( opengl_files = [] if ['windows', 'mingw'].contains(host_machine.system()) vklayer_files += files( + 'file_utils_win32.cpp', 'win/main.cpp', 'win/kiero.cpp', 'win/d3d12_hook.cpp', From 21e8d8c4025eca144451b6829e0d1ac84b7fb407 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sun, 6 Sep 2020 10:58:16 +0200 Subject: [PATCH 025/130] Move calc benchmark into overlay --- src/overlay.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/vulkan.cpp | 40 ---------------------------------------- 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/src/overlay.cpp b/src/overlay.cpp index 8bb70117..f1633b52 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "overlay.h" #include "logging.h" #include "cpu.h" @@ -8,9 +9,13 @@ #include "memory.h" #include "timing.hpp" #include "mesa/util/macros.h" +#include "string_utils.h" + +struct benchmark_stats benchmark; void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& params, uint32_t vendorID) { +#ifdef __gnu_linux__ if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_stats] || logger->is_active()) { cpuStats.UpdateCPUData(); @@ -29,6 +34,7 @@ void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& par } // get ram usage/max + if (params.enabled[OVERLAY_PARAM_ENABLED_ram] || logger->is_active()) update_meminfo(); if (params.enabled[OVERLAY_PARAM_ENABLED_io_read] || params.enabled[OVERLAY_PARAM_ENABLED_io_write]) @@ -43,6 +49,7 @@ void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& par currentLogData.cpu_load = cpuStats.GetCPUDataTotal().percent; currentLogData.cpu_temp = cpuStats.GetCPUDataTotal().temp; +#endif logger->notify_data_valid(); } @@ -87,4 +94,43 @@ void update_hud_info(struct swapchain_stats& sw_stats, struct overlay_params& pa sw_stats.last_present_time = now; sw_stats.n_frames++; sw_stats.n_frames_since_update++; +} + +void calculate_benchmark_data(void *params_void){ + overlay_params *params = reinterpret_cast(params_void); + + vector sorted = benchmark.fps_data; + std::sort(sorted.begin(), sorted.end()); + benchmark.percentile_data.clear(); + + benchmark.total = 0.f; + for (auto fps_ : sorted){ + benchmark.total = benchmark.total + fps_; + } + + size_t max_label_size = 0; + + for (std::string percentile : params->benchmark_percentiles) { + float result; + + // special case handling for a mean-based average + if (percentile == "AVG") { + result = benchmark.total / sorted.size(); + } else { + // the percentiles are already validated when they're parsed from the config. + float fraction = parse_float(percentile) / 100; + + result = sorted[(fraction * sorted.size()) - 1]; + percentile += "%"; + } + + if (percentile.length() > max_label_size) + max_label_size = percentile.length(); + + benchmark.percentile_data.push_back({percentile, result}); + } + + for (auto& entry : benchmark.percentile_data) { + entry.first.append(max_label_size - entry.first.length(), ' '); + } } \ No newline at end of file diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 51f1d2bd..beab5fc4 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -77,7 +77,6 @@ int hudFirstRow, hudSecondRow; struct fps_limit fps_limit_stats {}; VkPhysicalDeviceDriverProperties driverProps = {}; int32_t deviceID; -struct benchmark_stats benchmark; /* Mapped from VkInstace/VkPhysicalDevice */ struct instance_data { @@ -682,45 +681,6 @@ void init_system_info(){ parse_pciids(); } -void calculate_benchmark_data(void *params_void){ - overlay_params *params = reinterpret_cast(params_void); - - vector sorted = benchmark.fps_data; - sort(sorted.begin(), sorted.end()); - benchmark.percentile_data.clear(); - - benchmark.total = 0.f; - for (auto fps_ : sorted){ - benchmark.total = benchmark.total + fps_; - } - - size_t max_label_size = 0; - - for (std::string percentile : params->benchmark_percentiles) { - float result; - - // special case handling for a mean-based average - if (percentile == "AVG") { - result = benchmark.total / sorted.size(); - } else { - // the percentiles are already validated when they're parsed from the config. - float fraction = parse_float(percentile) / 100; - - result = sorted[(fraction * sorted.size()) - 1]; - percentile += "%"; - } - - if (percentile.length() > max_label_size) - max_label_size = percentile.length(); - - benchmark.percentile_data.push_back({percentile, result}); - } - - for (auto& entry : benchmark.percentile_data) { - entry.first.append(max_label_size - entry.first.length(), ' '); - } -} - static void snapshot_swapchain_frame(struct swapchain_data *data) { struct device_data *device_data = data->device; From ed466d3c9dc6a5a13817fa7ce411e7ede21c0191 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sun, 6 Sep 2020 11:41:31 +0200 Subject: [PATCH 026/130] Fix some more linux vs win compatability --- src/keybinds.h | 2 ++ src/meson.build | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/keybinds.h b/src/keybinds.h index 3943f830..e2743287 100644 --- a/src/keybinds.h +++ b/src/keybinds.h @@ -2,8 +2,10 @@ #ifndef MANGOHUD_KEYBINDS_H #define MANGOHUD_KEYBINDS_H +#ifdef HAVE_X11 #include "shared_x11.h" #include "loaders/loader_x11.h" +#endif #ifndef KeySym typedef unsigned long KeySym; diff --git a/src/meson.build b/src/meson.build index cbecba49..c5d84727 100644 --- a/src/meson.build +++ b/src/meson.build @@ -29,7 +29,10 @@ endforeach vklayer_files = files( 'overlay.cpp', 'font.cpp', - 'keybinds.cpp' + 'keybinds.cpp', + 'font_unispace.c', + 'logging.cpp', + 'config.cpp', ) opengl_files = [] if ['windows', 'mingw'].contains(host_machine.system()) @@ -46,19 +49,16 @@ if is_unixy vklayer_files += files( 'vulkan.cpp', 'overlay_params.cpp', - 'font_unispace.c', 'blacklist.cpp', 'cpu.cpp', 'file_utils.cpp', 'memory.cpp', - 'config.cpp', 'iostats.cpp', 'gpu.cpp', 'notify.cpp', 'elfhacks.cpp', 'real_dlsym.cpp', 'pci_ids.cpp', - 'logging.cpp', ) opengl_files = files( From ff5d85a4a54025fcd192a1e417c48b5fc67e9715 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sun, 6 Sep 2020 13:44:19 +0200 Subject: [PATCH 027/130] Win32 overlay_params --- src/meson.build | 1 + src/overlay_params.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/meson.build b/src/meson.build index c5d84727..3cb1d4e4 100644 --- a/src/meson.build +++ b/src/meson.build @@ -28,6 +28,7 @@ endforeach vklayer_files = files( 'overlay.cpp', + 'overlay_params.cpp', 'font.cpp', 'keybinds.cpp', 'font_unispace.c', diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index ae243f1f..7369dbb1 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -2,8 +2,10 @@ #include #include #include +#ifdef __gnu_linux__ #include #include +#endif #include "imgui.h" #include #include From cbd87585b4f6fed958ce03219ea0b4d7c6668e1b Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sun, 6 Sep 2020 13:52:18 +0200 Subject: [PATCH 028/130] Win32 cpu usage --- src/cpu_win32.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++ src/meson.build | 1 + src/overlay.cpp | 10 +++++--- 3 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 src/cpu_win32.cpp diff --git a/src/cpu_win32.cpp b/src/cpu_win32.cpp new file mode 100644 index 00000000..e6be55f4 --- /dev/null +++ b/src/cpu_win32.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include "cpu.h" +#include +#define SystemProcessorPerformanceInformation 0x8 +#define SystemBasicInformation 0x0 +FILETIME last_userTime, last_kernelTime, last_idleTime; + +uint64_t FileTimeToInt64( const FILETIME& ft ) { + ULARGE_INTEGER uli = { 0 }; + uli.LowPart = ft.dwLowDateTime; + uli.HighPart = ft.dwHighDateTime; + return uli.QuadPart; +} + +bool CPUStats::UpdateCPUData() +{ + #define NUMBER_OF_PROCESSORS (8) + #define PROCESSOR_BUFFER_SIZE (NUMBER_OF_PROCESSORS * 8) + static ULONG64 ProcessorIdleTimeBuffer [ PROCESSOR_BUFFER_SIZE ]; + + FILETIME IdleTime, KernelTime, UserTime; + static unsigned long long PrevTotal = 0; + static unsigned long long PrevIdle = 0; + static unsigned long long PrevUser = 0; + unsigned long long ThisTotal; + unsigned long long ThisIdle, ThisKernel, ThisUser; + unsigned long long TotalSinceLast, IdleSinceLast, UserSinceLast; + + + // GET THE KERNEL / USER / IDLE times. + // And oh, BTW, kernel time includes idle time + GetSystemTimes( & IdleTime, & KernelTime, & UserTime); + + ThisIdle = FileTimeToInt64(IdleTime); + ThisKernel = FileTimeToInt64 (KernelTime); + ThisUser = FileTimeToInt64 (UserTime); + + ThisTotal = ThisKernel + ThisUser; + TotalSinceLast = ThisTotal - PrevTotal; + IdleSinceLast = ThisIdle - PrevIdle; + UserSinceLast = ThisUser - PrevUser; + double Headroom; + Headroom = (double)IdleSinceLast / (double)TotalSinceLast ; + double Load; + Load = 1.0 - Headroom; + Headroom *= 100.0; // to make it percent + Load *= 100.0; // percent + + PrevTotal = ThisTotal; + PrevIdle = ThisIdle; + PrevUser = ThisUser; + + // print results to output window of VS when run in Debug + m_cpuDataTotal.percent = Load; + return true; +} +CPUStats::CPUStats() +{ +} +CPUStats::~CPUStats() +{ +} +CPUStats cpuStats; \ No newline at end of file diff --git a/src/meson.build b/src/meson.build index 3cb1d4e4..3d283107 100644 --- a/src/meson.build +++ b/src/meson.build @@ -39,6 +39,7 @@ opengl_files = [] if ['windows', 'mingw'].contains(host_machine.system()) vklayer_files += files( 'file_utils_win32.cpp', + 'cpu_win32.cpp', 'win/main.cpp', 'win/kiero.cpp', 'win/d3d12_hook.cpp', diff --git a/src/overlay.cpp b/src/overlay.cpp index f1633b52..b3a15aa5 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -12,19 +12,20 @@ #include "string_utils.h" struct benchmark_stats benchmark; +struct fps_limit fps_limit_stats {}; void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& params, uint32_t vendorID) { -#ifdef __gnu_linux__ if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_stats] || logger->is_active()) { cpuStats.UpdateCPUData(); +#ifdef __gnu_linux__ if (params.enabled[OVERLAY_PARAM_ENABLED_core_load]) cpuStats.UpdateCoreMhz(); if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_temp] || logger->is_active()) cpuStats.UpdateCpuTemp(); +#endif } - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] || logger->is_active()) { if (vendorID == 0x1002) getAmdGpuInfo(); @@ -35,21 +36,24 @@ void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& par // get ram usage/max +#ifdef __gnu_linux__ if (params.enabled[OVERLAY_PARAM_ENABLED_ram] || logger->is_active()) update_meminfo(); if (params.enabled[OVERLAY_PARAM_ENABLED_io_read] || params.enabled[OVERLAY_PARAM_ENABLED_io_write]) getIoStats(&sw_stats.io); +#endif currentLogData.gpu_load = gpu_info.load; currentLogData.gpu_temp = gpu_info.temp; currentLogData.gpu_core_clock = gpu_info.CoreClock; currentLogData.gpu_mem_clock = gpu_info.MemClock; currentLogData.gpu_vram_used = gpu_info.memoryUsed; +#ifdef __gnu_linux__ currentLogData.ram_used = memused; +#endif currentLogData.cpu_load = cpuStats.GetCPUDataTotal().percent; currentLogData.cpu_temp = cpuStats.GetCPUDataTotal().temp; -#endif logger->notify_data_valid(); } From 2ebb381166c70a788b17a7e4ef9cb3302d102213 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sun, 6 Sep 2020 13:55:02 +0200 Subject: [PATCH 029/130] Win32 d3d_shared --- src/meson.build | 5 ++--- src/vulkan.cpp | 1 - src/win/d3d12_hook.cpp | 10 +++++++--- src/win/d3d_shared.cpp | 15 +++++++++++++++ src/win/d3d_shared.h | 9 +++++++++ 5 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 src/win/d3d_shared.cpp create mode 100644 src/win/d3d_shared.h diff --git a/src/meson.build b/src/meson.build index 3d283107..9a7bb8f2 100644 --- a/src/meson.build +++ b/src/meson.build @@ -34,6 +34,7 @@ vklayer_files = files( 'font_unispace.c', 'logging.cpp', 'config.cpp', + 'gpu.cpp', ) opengl_files = [] if ['windows', 'mingw'].contains(host_machine.system()) @@ -43,20 +44,18 @@ if ['windows', 'mingw'].contains(host_machine.system()) 'win/main.cpp', 'win/kiero.cpp', 'win/d3d12_hook.cpp', - 'win/d3d_shared.cpp' + 'win/d3d_shared.cpp', ) endif if is_unixy vklayer_files += files( 'vulkan.cpp', - 'overlay_params.cpp', 'blacklist.cpp', 'cpu.cpp', 'file_utils.cpp', 'memory.cpp', 'iostats.cpp', - 'gpu.cpp', 'notify.cpp', 'elfhacks.cpp', 'real_dlsym.cpp', diff --git a/src/vulkan.cpp b/src/vulkan.cpp index beab5fc4..d450db64 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -74,7 +74,6 @@ bool open = false; string gpuString,wineVersion,wineProcess; float offset_x, offset_y, hudSpacing; int hudFirstRow, hudSecondRow; -struct fps_limit fps_limit_stats {}; VkPhysicalDeviceDriverProperties driverProps = {}; int32_t deviceID; diff --git a/src/win/d3d12_hook.cpp b/src/win/d3d12_hook.cpp index c0e9f3d0..8719a5dd 100644 --- a/src/win/d3d12_hook.cpp +++ b/src/win/d3d12_hook.cpp @@ -1,18 +1,22 @@ -#include "kiero.h" -#include "d3d12_hook.h" #include #include +#include "kiero.h" +#include "d3d12_hook.h" +#include "d3d_shared.h" +#include "../overlay.h" typedef long(__fastcall* PresentD3D12) (IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags); PresentD3D12 oPresentD3D12; long __fastcall hkPresent12(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT Flags){ - printf("d3d12 present\n"); + update_hud_info(sw_stats, params, vendorID); return oPresentD3D12(pSwapChain, SyncInterval, Flags); } void impl::d3d12::init() { + printf("init d3d12\n"); auto ret = kiero::bind(140, (void**)&oPresentD3D12, reinterpret_cast(hkPresent12)); assert(ret == kiero::Status::Success); + init_d3d_shared(); } \ No newline at end of file diff --git a/src/win/d3d_shared.cpp b/src/win/d3d_shared.cpp new file mode 100644 index 00000000..1f9da966 --- /dev/null +++ b/src/win/d3d_shared.cpp @@ -0,0 +1,15 @@ +#include "d3d_shared.h" + +bool cfg_inited = false; +ImVec2 window_size; +overlay_params params {}; +struct swapchain_stats sw_stats {}; +uint32_t vendorID; + +void init_d3d_shared(){ + if (cfg_inited) + return; + parse_overlay_config(¶ms, getenv("MANGOHUD_CONFIG")); + cfg_inited = true; + // init_cpu_stats(params); +} \ No newline at end of file diff --git a/src/win/d3d_shared.h b/src/win/d3d_shared.h new file mode 100644 index 00000000..205246de --- /dev/null +++ b/src/win/d3d_shared.h @@ -0,0 +1,9 @@ +#include "../overlay.h" + +extern bool cfg_inited; +extern ImVec2 window_size; +extern struct overlay_params params; +extern struct swapchain_stats sw_stats; +extern uint32_t vendorID; + +extern void init_d3d_shared(void); \ No newline at end of file From 7dd67927729acad155a756c0ff79a0aba7bff4e2 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Mon, 7 Sep 2020 04:38:35 +0200 Subject: [PATCH 030/130] Win32 nvapi gpu usage --- src/meson.build | 1 + src/win/d3d_shared.cpp | 1 + src/win/d3d_shared.h | 3 ++- src/win/dxgi.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/win/dxgi.cpp diff --git a/src/meson.build b/src/meson.build index 9a7bb8f2..ec9d1aa9 100644 --- a/src/meson.build +++ b/src/meson.build @@ -41,6 +41,7 @@ if ['windows', 'mingw'].contains(host_machine.system()) vklayer_files += files( 'file_utils_win32.cpp', 'cpu_win32.cpp', + 'win/dxgi.cpp', 'win/main.cpp', 'win/kiero.cpp', 'win/d3d12_hook.cpp', diff --git a/src/win/d3d_shared.cpp b/src/win/d3d_shared.cpp index 1f9da966..c826ccce 100644 --- a/src/win/d3d_shared.cpp +++ b/src/win/d3d_shared.cpp @@ -7,6 +7,7 @@ struct swapchain_stats sw_stats {}; uint32_t vendorID; void init_d3d_shared(){ + vendorID = get_device_id_dxgi(); if (cfg_inited) return; parse_overlay_config(¶ms, getenv("MANGOHUD_CONFIG")); diff --git a/src/win/d3d_shared.h b/src/win/d3d_shared.h index 205246de..75270998 100644 --- a/src/win/d3d_shared.h +++ b/src/win/d3d_shared.h @@ -6,4 +6,5 @@ extern struct overlay_params params; extern struct swapchain_stats sw_stats; extern uint32_t vendorID; -extern void init_d3d_shared(void); \ No newline at end of file +extern void init_d3d_shared(void); +extern uint32_t get_device_id_dxgi(void); \ No newline at end of file diff --git a/src/win/dxgi.cpp b/src/win/dxgi.cpp new file mode 100644 index 00000000..3c7c23cf --- /dev/null +++ b/src/win/dxgi.cpp @@ -0,0 +1,46 @@ +#include "kiero.h" +#include "windows.h" +#include +#include "kiero.h" +#include + +#ifdef _UNICODE +# define KIERO_TEXT(text) L##text +#else +# define KIERO_TEXT(text) text +#endif + +uint32_t get_device_id_dxgi(){ + printf("start get device id\n"); + HMODULE libDXGI; + if ((libDXGI = ::GetModuleHandle(KIERO_TEXT("dxgi.dll"))) == NULL){ + printf("dxgi not found\n"); + return 0; + } + auto CreateDXGIFactory = reinterpret_cast(::GetProcAddress(libDXGI, "CreateDXGIFactory")); + if (!CreateDXGIFactory) + { + printf("can't create dxgi factory\n"); + return 0; + } + IDXGIAdapter* dxgi_adapter; + IDXGIFactory* dxgi_factory; + if (((long(__stdcall*)(const IID&, void**))(CreateDXGIFactory))(__uuidof(IDXGIFactory), (void**)&dxgi_factory) < 0) + { + printf("can't assign factory\n"); + return 0; + } + DXGI_ADAPTER_DESC AdapterDesc; + int i; + for (i = 0; SUCCEEDED(dxgi_factory->EnumAdapters(i, &dxgi_adapter)); i++) { + dxgi_adapter->GetDesc(&AdapterDesc); + printf("%ls\n", AdapterDesc.Description); + if (AdapterDesc.VendorId == 0x10de) + return AdapterDesc.VendorId; + if (AdapterDesc.VendorId == 0x1002) + return AdapterDesc.VendorId; + if (AdapterDesc.VendorId == 0x8086) + return AdapterDesc.VendorId; + } + return 0; +} \ No newline at end of file From bf9132bba1cc4a670f537dfb4de61e8e41521b9e Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Mon, 7 Sep 2020 04:38:55 +0200 Subject: [PATCH 031/130] Win32 nvapi gpu usage --- src/gpu.cpp | 3 +++ src/gpu.h | 2 +- src/meson.build | 1 + src/nvapi.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/nvapi.cpp diff --git a/src/gpu.cpp b/src/gpu.cpp index 1b04df35..7d3fb69c 100644 --- a/src/gpu.cpp +++ b/src/gpu.cpp @@ -29,6 +29,9 @@ void getNvidiaGpuInfo(){ return; } #endif +#ifdef _WIN32 +nvapi_util(); +#endif } void getAmdGpuInfo(){ diff --git a/src/gpu.h b/src/gpu.h index 2c544210..73692925 100644 --- a/src/gpu.h +++ b/src/gpu.h @@ -38,5 +38,5 @@ extern struct gpuInfo gpu_info; void getNvidiaGpuInfo(void); void getAmdGpuInfo(void); - +extern void nvapi_util(); #endif //MANGOHUD_GPU_H diff --git a/src/meson.build b/src/meson.build index ec9d1aa9..f503b88a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -41,6 +41,7 @@ if ['windows', 'mingw'].contains(host_machine.system()) vklayer_files += files( 'file_utils_win32.cpp', 'cpu_win32.cpp', + 'nvapi.cpp', 'win/dxgi.cpp', 'win/main.cpp', 'win/kiero.cpp', diff --git a/src/nvapi.cpp b/src/nvapi.cpp new file mode 100644 index 00000000..5ddce7e7 --- /dev/null +++ b/src/nvapi.cpp @@ -0,0 +1,65 @@ +#include +#include +#include "nvidia_info.h" +#include "gpu.h" + +// magic numbers, do not change them +#define NVAPI_MAX_PHYSICAL_GPUS 64 +#define NVAPI_MAX_USAGES_PER_GPU 34 + +// function pointer types +typedef int *(*NvAPI_QueryInterface_t)(unsigned int offset); +typedef int (*NvAPI_Initialize_t)(); +typedef int (*NvAPI_EnumPhysicalGPUs_t)(int **handles, int *count); +typedef int (*NvAPI_GPU_GetUsages_t)(int *handle, unsigned int *usages); + +NvAPI_QueryInterface_t NvAPI_QueryInterface = NULL; +NvAPI_Initialize_t NvAPI_Initialize = NULL; +NvAPI_EnumPhysicalGPUs_t NvAPI_EnumPhysicalGPUs = NULL; +NvAPI_GPU_GetUsages_t NvAPI_GPU_GetUsages = NULL; +HMODULE hmod; +bool init_nvapi_bool; +int *gpuHandles[NVAPI_MAX_PHYSICAL_GPUS] = { NULL }; +int gpuCount = 0; +unsigned int gpuUsages[NVAPI_MAX_USAGES_PER_GPU] = { 0 }; + +bool checkNVAPI(){ + + if (MANGOHUD_ARCH == "64bit") + hmod = LoadLibraryA("nvapi64.dll"); + else + hmod = LoadLibraryA("nvapi.dll"); + if (hmod == NULL) + { + printf("Failed to load nvapi.dll"); + return false; + } + NvAPI_QueryInterface = (NvAPI_QueryInterface_t) GetProcAddress(hmod, "nvapi_QueryInterface"); + NvAPI_Initialize = (NvAPI_Initialize_t) (*NvAPI_QueryInterface)(0x0150E828); + NvAPI_EnumPhysicalGPUs = (NvAPI_EnumPhysicalGPUs_t) (*NvAPI_QueryInterface)(0xE5AC921F); + NvAPI_GPU_GetUsages = (NvAPI_GPU_GetUsages_t) (*NvAPI_QueryInterface)(0x189A1FDF); + if (NvAPI_Initialize == NULL || NvAPI_EnumPhysicalGPUs == NULL || + NvAPI_EnumPhysicalGPUs == NULL || NvAPI_GPU_GetUsages == NULL) + { + std::cerr << "Couldn't get functions in nvapi.dll" << std::endl; + return 2; + } + (*NvAPI_Initialize)(); + + int *gpuHandles[NVAPI_MAX_PHYSICAL_GPUS] = { NULL }; + + return true; +} + +void nvapi_util() +{ + if (!init_nvapi_bool){ + init_nvapi_bool = checkNVAPI(); + } + + gpuUsages[0] = (NVAPI_MAX_USAGES_PER_GPU * 4) | 0x10000; + (*NvAPI_EnumPhysicalGPUs)(gpuHandles, &gpuCount); + (*NvAPI_GPU_GetUsages)(gpuHandles[0], gpuUsages); + gpu_info.load = gpuUsages[3]; + +} \ No newline at end of file From ab469dee7815e80876a8471c205d937f3fabc935 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Mon, 7 Sep 2020 04:40:30 +0200 Subject: [PATCH 032/130] Win32 dxgi cleaning up debugging --- src/win/dxgi.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/win/dxgi.cpp b/src/win/dxgi.cpp index 3c7c23cf..72c63b05 100644 --- a/src/win/dxgi.cpp +++ b/src/win/dxgi.cpp @@ -11,7 +11,6 @@ #endif uint32_t get_device_id_dxgi(){ - printf("start get device id\n"); HMODULE libDXGI; if ((libDXGI = ::GetModuleHandle(KIERO_TEXT("dxgi.dll"))) == NULL){ printf("dxgi not found\n"); @@ -34,7 +33,6 @@ uint32_t get_device_id_dxgi(){ int i; for (i = 0; SUCCEEDED(dxgi_factory->EnumAdapters(i, &dxgi_adapter)); i++) { dxgi_adapter->GetDesc(&AdapterDesc); - printf("%ls\n", AdapterDesc.Description); if (AdapterDesc.VendorId == 0x10de) return AdapterDesc.VendorId; if (AdapterDesc.VendorId == 0x1002) From ab90abe4d4a841c5951876f2afc71ef86cd863de Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Mon, 7 Sep 2020 06:36:35 +0200 Subject: [PATCH 033/130] De-linuxify vulkan --- src/gpu.h | 1 + src/meson.build | 4 ++-- src/vulkan.cpp | 26 +++++++++++++++++++++++--- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/gpu.h b/src/gpu.h index 73692925..16122b70 100644 --- a/src/gpu.h +++ b/src/gpu.h @@ -39,4 +39,5 @@ extern struct gpuInfo gpu_info; void getNvidiaGpuInfo(void); void getAmdGpuInfo(void); extern void nvapi_util(); +extern bool checkNVAPI(); #endif //MANGOHUD_GPU_H diff --git a/src/meson.build b/src/meson.build index f503b88a..275cc7ba 100644 --- a/src/meson.build +++ b/src/meson.build @@ -35,6 +35,7 @@ vklayer_files = files( 'logging.cpp', 'config.cpp', 'gpu.cpp', + 'vulkan.cpp', ) opengl_files = [] if ['windows', 'mingw'].contains(host_machine.system()) @@ -42,6 +43,7 @@ if ['windows', 'mingw'].contains(host_machine.system()) 'file_utils_win32.cpp', 'cpu_win32.cpp', 'nvapi.cpp', + 'blacklist.cpp', 'win/dxgi.cpp', 'win/main.cpp', 'win/kiero.cpp', @@ -52,8 +54,6 @@ endif if is_unixy vklayer_files += files( - 'vulkan.cpp', - 'blacklist.cpp', 'cpu.cpp', 'file_utils.cpp', 'memory.cpp', diff --git a/src/vulkan.cpp b/src/vulkan.cpp index d450db64..264b4662 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -462,11 +462,13 @@ struct overlay_draw *get_overlay_draw(struct swapchain_data *data) void init_cpu_stats(overlay_params& params) { +#ifdef __gnu_linux__ auto& enabled = params.enabled; enabled[OVERLAY_PARAM_ENABLED_cpu_stats] = cpuStats.Init() && enabled[OVERLAY_PARAM_ENABLED_cpu_stats]; enabled[OVERLAY_PARAM_ENABLED_cpu_temp] = cpuStats.GetCpuFile() && enabled[OVERLAY_PARAM_ENABLED_cpu_temp]; +#endif } struct PCI_BUS { @@ -524,6 +526,10 @@ void init_gpu_stats(uint32_t& vendorID, overlay_params& params) if (!nvSuccess) nvSuccess = checkXNVCtrl(); #endif +#ifdef _WIN32 + if (!nvSuccess) + nvSuccess = checkNVAPI(); +#endif if(not nvSuccess) { params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] = false; @@ -532,7 +538,7 @@ void init_gpu_stats(uint32_t& vendorID, overlay_params& params) vendorID = 0x10de; } } - +#ifdef __gnu_linux__ if (vendorID == 0x8086 || vendorID == 0x1002 || gpu.find("Radeon") != std::string::npos || gpu.find("AMD") != std::string::npos) { @@ -598,11 +604,13 @@ void init_gpu_stats(uint32_t& vendorID, overlay_params& params) params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] = false; } } +#endif if (!params.permit_upload) printf("MANGOHUD: Uploading is disabled (permit_upload = 0)\n"); } void init_system_info(){ + #ifdef __gnu_linux__ const char* ld_preload = getenv("LD_PRELOAD"); if (ld_preload) unsetenv("LD_PRELOAD"); @@ -678,6 +686,7 @@ void init_system_info(){ << "Driver:" << driver << std::endl; #endif parse_pciids(); +#endif } static void snapshot_swapchain_frame(struct swapchain_data *data) @@ -1155,6 +1164,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::PopFont(); } } +#ifdef __gnu_linux__ if (params.enabled[OVERLAY_PARAM_ENABLED_ram]){ ImGui::TableNextRow(); ImGui::TextColored(data.colors.ram, "RAM"); @@ -1165,6 +1175,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::Text("GiB"); ImGui::PopFont(); } +#endif if (params.enabled[OVERLAY_PARAM_ENABLED_fps]){ ImGui::TableNextRow(); ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); @@ -1305,10 +1316,12 @@ static void compute_swapchain_display(struct swapchain_data *data) { scoped_lock lk(instance_data->notifier.mutex); position_layer(data->sw_stats, instance_data->params, data->window_size); +#ifdef __gnu_linux__ if(instance_data->params.render_mango) render_mango(data->sw_stats, instance_data->params, data->window_size, true); else render_imgui(data->sw_stats, instance_data->params, data->window_size, true); +#endif } ImGui::PopStyleVar(3); @@ -2337,6 +2350,7 @@ static struct overlay_draw *before_present(struct swapchain_data *swapchain_data void get_device_name(int32_t vendorID, int32_t deviceID, struct swapchain_stats& sw_stats) { +#ifdef __gnu_linux__ string desc = pci_ids[vendorID].second[deviceID].desc; size_t position = desc.find("["); if (position != std::string::npos) { @@ -2347,6 +2361,7 @@ void get_device_name(int32_t vendorID, int32_t deviceID, struct swapchain_stats& } sw_stats.gpuName = desc; trim(sw_stats.gpuName); +#endif } static VkResult overlay_CreateSwapchainKHR( @@ -2382,13 +2397,14 @@ static VkResult overlay_CreateSwapchainKHR( ss << " " << ((prop.driverVersion >> 22) & 0x3ff); ss << "." << ((prop.driverVersion >> 14) & 0x0ff); ss << "." << std::setw(2) << std::setfill('0') << ((prop.driverVersion >> 6) & 0x0ff); + } #ifdef _WIN32 - } else if (prop.vendorID == 0x8086) { + else if (prop.vendorID == 0x8086) { ss << " " << (prop.driverVersion >> 14); ss << "." << (prop.driverVersion & 0x3fff); } #endif - } else { + else { ss << " " << VK_VERSION_MAJOR(prop.driverVersion); ss << "." << VK_VERSION_MINOR(prop.driverVersion); ss << "." << VK_VERSION_PATCH(prop.driverVersion); @@ -2757,8 +2773,10 @@ static VkResult overlay_CreateInstance( if (!is_blacklisted()) { parse_overlay_config(&instance_data->params, getenv("MANGOHUD_CONFIG")); +#ifdef __gnu_linux__ instance_data->notifier.params = &instance_data->params; start_notifier(instance_data->notifier); +#endif init_cpu_stats(instance_data->params); @@ -2788,7 +2806,9 @@ static void overlay_DestroyInstance( instance_data_map_physical_devices(instance_data, false); instance_data->vtable.DestroyInstance(instance, pAllocator); if (!is_blacklisted()) +#ifdef __gnu_linux__ stop_notifier(instance_data->notifier); +#endif destroy_instance_data(instance_data); } From 2f55f52011f37a8ed99840822b544daa46038dc3 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Mon, 7 Sep 2020 06:37:27 +0200 Subject: [PATCH 034/130] Allow blacklist for unix too --- src/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meson.build b/src/meson.build index 275cc7ba..52518b1c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -36,6 +36,7 @@ vklayer_files = files( 'config.cpp', 'gpu.cpp', 'vulkan.cpp', + 'blacklist.cpp', ) opengl_files = [] if ['windows', 'mingw'].contains(host_machine.system()) @@ -43,7 +44,6 @@ if ['windows', 'mingw'].contains(host_machine.system()) 'file_utils_win32.cpp', 'cpu_win32.cpp', 'nvapi.cpp', - 'blacklist.cpp', 'win/dxgi.cpp', 'win/main.cpp', 'win/kiero.cpp', From dd741cdda3aa1be68f72a378895255a1d84abb7b Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sat, 6 Jun 2020 04:53:50 +0200 Subject: [PATCH 035/130] Assume MangoHud.conf in C:\ root on win32 --- src/config.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/config.cpp b/src/config.cpp index a78738d7..7d33106b 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -37,7 +37,9 @@ void enumerate_config_files(std::vector& paths) if (!env_config.empty()) paths.push_back(env_config + mangohud_dir + "MangoHud.conf"); - +#ifdef _WIN32 + paths.push_back("C:\\MangoHud.conf"); +#endif std::string exe_path = get_exe_path(); auto n = exe_path.find_last_of('/'); if (!exe_path.empty() && n != std::string::npos && n < exe_path.size() - 1) { From 86703ee364944ca335ae002d02e9b55dad2f461c Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Mon, 7 Sep 2020 07:26:53 +0200 Subject: [PATCH 036/130] Win32 keybinds --- src/keybinds.cpp | 12 ++++++------ src/keybinds.h | 18 ++++++++++++++++++ src/overlay_params.cpp | 18 ++++++++++++++++++ src/win/d3d12_hook.cpp | 1 + 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/keybinds.cpp b/src/keybinds.cpp index d9550480..0285afe0 100644 --- a/src/keybinds.cpp +++ b/src/keybinds.cpp @@ -15,14 +15,14 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par auto keyPressDelay = 500ms; if (elapsedF2 >= keyPressDelay){ -#ifdef HAVE_X11 +#if defined(HAVE_X11) || defined(_WIN32) pressed = keys_are_pressed(params.toggle_logging); #else pressed = false; #endif if (pressed && (now - logger->last_log_end() > 11s)) { last_f2_press = now; - + printf("pressed\n"); if (logger->is_active()) { logger->stop_logging(); } else { @@ -36,7 +36,7 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par } if (elapsedF12 >= keyPressDelay){ -#ifdef HAVE_X11 +#if defined(HAVE_X11) || defined(_WIN32) pressed = keys_are_pressed(params.toggle_hud); #else pressed = false; @@ -48,7 +48,7 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par } if (elapsedReloadCfg >= keyPressDelay){ -#ifdef HAVE_X11 +#if defined(HAVE_X11) || defined(_WIN32) pressed = keys_are_pressed(params.reload_cfg); #else pressed = false; @@ -60,7 +60,7 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par } if (params.permit_upload && elapsedUpload >= keyPressDelay){ -#ifdef HAVE_X11 +#if defined(HAVE_X11) || defined(_WIN32) pressed = keys_are_pressed(params.upload_log); #else pressed = false; @@ -71,7 +71,7 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par } } if (params.permit_upload && elapsedUpload >= keyPressDelay){ -#ifdef HAVE_X11 +#if defined(HAVE_X11) || defined(_WIN32) pressed = keys_are_pressed(params.upload_logs); #else pressed = false; diff --git a/src/keybinds.h b/src/keybinds.h index e2743287..6aec3e58 100644 --- a/src/keybinds.h +++ b/src/keybinds.h @@ -41,4 +41,22 @@ bool keys_are_pressed(const std::vector& keys) { } #endif //HAVE_X11 +#ifdef _WIN32 +#include +bool keys_are_pressed(const std::vector& keys) { + size_t pressed = 0; + + for (KeySym ks : keys) { + if (GetAsyncKeyState(ks) & 0x8000) + pressed++; + } + + if (pressed > 0 && pressed == keys.size()) { + return true; + } + + return false; +} +#endif + #endif //MANGOHUD_KEYBINDS_H \ No newline at end of file diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 7369dbb1..4eacd9c6 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -1,3 +1,6 @@ +#ifdef _WIN32 +#include +#endif #include #include #include @@ -498,6 +501,21 @@ parse_overlay_config(struct overlay_params *params, params->upload_logs = { XK_Control_L, XK_F3 }; #endif +#ifdef _WIN32 + params->toggle_hud = { VK_F12 }; + params->toggle_logging = { VK_F2 }; + params->reload_cfg = { VK_F4 }; + + #undef parse_toggle_hud + #undef parse_toggle_logging + #undef parse_reload_cfg + + #define parse_toggle_hud(x) params->toggle_hud + #define parse_toggle_logging(x) params->toggle_logging + #define parse_reload_cfg(x) params->reload_cfg +#endif + + // first pass with env var if (env) parse_overlay_env(params, env); diff --git a/src/win/d3d12_hook.cpp b/src/win/d3d12_hook.cpp index 8719a5dd..58980111 100644 --- a/src/win/d3d12_hook.cpp +++ b/src/win/d3d12_hook.cpp @@ -9,6 +9,7 @@ typedef long(__fastcall* PresentD3D12) (IDXGISwapChain* pSwapChain, UINT SyncInt PresentD3D12 oPresentD3D12; long __fastcall hkPresent12(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT Flags){ + check_keybinds(sw_stats, params, vendorID); update_hud_info(sw_stats, params, vendorID); return oPresentD3D12(pSwapChain, SyncInterval, Flags); } From ac821df7faef5c2457b7575c204f77ebcf3b1448 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Mon, 7 Sep 2020 07:49:14 +0200 Subject: [PATCH 037/130] Win32 basic d3d11 present hook --- src/keybinds.cpp | 1 - src/meson.build | 1 + src/win/d3d11_hook.cpp | 28 ++++++++++++++++++++++++++++ src/win/d3d11_hook.h | 13 +++++++++++++ src/win/d3d12_hook.cpp | 3 +-- src/win/d3d_shared.cpp | 6 ++++++ src/win/d3d_shared.h | 1 + src/win/kiero.cpp | 4 ++-- src/win/kiero.h | 2 +- src/win/main.cpp | 9 ++++++++- 10 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 src/win/d3d11_hook.cpp create mode 100644 src/win/d3d11_hook.h diff --git a/src/keybinds.cpp b/src/keybinds.cpp index 0285afe0..7cc579b8 100644 --- a/src/keybinds.cpp +++ b/src/keybinds.cpp @@ -22,7 +22,6 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par #endif if (pressed && (now - logger->last_log_end() > 11s)) { last_f2_press = now; - printf("pressed\n"); if (logger->is_active()) { logger->stop_logging(); } else { diff --git a/src/meson.build b/src/meson.build index 52518b1c..6f02da73 100644 --- a/src/meson.build +++ b/src/meson.build @@ -48,6 +48,7 @@ if ['windows', 'mingw'].contains(host_machine.system()) 'win/main.cpp', 'win/kiero.cpp', 'win/d3d12_hook.cpp', + 'win/d3d11_hook.cpp', 'win/d3d_shared.cpp', ) endif diff --git a/src/win/d3d11_hook.cpp b/src/win/d3d11_hook.cpp new file mode 100644 index 00000000..c1a48aaa --- /dev/null +++ b/src/win/d3d11_hook.cpp @@ -0,0 +1,28 @@ +#include "kiero.h" + +#if KIERO_INCLUDE_D3D11 + +#include "d3d11_hook.h" +#include +#include + +#include "d3d_shared.h" + +typedef long(__stdcall* Present)(IDXGISwapChain*, UINT, UINT); +static Present oPresent = NULL; + +long __stdcall hkPresent11(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags) +{ + d3d_run(); + return oPresent(pSwapChain, SyncInterval, Flags); +} + +void impl::d3d11::init() +{ + printf("init d3d11\n"); + auto ret = kiero::bind(8, (void**)&oPresent, reinterpret_cast(hkPresent11)); + assert(ret == kiero::Status::Success); + init_d3d_shared(); +} + +#endif // KIERO_INCLUDE_D3D11 \ No newline at end of file diff --git a/src/win/d3d11_hook.h b/src/win/d3d11_hook.h new file mode 100644 index 00000000..d0c1a8e1 --- /dev/null +++ b/src/win/d3d11_hook.h @@ -0,0 +1,13 @@ +#ifndef __D3D11_IMPL_H__ +#define __D3D11_IMPL_H__ + +namespace impl +{ + namespace d3d11 + { + void init(); + } +} + + +#endif // __D3D11_IMPL_H__ \ No newline at end of file diff --git a/src/win/d3d12_hook.cpp b/src/win/d3d12_hook.cpp index 58980111..44148aad 100644 --- a/src/win/d3d12_hook.cpp +++ b/src/win/d3d12_hook.cpp @@ -9,8 +9,7 @@ typedef long(__fastcall* PresentD3D12) (IDXGISwapChain* pSwapChain, UINT SyncInt PresentD3D12 oPresentD3D12; long __fastcall hkPresent12(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT Flags){ - check_keybinds(sw_stats, params, vendorID); - update_hud_info(sw_stats, params, vendorID); + d3d_run(); return oPresentD3D12(pSwapChain, SyncInterval, Flags); } diff --git a/src/win/d3d_shared.cpp b/src/win/d3d_shared.cpp index c826ccce..cb60c07d 100644 --- a/src/win/d3d_shared.cpp +++ b/src/win/d3d_shared.cpp @@ -1,4 +1,5 @@ #include "d3d_shared.h" +#include "overlay.h" bool cfg_inited = false; ImVec2 window_size; @@ -13,4 +14,9 @@ void init_d3d_shared(){ parse_overlay_config(¶ms, getenv("MANGOHUD_CONFIG")); cfg_inited = true; // init_cpu_stats(params); +} + +void d3d_run(){ + check_keybinds(sw_stats, params, vendorID); + update_hud_info(sw_stats, params, vendorID); } \ No newline at end of file diff --git a/src/win/d3d_shared.h b/src/win/d3d_shared.h index 75270998..ff087424 100644 --- a/src/win/d3d_shared.h +++ b/src/win/d3d_shared.h @@ -7,4 +7,5 @@ extern struct swapchain_stats sw_stats; extern uint32_t vendorID; extern void init_d3d_shared(void); +extern void d3d_run(void); extern uint32_t get_device_id_dxgi(void); \ No newline at end of file diff --git a/src/win/kiero.cpp b/src/win/kiero.cpp index 61f77189..2401327c 100644 --- a/src/win/kiero.cpp +++ b/src/win/kiero.cpp @@ -281,8 +281,8 @@ kiero::Status::Enum kiero::init(RenderType::Enum _renderType) return Status::ModuleNotFoundError; } - void* D3D11CreateDeviceAndSwapChain; - if ((D3D11CreateDeviceAndSwapChain = ::GetProcAddress(libD3D11, "D3D11CreateDeviceAndSwapChain")) == NULL) + auto D3D11CreateDeviceAndSwapChain = reinterpret_cast(::GetProcAddress(libD3D11, "D3D11CreateDeviceAndSwapChain")); + if (!D3D11CreateDeviceAndSwapChain) { ::DestroyWindow(window); ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); diff --git a/src/win/kiero.h b/src/win/kiero.h index 3d275226..3fe6c015 100644 --- a/src/win/kiero.h +++ b/src/win/kiero.h @@ -7,7 +7,7 @@ #define KIERO_INCLUDE_D3D9 0 // 1 if you need D3D9 hook #define KIERO_INCLUDE_D3D10 0 // 1 if you need D3D10 hook -#define KIERO_INCLUDE_D3D11 0 // 1 if you need D3D11 hook +#define KIERO_INCLUDE_D3D11 1 // 1 if you need D3D11 hook #define KIERO_INCLUDE_D3D12 1 // 1 if you need D3D12 hook #define KIERO_INCLUDE_OPENGL 0 // 1 if you need OpenGL hook #define KIERO_INCLUDE_VULKAN 1 // 1 if you need Vulkan hook diff --git a/src/win/main.cpp b/src/win/main.cpp index 26f7293e..16454780 100644 --- a/src/win/main.cpp +++ b/src/win/main.cpp @@ -1,7 +1,9 @@ #include "windows.h" #include #include "kiero.h" - +#if KIERO_INCLUDE_D3D11 +# include "d3d11_hook.h" +#endif #if KIERO_INCLUDE_D3D12 # include "d3d12_hook.h" #endif @@ -24,6 +26,11 @@ int MainThread() { switch (kiero::getRenderType()) { +#if KIERO_INCLUDE_D3D11 + case kiero::RenderType::D3D11: + impl::d3d11::init(); + break; +#endif #if KIERO_INCLUDE_D3D12 case kiero::RenderType::D3D12: impl::d3d12::init(); From 84e64c80b5e64060c9702c1d0cb426dda8158238 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Mon, 7 Sep 2020 08:29:44 +0200 Subject: [PATCH 038/130] Win32 d3d11 make sure we don't update hud unnecessarily --- src/win/d3d11_hook.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/win/d3d11_hook.cpp b/src/win/d3d11_hook.cpp index c1a48aaa..a454f805 100644 --- a/src/win/d3d11_hook.cpp +++ b/src/win/d3d11_hook.cpp @@ -13,7 +13,15 @@ static Present oPresent = NULL; long __stdcall hkPresent11(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags) { - d3d_run(); +#ifdef _MSC_VER + static auto addr = _ReturnAddress(); + if(addr == _ReturnAddress()){ +#else + static auto addr = __builtin_return_address(0); + if(addr == __builtin_return_address(0)){ +#endif + d3d_run(); + } return oPresent(pSwapChain, SyncInterval, Flags); } From bb6f7ab3a84f33d54efe74093cd4cfbcf0f3c2c4 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Tue, 8 Sep 2020 20:22:09 +0200 Subject: [PATCH 039/130] Win32 mingw cross files --- mingw32.txt | 1041 +++++++++++++++++++++++++++++++++++++++++++++++++++ mingw64.txt | 18 + 2 files changed, 1059 insertions(+) create mode 100644 mingw32.txt create mode 100644 mingw64.txt diff --git a/mingw32.txt b/mingw32.txt new file mode 100644 index 00000000..b3dedbe1 --- /dev/null +++ b/mingw32.txt @@ -0,0 +1,1041 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MangoHud/mingw32.txt at d3d12 · flightlessmango/MangoHud · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + + +
+
+
+ + + + + + + + + + + + + +
+ +
+ +
+

+ + + / + + MangoHud + + +

+ + +
+ + + +
+ + +
+ +
+
+ + + + + + + Permalink + + + + + +
+ +
+
+ + + d3d12 + + + + +
+ + + +
+
+
+ +
+ + + + Go to file + + +
+ + + + + + + +
+ + + +
+ +
+
+
 
+
+ +
+
 
+ Cannot retrieve contributors at this time +
+
+ + + + + + +
+ +
+
+ + 18 lines (16 sloc) + + 417 Bytes +
+ +
+ +
+ Raw + Blame +
+ + +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
[binaries]
c = 'i686-w64-mingw32-gcc'
cpp = 'i686-w64-mingw32-g++'
ar = 'i686-w64-mingw32-ar'
strip = 'i686-w64-mingw32-strip'
+
[properties]
c_args=['-msse', '-msse2']
cpp_args=['-msse', '-msse2']
c_link_args = ['-static', '-static-libgcc']
cpp_link_args = ['-static', '-static-libgcc', '-static-libstdc++']
needs_exe_wrapper = true
+
[host_machine]
system = 'windows'
cpu_family = 'x86'
cpu = 'x86'
endian = 'little'
+ + + +
+ +
+ + + + +
+ + +
+ + +
+
+ + + + +
+
+ +
+
+ +
+ + + + + + +
+ + + You can’t perform that action at this time. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mingw64.txt b/mingw64.txt new file mode 100644 index 00000000..c43a4a53 --- /dev/null +++ b/mingw64.txt @@ -0,0 +1,18 @@ +[binaries] +c = 'x86_64-w64-mingw32-gcc' +cpp = 'x86_64-w64-mingw32-g++' +ar = 'x86_64-w64-mingw32-ar' +strip = 'x86_64-w64-mingw32-strip' +pkgconfig = 'x86_64-w64-mingw32-pkg-config' +sh = '/usr/bin/sh' + +[properties] +c_link_args = ['-static', '-static-libgcc'] +cpp_link_args = ['-static', '-static-libgcc', '-static-libstdc++'] +needs_exe_wrapper = true + +[host_machine] +system = 'windows' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' From 3ef4cf54538314e291c620ad4aa1a175fe9f5f7c Mon Sep 17 00:00:00 2001 From: jackun Date: Wed, 9 Sep 2020 10:39:42 +0300 Subject: [PATCH 040/130] win32: load correct NVAPI dll by checking _WIN64 --- src/nvapi.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/nvapi.cpp b/src/nvapi.cpp index 5ddce7e7..19e909e1 100644 --- a/src/nvapi.cpp +++ b/src/nvapi.cpp @@ -25,10 +25,12 @@ unsigned int gpuUsages[NVAPI_MAX_USAGES_PER_GPU] = { 0 }; bool checkNVAPI(){ - if (MANGOHUD_ARCH == "64bit") - hmod = LoadLibraryA("nvapi64.dll"); - else - hmod = LoadLibraryA("nvapi.dll"); +#if _WIN64 + hmod = LoadLibraryA("nvapi64.dll"); +#else + hmod = LoadLibraryA("nvapi.dll"); +#endif + if (hmod == NULL) { printf("Failed to load nvapi.dll"); From a6dc259ea4ca8c9b7ac13f6db1db0889a6cc082f Mon Sep 17 00:00:00 2001 From: jackun Date: Wed, 9 Sep 2020 10:43:24 +0300 Subject: [PATCH 041/130] Remove unused sysinfo header --- src/overlay_params.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 4eacd9c6..ba10d23c 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -6,7 +6,6 @@ #include #include #ifdef __gnu_linux__ -#include #include #endif #include "imgui.h" From c15133b82fd1ec7555c860008d6bf4f3bc49ccd8 Mon Sep 17 00:00:00 2001 From: jackun Date: Wed, 9 Sep 2020 11:24:24 +0300 Subject: [PATCH 042/130] Add `checkNvidia` for nvml/xnvctrl/nvapi checks, for header cleanup --- src/gpu.cpp | 22 +++++++++++++++++++++- src/gpu.h | 8 +------- src/vulkan.cpp | 22 ++++------------------ 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/gpu.cpp b/src/gpu.cpp index 7d3fb69c..57724f38 100644 --- a/src/gpu.cpp +++ b/src/gpu.cpp @@ -1,9 +1,29 @@ -#include "memory.h" #include "gpu.h" +#include +#include "nvctrl.h" +#ifdef HAVE_NVML +#include "nvidia_info.h" +#endif struct gpuInfo gpu_info; amdgpu_files amdgpu {}; +bool checkNvidia(const char *pci_dev){ + bool nvSuccess = false; +#ifdef HAVE_NVML + nvSuccess = checkNVML(pci_dev) && getNVMLInfo(); +#endif +#ifdef HAVE_XNVCTRL + if (!nvSuccess) + nvSuccess = checkXNVCtrl(); +#endif +#ifdef _WIN32 + if (!nvSuccess) + nvSuccess = checkNVAPI(); +#endif + return nvSuccess; +} + void getNvidiaGpuInfo(){ #ifdef HAVE_NVML if (nvmlSuccess){ diff --git a/src/gpu.h b/src/gpu.h index 16122b70..8c2b0638 100644 --- a/src/gpu.h +++ b/src/gpu.h @@ -2,14 +2,7 @@ #ifndef MANGOHUD_GPU_H #define MANGOHUD_GPU_H -#include -#include -#include #include -#include "nvctrl.h" -#ifdef HAVE_NVML -#include "nvidia_info.h" -#endif struct amdgpu_files { @@ -38,6 +31,7 @@ extern struct gpuInfo gpu_info; void getNvidiaGpuInfo(void); void getAmdGpuInfo(void); +bool checkNvidia(const char *pci_dev); extern void nvapi_util(); extern bool checkNVAPI(); #endif //MANGOHUD_GPU_H diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 264b4662..eb44764e 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -518,26 +518,12 @@ void init_gpu_stats(uint32_t& vendorID, overlay_params& params) if (vendorID == 0x8086 || vendorID == 0x10de) { - bool nvSuccess = false; -#ifdef HAVE_NVML - nvSuccess = checkNVML(pci_dev) && getNVMLInfo(); -#endif -#ifdef HAVE_XNVCTRL - if (!nvSuccess) - nvSuccess = checkXNVCtrl(); -#endif -#ifdef _WIN32 - if (!nvSuccess) - nvSuccess = checkNVAPI(); -#endif - - if(not nvSuccess) { - params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] = false; - } - else { + if(checkNvidia(pci_dev)) vendorID = 0x10de; - } + else + params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] = false; } + #ifdef __gnu_linux__ if (vendorID == 0x8086 || vendorID == 0x1002 || gpu.find("Radeon") != std::string::npos From 63b50abeded5099910f3a70df820266628d3fac6 Mon Sep 17 00:00:00 2001 From: jackun Date: Fri, 11 Sep 2020 10:47:26 +0300 Subject: [PATCH 043/130] Try out tls/x86_64, tls/i686 for less symlinking --- bin/mangohud-setup.sh | 15 +++++---------- build.sh | 15 +++++---------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/bin/mangohud-setup.sh b/bin/mangohud-setup.sh index e5f10e5f..da5ec320 100755 --- a/bin/mangohud-setup.sh +++ b/bin/mangohud-setup.sh @@ -55,16 +55,11 @@ mangohud_install() { install -vm755 ./usr/bin/mangohud /usr/bin/mangohud # FIXME get the triplet somehow - ln -sv lib /usr/lib/mangohud/lib64 - ln -sv lib /usr/lib/mangohud/x86_64 - ln -sv lib /usr/lib/mangohud/x86_64-linux-gnu - ln -sv . /usr/lib/mangohud/lib/x86_64 - ln -sv . /usr/lib/mangohud/lib/x86_64-linux-gnu - ln -sv lib32 /usr/lib/mangohud/i686 - ln -sv lib32 /usr/lib/mangohud/i386-linux-gnu - ln -sv ../lib32 /usr/lib/mangohud/lib/i386-linux-gnu - ln -sv lib32 /usr/lib/mangohud/i686-linux-gnu - ln -sv ../lib32 /usr/lib/mangohud/lib/i686-linux-gnu + mkdir -p /usr/lib/mangohud/tls + ln -sv ../lib /usr/lib/mangohud/tls/x86_64 + ln -sv ../lib32 /usr/lib/mangohud/tls/i686 + # $LIB can be "lib/tls/x86_64"? + ln -sv ../tls /usr/lib/mangohud/lib/tls #ln -sv lib /usr/lib/mangohud/aarch64-linux-gnu #ln -sv lib /usr/lib/mangohud/arm-linux-gnueabihf diff --git a/build.sh b/build.sh index a828809f..05b08462 100755 --- a/build.sh +++ b/build.sh @@ -214,16 +214,11 @@ install() { /usr/bin/install -vm755 ./build/release/usr/bin/mangohud /usr/bin/mangohud # FIXME get the triplet somehow - ln -sv lib /usr/lib/mangohud/lib64 - ln -sv lib /usr/lib/mangohud/x86_64 - ln -sv lib /usr/lib/mangohud/x86_64-linux-gnu - ln -sv . /usr/lib/mangohud/lib/x86_64 - ln -sv . /usr/lib/mangohud/lib/x86_64-linux-gnu - ln -sv lib32 /usr/lib/mangohud/i686 - ln -sv lib32 /usr/lib/mangohud/i386-linux-gnu - ln -sv ../lib32 /usr/lib/mangohud/lib/i386-linux-gnu - ln -sv lib32 /usr/lib/mangohud/i686-linux-gnu - ln -sv ../lib32 /usr/lib/mangohud/lib/i686-linux-gnu + mkdir -p /usr/lib/mangohud/tls + ln -sv ../lib /usr/lib/mangohud/tls/x86_64 + ln -sv ../lib32 /usr/lib/mangohud/tls/i686 + # $LIB can be "lib/tls/x86_64"? + ln -sv ../tls /usr/lib/mangohud/lib/tls #ln -sv lib /usr/lib/mangohud/aarch64-linux-gnu #ln -sv lib /usr/lib/mangohud/arm-linux-gnueabihf From e25ffbafe0ea5faa1df968a2824e2f854f3085e5 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Thu, 17 Sep 2020 17:48:36 +0200 Subject: [PATCH 044/130] Scale cellpadding based on font_size --- src/vulkan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vulkan.cpp b/src/vulkan.cpp index eb44764e..6a211140 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -2103,7 +2103,7 @@ void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overl style.Colors[ImGuiCol_PlotHistogram] = convert(params.frametime_color); style.Colors[ImGuiCol_WindowBg] = convert(params.background_color); style.Colors[ImGuiCol_Text] = convert(params.text_color); - style.CellPadding.y = -2; + style.CellPadding.y = -0.085 * params.font_size; } // TODO probably needs colorspace check too From d86a05d3a0425381ab54e9ee1b9daf02acd7a120 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Thu, 17 Sep 2020 18:37:02 +0200 Subject: [PATCH 045/130] Don't log twice if interval is 0 --- src/vulkan.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 6a211140..c2a78cd3 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -999,9 +999,6 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size = ImVec2(params.width, params.height); unsigned height = ImGui::GetIO().DisplaySize.y; auto now = Clock::now(); - if (params.log_interval == 0){ - logger->try_log(); - } if (old_scale != params.font_scale) { ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; From 73e6e3130188806a4590a7f5f65e1bf2908b087f Mon Sep 17 00:00:00 2001 From: ZakMcKrack3n <30725358+ZakMcKrack3n@users.noreply.github.com> Date: Mon, 17 Aug 2020 08:09:01 +0200 Subject: [PATCH 046/130] toggle fps limiter via hotkey, fps_limit may be set to multiple values (e.g. 0,30,60). fps toggle toggles between entries where zero means unlimited --- src/keybinds.cpp | 28 +++++++++++++++++- src/keybinds.h | 2 +- src/overlay.cpp | 2 +- src/overlay_params.cpp | 65 ++++++++++++++++++++---------------------- src/overlay_params.h | 4 ++- 5 files changed, 63 insertions(+), 38 deletions(-) diff --git a/src/keybinds.cpp b/src/keybinds.cpp index 7cc579b8..b2a3ccdd 100644 --- a/src/keybinds.cpp +++ b/src/keybinds.cpp @@ -8,6 +8,7 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par bool pressed = false; // FIXME just a placeholder until wayland support auto now = Clock::now(); /* us */ auto elapsedF2 = now - last_f2_press; + auto elapsedF3 = now - last_f3_press; auto elapsedF12 = now - last_f12_press; auto elapsedReloadCfg = now - reload_cfg_press; auto elapsedUpload = now - last_upload_press; @@ -34,6 +35,31 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par } } + if (elapsedF3 >= keyPressDelay){ +#if defined(HAVE_X11) || defined(_WIN32) + pressed = keys_are_pressed(params.toggle_fps_limit); +#else + pressed = false; +#endif + if (pressed){ + last_f3_press = now; + for (size_t i = 0; i < params.fps_limit.size(); i++){ + uint32_t fps_limit = params.fps_limit[i]; + // current fps limit equals vector entry, use next / first + if((fps_limit > 0 && fps_limit_stats.targetFrameTime == std::chrono::duration_cast(std::chrono::duration(1) / params.fps_limit[i])) + || (fps_limit == 0 && fps_limit_stats.targetFrameTime == fps_limit_stats.targetFrameTime.zero())) { + uint32_t newFpsLimit = i+1 == params.fps_limit.size() ? params.fps_limit[0] : params.fps_limit[i+1]; + if(newFpsLimit > 0) { + fps_limit_stats.targetFrameTime = std::chrono::duration_cast(std::chrono::duration(1) / newFpsLimit); + } else { + fps_limit_stats.targetFrameTime = {}; + } + break; + } + } + } + } + if (elapsedF12 >= keyPressDelay){ #if defined(HAVE_X11) || defined(_WIN32) pressed = keys_are_pressed(params.toggle_hud); @@ -80,4 +106,4 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par logger->upload_last_logs(); } } -} \ No newline at end of file +} diff --git a/src/keybinds.h b/src/keybinds.h index 6aec3e58..698a1e23 100644 --- a/src/keybinds.h +++ b/src/keybinds.h @@ -11,7 +11,7 @@ typedef unsigned long KeySym; #endif -Clock::time_point last_f2_press, last_f12_press, reload_cfg_press, last_upload_press; +Clock::time_point last_f2_press, last_f3_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/overlay.cpp b/src/overlay.cpp index b3a15aa5..ae3e9897 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -137,4 +137,4 @@ void calculate_benchmark_data(void *params_void){ for (auto& entry : benchmark.percentile_data) { entry.first.append(max_label_size - entry.first.length(), ' '); } -} \ No newline at end of file +} diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index ba10d23c..719937b7 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -94,35 +94,12 @@ parse_string_to_keysym_vec(const char *str) return keys; } -static std::vector -parse_toggle_hud(const char *str) -{ - return parse_string_to_keysym_vec(str); -} - -static std::vector -parse_toggle_logging(const char *str) -{ - return parse_string_to_keysym_vec(str); -} - -static std::vector -parse_reload_cfg(const char *str) -{ - return parse_string_to_keysym_vec(str); -} - -static std::vector -parse_upload_log(const char *str) -{ - return parse_string_to_keysym_vec(str); -} - -static std::vector -parse_upload_logs(const char *str) -{ - return parse_string_to_keysym_vec(str); -} +#define parse_toggle_hud parse_string_to_keysym_vec +#define parse_toggle_logging parse_string_to_keysym_vec +#define parse_reload_cfg parse_string_to_keysym_vec +#define parse_upload_log parse_string_to_keysym_vec +#define parse_upload_logs parse_string_to_keysym_vec +#define parse_toggle_fps_limit parse_string_to_keysym_vec #else #define parse_toggle_hud(x) {} @@ -130,6 +107,7 @@ parse_upload_logs(const char *str) #define parse_reload_cfg(x) {} #define parse_upload_log(x) {} #define parse_upload_logs(x) {} +#define parse_toggle_fps_limit(x) {} #endif static uint32_t @@ -138,10 +116,28 @@ parse_fps_sampling_period(const char *str) return strtol(str, NULL, 0) * 1000; } -static uint32_t +static std::vector parse_fps_limit(const char *str) { - return strtol(str, NULL, 0); + std::vector fps_limit; + std::stringstream fps_limit_strings(str); + std::string value; + + while (std::getline(fps_limit_strings, value, ',')) { + trim(value); + + uint32_t as_int; + try { + as_int = static_cast(std::stoul(value)); + } catch (const std::invalid_argument&) { + std::cerr << "MANGOHUD: invalid fps_limit value: '" << value << "'\n"; + continue; + } + + fps_limit.push_back(as_int); + } + + return fps_limit; } static bool @@ -464,7 +460,7 @@ parse_overlay_config(struct overlay_params *params, params->width = 0; params->height = 140; params->control = -1; - params->fps_limit = 0; + params->fps_limit = { 0 }; params->vsync = -1; params->gl_vsync = -2; params->offset_x = 0; @@ -494,6 +490,7 @@ parse_overlay_config(struct overlay_params *params, #ifdef HAVE_X11 params->toggle_hud = { XK_Shift_R, XK_F12 }; + params->toggle_fps_limit = { XK_Shift_L, XK_F3 }; params->toggle_logging = { XK_Shift_L, XK_F2 }; params->reload_cfg = { XK_Shift_L, XK_F4 }; params->upload_log = { XK_Shift_L, XK_F3 }; @@ -601,8 +598,8 @@ parse_overlay_config(struct overlay_params *params, // set frametime limit using namespace std::chrono; - if (params->fps_limit > 0) - fps_limit_stats.targetFrameTime = duration_cast(duration(1) / params->fps_limit); + if (params->fps_limit.size() > 0 && params->fps_limit[0] > 0) + fps_limit_stats.targetFrameTime = duration_cast(duration(1) / params->fps_limit[0]); else fps_limit_stats.targetFrameTime = {}; diff --git a/src/overlay_params.h b/src/overlay_params.h index 560465f3..6eedbafe 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -69,6 +69,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(vsync) \ OVERLAY_PARAM_CUSTOM(gl_vsync) \ OVERLAY_PARAM_CUSTOM(toggle_hud) \ + OVERLAY_PARAM_CUSTOM(toggle_fps_limit) \ OVERLAY_PARAM_CUSTOM(toggle_logging) \ OVERLAY_PARAM_CUSTOM(reload_cfg) \ OVERLAY_PARAM_CUSTOM(upload_log) \ @@ -148,7 +149,7 @@ struct overlay_params { enum overlay_param_position position; int control; uint32_t fps_sampling_period; /* us */ - uint32_t fps_limit; + std::vector fps_limit; bool help; bool no_display; bool full; @@ -168,6 +169,7 @@ struct overlay_params { float font_scale_media_player; float background_alpha, alpha; std::vector toggle_hud; + std::vector toggle_fps_limit; std::vector toggle_logging; std::vector reload_cfg; std::vector upload_log; From 0bc9949af9a307f5cac830d3e7485d828dcefbfd Mon Sep 17 00:00:00 2001 From: jackun Date: Sat, 19 Sep 2020 13:19:20 +0300 Subject: [PATCH 047/130] Default toggle FPS limit to Shift_L+F1, update README and config file --- README.md | 3 ++- bin/MangoHud.conf | 3 ++- src/overlay_params.cpp | 11 +++++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7026527f..0781683c 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,8 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `io_read`
`io_write` | Show non-cached IO read/write, in MiB/s | | `pci_dev` | Select GPU device in multi-gpu setups | | `version` | Shows current mangohud version | -| `fps_limit` | Limit the apps framerate | +| `fps_limit` | Limit the apps framerate. Comma-separated list of one or more FPS values. `0` means unlimited. | +| `toggle_fps_limit` | Cycle between FPS limits. Defaults to `Shift_L+F1`. | | `arch` | Show if the application is 32 or 64 bit | | `histogram` | Change fps graph to histogram | | `cpu_text`
`gpu_text` | Override CPU and GPU text | diff --git a/bin/MangoHud.conf b/bin/MangoHud.conf index dbc177f7..4eba14eb 100644 --- a/bin/MangoHud.conf +++ b/bin/MangoHud.conf @@ -5,7 +5,7 @@ ################ PERFORMANCE ################# -### Limit the application FPS +### Limit the application FPS. Comma-separated list of one or more FPS values (e.g. 0,30,60). 0 means unlimited (unless v-synced). # fps_limit= ### VSYNC [0-3] 0 = adaptive; 1 = off; 2 = mailbox; 3 = on @@ -122,6 +122,7 @@ background_alpha=0.5 ### Change toggle keybinds for the hud & logging #toggle_hud=Shift_R+F12 +#toggle_fps_limit=Shift_L+F1 #toggle_logging=Shift_L+F2 #reload_cfg=Shift_L+F4 #upload_log=Shift+F3 diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 719937b7..b1967580 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -490,7 +490,7 @@ parse_overlay_config(struct overlay_params *params, #ifdef HAVE_X11 params->toggle_hud = { XK_Shift_R, XK_F12 }; - params->toggle_fps_limit = { XK_Shift_L, XK_F3 }; + params->toggle_fps_limit = { XK_Shift_L, XK_F1 }; params->toggle_logging = { XK_Shift_L, XK_F2 }; params->reload_cfg = { XK_Shift_L, XK_F4 }; params->upload_log = { XK_Shift_L, XK_F3 }; @@ -499,16 +499,19 @@ parse_overlay_config(struct overlay_params *params, #ifdef _WIN32 params->toggle_hud = { VK_F12 }; + params->toggle_fps_limit = { VK_F3 }; params->toggle_logging = { VK_F2 }; params->reload_cfg = { VK_F4 }; #undef parse_toggle_hud + #undef parse_toggle_fps_limit #undef parse_toggle_logging #undef parse_reload_cfg - #define parse_toggle_hud(x) params->toggle_hud - #define parse_toggle_logging(x) params->toggle_logging - #define parse_reload_cfg(x) params->reload_cfg + #define parse_toggle_hud(x) params->toggle_hud + #define parse_toggle_fps_limit(x) params->toggle_fps_limit + #define parse_toggle_logging(x) params->toggle_logging + #define parse_reload_cfg(x) params->reload_cfg #endif From 6dbb1c2aa8414625e1d4dcddf00166bf0b1a4514 Mon Sep 17 00:00:00 2001 From: jackun Date: Sat, 19 Sep 2020 13:53:24 +0300 Subject: [PATCH 048/130] Rename `last_f3_press` to more generic `toggle_fps_limit_press` --- src/keybinds.cpp | 6 +++--- src/keybinds.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/keybinds.cpp b/src/keybinds.cpp index b2a3ccdd..48b7babb 100644 --- a/src/keybinds.cpp +++ b/src/keybinds.cpp @@ -8,7 +8,7 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par bool pressed = false; // FIXME just a placeholder until wayland support auto now = Clock::now(); /* us */ auto elapsedF2 = now - last_f2_press; - auto elapsedF3 = now - last_f3_press; + auto elapsedFpsLimitToggle = now - toggle_fps_limit_press; auto elapsedF12 = now - last_f12_press; auto elapsedReloadCfg = now - reload_cfg_press; auto elapsedUpload = now - last_upload_press; @@ -35,14 +35,14 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par } } - if (elapsedF3 >= keyPressDelay){ + if (elapsedFpsLimitToggle >= keyPressDelay){ #if defined(HAVE_X11) || defined(_WIN32) pressed = keys_are_pressed(params.toggle_fps_limit); #else pressed = false; #endif if (pressed){ - last_f3_press = now; + toggle_fps_limit_press = now; for (size_t i = 0; i < params.fps_limit.size(); i++){ uint32_t fps_limit = params.fps_limit[i]; // current fps limit equals vector entry, use next / first diff --git a/src/keybinds.h b/src/keybinds.h index 698a1e23..3aee726a 100644 --- a/src/keybinds.h +++ b/src/keybinds.h @@ -11,7 +11,7 @@ typedef unsigned long KeySym; #endif -Clock::time_point last_f2_press, last_f3_press , last_f12_press, reload_cfg_press, last_upload_press; +Clock::time_point last_f2_press, toggle_fps_limit_press , last_f12_press, reload_cfg_press, last_upload_press; #ifdef HAVE_X11 bool keys_are_pressed(const std::vector& keys) { @@ -59,4 +59,4 @@ bool keys_are_pressed(const std::vector& keys) { } #endif -#endif //MANGOHUD_KEYBINDS_H \ No newline at end of file +#endif //MANGOHUD_KEYBINDS_H From 9bb65654cb9aba2aece35cdc1547530f69ba1ce9 Mon Sep 17 00:00:00 2001 From: jackun Date: Sat, 19 Sep 2020 13:54:25 +0300 Subject: [PATCH 049/130] editorconfig: vulkan.*, keybinds.* indent_size to 3 spaces, for now --- .editorconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.editorconfig b/.editorconfig index 09a8ffd9..36574d32 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,6 +16,9 @@ trim_trailing_whitespace = true [src/overlay*{cpp,h}] indent_size = 3 +[src/{keybinds,vulkan}.{cpp,h}] +indent_size = 3 + [src/mesa/**] indent_size = 3 From 8b4df2a9a3a36f372eda44e0ba98c625a0b98247 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Tue, 22 Sep 2020 11:18:48 +0200 Subject: [PATCH 050/130] Put time and version inside imgui table --- src/vulkan.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vulkan.cpp b/src/vulkan.cpp index c2a78cd3..47b5b124 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -1007,14 +1007,15 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if (!params.no_display){ ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); + ImGui::BeginTable("hud", params.tableCols, ImGuiTableFlags_NoClipX); if (params.enabled[OVERLAY_PARAM_ENABLED_version]){ + ImGui::TableNextCell(); ImGui::Text("%s", MANGOHUD_VERSION); - ImGui::Dummy(ImVec2(0, 8.0f)); } if (params.enabled[OVERLAY_PARAM_ENABLED_time]){ + ImGui::TableNextRow(); ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.00f), "%s", data.time.c_str()); } - ImGui::BeginTable("hud", params.tableCols); if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats]){ ImGui::TableNextRow(); const char* gpu_text; From cb8d992bfebe3e4d7827db57c2468f3300a570da Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Wed, 23 Sep 2020 12:23:29 +0200 Subject: [PATCH 051/130] Use real_font_size for padding --- src/overlay.cpp | 1 + src/overlay.h | 1 + src/overlay_params.cpp | 3 ++- src/vulkan.cpp | 10 +++++----- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/overlay.cpp b/src/overlay.cpp index ae3e9897..68d676f9 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -13,6 +13,7 @@ struct benchmark_stats benchmark; struct fps_limit fps_limit_stats {}; +ImVec2 real_font_size; void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& params, uint32_t vendorID) { diff --git a/src/overlay.h b/src/overlay.h index 91e30abc..471f36e1 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -79,6 +79,7 @@ extern struct fps_limit fps_limit_stats; extern int32_t deviceID; extern struct benchmark_stats benchmark; +extern ImVec2 real_font_size; void position_layer(struct swapchain_stats& data, struct overlay_params& params, ImVec2 window_size); void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan); diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index b1967580..1fe5346c 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -616,5 +616,6 @@ parse_overlay_config(struct overlay_params *params, #endif if(!params->output_file.empty()) printf("MANGOHUD: output_file is Deprecated, use output_folder instead\n"); - + auto real_size = params->font_size * params->font_scale; + real_font_size = ImVec2(real_size, real_size / 2); } diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 47b5b124..e5635635 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -850,7 +850,7 @@ static void render_mpris_metadata(struct overlay_params& params, mutexed_metadat 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 = (2 + benchmark.percentile_data.size()) * params.font_size + 10.0f + 58; + int benchHeight = (2 + benchmark.percentile_data.size()) * real_font_size.x + 10.0f + 58; ImGui::SetNextWindowSize(ImVec2(window_size.x, benchHeight), ImGuiCond_Always); if (height - (window_size.y + data.main_window_pos.y + 5) < benchHeight) ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y - benchHeight - 5), ImGuiCond_Always); @@ -1236,7 +1236,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& } } if (params.enabled[OVERLAY_PARAM_ENABLED_frame_timing]){ - ImGui::Dummy(ImVec2(0.0f, params.font_size * params.font_scale / 2)); + ImGui::Dummy(ImVec2(0.0f, real_font_size.y)); ImGui::PushFont(data.font1); ImGui::TextColored(data.colors.engine, "%s", "Frametime"); ImGui::PopFont(); @@ -1253,12 +1253,12 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::PlotHistogram(hash, get_time_stat, &data, ARRAY_SIZE(data.frames_stats), 0, NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth() - params.font_size * params.font_scale * 2.2, 50)); + ImVec2(ImGui::GetContentRegionAvailWidth() - real_font_size.x * 2.2, 50)); } else { ImGui::PlotLines(hash, get_time_stat, &data, ARRAY_SIZE(data.frames_stats), 0, NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth() - params.font_size * params.font_scale * 2.2, 50)); + ImVec2(ImGui::GetContentRegionAvailWidth() - real_font_size.x * 2.2, 50)); } ImGui::PopStyleColor(); } @@ -2101,7 +2101,7 @@ void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overl style.Colors[ImGuiCol_PlotHistogram] = convert(params.frametime_color); style.Colors[ImGuiCol_WindowBg] = convert(params.background_color); style.Colors[ImGuiCol_Text] = convert(params.text_color); - style.CellPadding.y = -0.085 * params.font_size; + style.CellPadding.y = -0.085 * real_font_size.y; } // TODO probably needs colorspace check too From 86cef7d75c36570e491bbc4044c947a8643bd34a Mon Sep 17 00:00:00 2001 From: Stephan Lachnit Date: Mon, 28 Sep 2020 22:22:00 +0200 Subject: [PATCH 052/130] fix typo in man page Signed-off-by: Stephan Lachnit --- data/mangohud.1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/mangohud.1 b/data/mangohud.1 index 89e38068..4043cb31 100644 --- a/data/mangohud.1 +++ b/data/mangohud.1 @@ -11,11 +11,11 @@ mangohud \- enable MangoHud on any application MangoHud is a Vulkan/OpenGL overlay for monitoring FPS, temperatures, CPU/GPU load and more. .SH USAGE -MangoHud can be enabled for Vulkan applications by setting \fBMANGOHUD=1\fR as envrionment variable. +MangoHud can be enabled for Vulkan applications by setting \fBMANGOHUD=1\fR as environment variable. .br To load MangoHud for any application, including OpenGL applications, the \fBmangohud\fR executable can be used. It preloads a library via ld into the application. .br -Note: some OpenGL applications may also need dlsym hooking. This can be done by passing option \fB--dlsym\fR or by setting \fBMANGOHUD_DLSYM=1\fR as envrionment variable. +Note: some OpenGL applications may also need dlsym hooking. This can be done by passing option \fB--dlsym\fR or by setting \fBMANGOHUD_DLSYM=1\fR as environment variable. .SH CONFIG MangoHud comes with a config file which can be used to set configuration options globally or per application. The priorities of different config files are: @@ -30,9 +30,9 @@ $XDG_CONFIG_HOME/MangoHud/MangoHud.conf .LP An example config file is located in /usr/share/doc/mangohud/MangoHud.conf, containing all available options. .LP -A custom config file location can also be specified with the \fBMANGOHUD_CONFIGFILE\fR envrionment variable. +A custom config file location can also be specified with the \fBMANGOHUD_CONFIGFILE\fR environment variable. .br -Config options can also be set with the \fBMANGOHUD_CONFIG\fR envrionment variable. This takes priority over any config file. +Config options can also be set with the \fBMANGOHUD_CONFIG\fR environment variable. This takes priority over any config file. .SH EXAMPLES OpenGL: \fBmangohud glxgears\fR From ade319fe8769e8e43c11354a17e91a658bac6be5 Mon Sep 17 00:00:00 2001 From: Stephan Lachnit Date: Mon, 28 Sep 2020 22:30:00 +0200 Subject: [PATCH 053/130] ensure minihook is not in source tarballs Signed-off-by: Stephan Lachnit --- build-source.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build-source.sh b/build-source.sh index 7030e1af..5636d594 100755 --- a/build-source.sh +++ b/build-source.sh @@ -5,6 +5,8 @@ NAME=MangoHud-$VERSION-Source # create archive via git git archive HEAD --format=tar --prefix=${NAME}/ --output=${NAME}.tar +# remove unused minihook from source tarball +tar -f ${NAME}.tar --delete ${NAME}/modules # create DFSG compliant version which excludes NVML cp ${NAME}.tar ${NAME}-DFSG.tar tar -f ${NAME}-DFSG.tar --delete ${NAME}/include/nvml.h From 144e9a591768bd281a3c599c8847f3de0388a9d2 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Mon, 28 Sep 2020 17:44:45 -0700 Subject: [PATCH 054/130] Add color option to right_aligned_text --- src/vulkan.cpp | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/vulkan.cpp b/src/vulkan.cpp index e5635635..54ee34b3 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -740,7 +740,7 @@ void position_layer(struct swapchain_stats& data, struct overlay_params& params, } } -static void right_aligned_text(float off_x, const char *fmt, ...) +static void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...) { ImVec2 pos = ImGui::GetCursorPos(); char buffer[32] {}; @@ -752,7 +752,8 @@ static void right_aligned_text(float off_x, const char *fmt, ...) ImVec2 sz = ImGui::CalcTextSize(buffer); ImGui::SetCursorPosX(pos.x + off_x - sz.x); - ImGui::Text("%s", buffer); + //ImGui::Text("%s", buffer); + ImGui::TextColored(col,"%s",buffer); } float get_ticker_limited_pos(float pos, float tw, float& left_limit, float& right_limit) @@ -934,7 +935,7 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& gpu_text = params.gpu_text.c_str(); ImGui::TextColored(data.colors.gpu, "%s", gpu_text); ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", gpu_info.load); + right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.load); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); } @@ -947,7 +948,7 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& cpu_text = params.cpu_text.c_str(); ImGui::TextColored(data.colors.cpu, "%s", cpu_text); ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); + right_aligned_text(data.colors.text,ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); } @@ -955,7 +956,7 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%.0f", data.fps); + right_aligned_text(data.colors.text,ralign_width, "%.0f", data.fps); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("FPS"); @@ -1025,14 +1026,14 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& gpu_text = params.gpu_text.c_str(); ImGui::TextColored(data.colors.gpu, "%s", gpu_text); ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", gpu_info.load); + right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.load); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); // ImGui::SameLine(150); // ImGui::Text("%s", "%"); if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_temp]){ ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", gpu_info.temp); + right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.temp); ImGui::SameLine(0, 1.0f); ImGui::Text("°C"); } @@ -1040,7 +1041,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock]){ ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", gpu_info.CoreClock); + right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.CoreClock); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("MHz"); @@ -1048,7 +1049,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& } if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_power]) { ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", gpu_info.powerUsage); + right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.powerUsage); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("W"); @@ -1064,7 +1065,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& cpu_text = params.cpu_text.c_str(); ImGui::TextColored(data.colors.cpu, "%s", cpu_text); ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); + right_aligned_text(data.colors.text,ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); // ImGui::SameLine(150); @@ -1072,7 +1073,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_temp]){ ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); + right_aligned_text(data.colors.text,ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); ImGui::SameLine(0, 1.0f); ImGui::Text("°C"); } @@ -1089,11 +1090,11 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TextColored(data.colors.cpu,"%i", i); ImGui::PopFont(); ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", int(cpuData.percent)); + right_aligned_text(data.colors.text,ralign_width, "%i", int(cpuData.percent)); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", cpuData.mhz); + right_aligned_text(data.colors.text,ralign_width, "%i", cpuData.mhz); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("MHz"); @@ -1114,7 +1115,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if (params.enabled[OVERLAY_PARAM_ENABLED_io_read]){ ImGui::TableNextCell(); float val = data.io.diff.read * 1000000 / sampling; - right_aligned_text(ralign_width, val < 100 ? "%.1f" : "%.f", val); + right_aligned_text(data.colors.text,ralign_width, val < 100 ? "%.1f" : "%.f", val); ImGui::SameLine(0,1.0f); ImGui::PushFont(data.font1); ImGui::Text("MiB/s"); @@ -1123,7 +1124,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if (params.enabled[OVERLAY_PARAM_ENABLED_io_write]){ ImGui::TableNextCell(); float val = data.io.diff.write * 1000000 / sampling; - right_aligned_text(ralign_width, val < 100 ? "%.1f" : "%.f", val); + right_aligned_text(data.colors.text,ralign_width, val < 100 ? "%.1f" : "%.f", val); ImGui::SameLine(0,1.0f); ImGui::PushFont(data.font1); ImGui::Text("MiB/s"); @@ -1134,14 +1135,14 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); ImGui::TextColored(data.colors.vram, "VRAM"); ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%.1f", gpu_info.memoryUsed); + right_aligned_text(data.colors.text,ralign_width, "%.1f", gpu_info.memoryUsed); ImGui::SameLine(0,1.0f); ImGui::PushFont(data.font1); ImGui::Text("GiB"); ImGui::PopFont(); if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_mem_clock]){ ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%i", gpu_info.MemClock); + right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.MemClock); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("MHz"); @@ -1153,7 +1154,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); ImGui::TextColored(data.colors.ram, "RAM"); ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%.1f", memused); + right_aligned_text(data.colors.text,ralign_width, "%.1f", memused); ImGui::SameLine(0,1.0f); ImGui::PushFont(data.font1); ImGui::Text("GiB"); @@ -1164,13 +1165,13 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%.0f", data.fps); + right_aligned_text(data.colors.text,ralign_width, "%.0f", data.fps); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("FPS"); ImGui::PopFont(); ImGui::TableNextCell(); - right_aligned_text(ralign_width, "%.1f", 1000 / data.fps); + right_aligned_text(data.colors.text,ralign_width, "%.1f", 1000 / data.fps); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("ms"); From d7f04deb5648b35b1507dd3ebeaa2d7b627644f0 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Mon, 28 Sep 2020 21:24:26 -0700 Subject: [PATCH 055/130] Implement gpu load color change --- src/overlay.h | 5 ++++- src/overlay_params.cpp | 15 ++++++++++++++- src/overlay_params.h | 12 +++++++++++- src/vulkan.cpp | 28 +++++++++++++++++++++++++--- 4 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/overlay.h b/src/overlay.h index 471f36e1..023c9955 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -57,7 +57,10 @@ struct swapchain_stats { background, text, media_player, - wine; + wine, + gpu_load_high, + gpu_load_med, + gpu_load_low; } colors; }; diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 1fe5346c..3a9702aa 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -324,6 +324,12 @@ parse_font_glyph_ranges(const char *str) #define parse_text_color(s) parse_color(s) #define parse_media_player_color(s) parse_color(s) #define parse_wine_color(s) parse_color(s) +#define parse_gpu_load_high_color(s) parse_color(s) +#define parse_gpu_load_med_color(s) parse_color(s) +#define parse_gpu_load_low_color(s) parse_color(s) +#define parse_gpu_load_high(s) parse_unsigned(s) +#define parse_gpu_load_med(s) parse_unsigned(s) +#define parse_gpu_load_low(s) parse_unsigned(s) static bool parse_help(const char *str) @@ -481,6 +487,9 @@ parse_overlay_config(struct overlay_params *params, params->media_player_name = ""; params->font_scale = 1.0f; params->wine_color = 0xeb5b5b; + params->gpu_load_high_color=0xb22222; + params->gpu_load_med_color=0xfdfd09; + params->gpu_load_low_color=0x39f900; params->font_scale_media_player = 0.55f; params->log_interval = 100; params->media_player_order = { MP_ORDER_TITLE, MP_ORDER_ARTIST, MP_ORDER_ALBUM }; @@ -562,7 +571,7 @@ parse_overlay_config(struct overlay_params *params, params->font_scale_media_player = 0.55f; // Convert from 0xRRGGBB to ImGui's format - std::array colors = { + std::array colors = { ¶ms->cpu_color, ¶ms->gpu_color, ¶ms->vram_color, @@ -574,6 +583,10 @@ parse_overlay_config(struct overlay_params *params, ¶ms->text_color, ¶ms->media_player_color, ¶ms->wine_color, + ¶ms->gpu_load_high_color, + ¶ms-> gpu_load_med_color, + ¶ms->gpu_load_low_color, + }; for (auto color : colors){ diff --git a/src/overlay_params.h b/src/overlay_params.h index 6eedbafe..d47b908f 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -50,6 +50,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_BOOL(engine_version) \ OVERLAY_PARAM_BOOL(histogram) \ OVERLAY_PARAM_BOOL(wine) \ + OVERLAY_PARAM_BOOL(gpu_load_change) \ OVERLAY_PARAM_CUSTOM(fps_sampling_period) \ OVERLAY_PARAM_CUSTOM(output_folder) \ OVERLAY_PARAM_CUSTOM(output_file) \ @@ -90,6 +91,9 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(io_color) \ OVERLAY_PARAM_CUSTOM(text_color) \ OVERLAY_PARAM_CUSTOM (wine_color) \ + OVERLAY_PARAM_CUSTOM(gpu_load_high_color) \ + OVERLAY_PARAM_CUSTOM(gpu_load_med_color) \ + OVERLAY_PARAM_CUSTOM(gpu_load_low_color) \ OVERLAY_PARAM_CUSTOM(alpha) \ OVERLAY_PARAM_CUSTOM(log_duration) \ OVERLAY_PARAM_CUSTOM(pci_dev) \ @@ -102,7 +106,11 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(permit_upload) \ OVERLAY_PARAM_CUSTOM(render_mango) \ OVERLAY_PARAM_CUSTOM(benchmark_percentiles) \ - OVERLAY_PARAM_CUSTOM(help) + OVERLAY_PARAM_CUSTOM(help) \ + OVERLAY_PARAM_CUSTOM(gpu_load_high) \ + OVERLAY_PARAM_CUSTOM(gpu_load_med) \ + OVERLAY_PARAM_CUSTOM(gpu_load_low) + enum overlay_param_position { LAYER_POSITION_TOP_LEFT, @@ -161,6 +169,8 @@ struct overlay_params { int gl_vsync; uint64_t log_duration; unsigned cpu_color, gpu_color, vram_color, ram_color, engine_color, io_color, frametime_color, background_color, text_color, wine_color; + unsigned gpu_load_high_color,gpu_load_med_color,gpu_load_low_color; + int gpu_load_high,gpu_load_med,gpu_load_low,gpu_load_change; unsigned media_player_color; unsigned tableCols; unsigned render_mango; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 54ee34b3..34bc5848 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -1026,9 +1026,28 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& gpu_text = params.gpu_text.c_str(); ImGui::TextColored(data.colors.gpu, "%s", gpu_text); ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::Text("%%"); + if(params.enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){ + if(gpu_info.load >= params.gpu_load_high){ + right_aligned_text(data.colors.gpu_load_high,ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(data.colors.gpu_load_high,"%%"); + } + else if (gpu_info.load >= params.gpu_load_med && gpu_info.load < params.gpu_load_high && gpu_info.load > params.gpu_load_low) { + right_aligned_text(data.colors.gpu_load_med,ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(data.colors.gpu_load_med,"%%"); + } + else { + right_aligned_text(data.colors.gpu_load_low,ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(data.colors.gpu_load_low,"%%"); + } + } + else { + right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::Text("%%"); + } // ImGui::SameLine(150); // ImGui::Text("%s", "%"); if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_temp]){ @@ -2096,6 +2115,9 @@ void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overl sw_stats.colors.text = convert(params.text_color); sw_stats.colors.media_player = convert(params.media_player_color); sw_stats.colors.wine = convert(params.wine_color); + sw_stats.colors.gpu_load_high = convert(params.gpu_load_high_color); + sw_stats.colors.gpu_load_med = convert(params.gpu_load_med_color); + sw_stats.colors.gpu_load_low = convert(params.gpu_load_low_color); ImGuiStyle& style = ImGui::GetStyle(); style.Colors[ImGuiCol_PlotLines] = convert(params.frametime_color); From 8605d2a7ddad1706514719ec3b9dd9e37c96ecbc Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Tue, 29 Sep 2020 15:43:26 -0700 Subject: [PATCH 056/130] Add spaces --- src/vulkan.cpp | 58 +++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 34bc5848..8354abc9 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -935,7 +935,7 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& gpu_text = params.gpu_text.c_str(); ImGui::TextColored(data.colors.gpu, "%s", gpu_text); ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.load); + right_aligned_text(data.colors.text, ralign_width, "%i", gpu_info.load); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); } @@ -948,7 +948,7 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& cpu_text = params.cpu_text.c_str(); ImGui::TextColored(data.colors.cpu, "%s", cpu_text); ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); + right_aligned_text(data.colors.text, ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); } @@ -956,7 +956,7 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%.0f", data.fps); + right_aligned_text(data.colors.text, ralign_width, "%.0f", data.fps); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("FPS"); @@ -1026,25 +1026,29 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& gpu_text = params.gpu_text.c_str(); ImGui::TextColored(data.colors.gpu, "%s", gpu_text); ImGui::TableNextCell(); - if(params.enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){ - if(gpu_info.load >= params.gpu_load_high){ - right_aligned_text(data.colors.gpu_load_high,ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(data.colors.gpu_load_high,"%%"); + auto gpu_high_color = data.colors.gpu_load_high; + auto gpu_med_color = data.colors.gpu_load_med; + auto gpu_low_color = data.colors.gpu_load_low; + auto text_color = data.colors.text; + if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){ + if (gpu_info.load >= params.gpu_load_high){ + right_aligned_text(gpu_high_color, ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(gpu_high_color, "%%"); } else if (gpu_info.load >= params.gpu_load_med && gpu_info.load < params.gpu_load_high && gpu_info.load > params.gpu_load_low) { - right_aligned_text(data.colors.gpu_load_med,ralign_width, "%i", gpu_info.load); + right_aligned_text(gpu_med_color, ralign_width, "%i", gpu_info.load); ImGui::SameLine(0, 1.0f); - ImGui::TextColored(data.colors.gpu_load_med,"%%"); + ImGui::TextColored(gpu_med_color, "%%"); } else { - right_aligned_text(data.colors.gpu_load_low,ralign_width, "%i", gpu_info.load); + right_aligned_text(gpu_low_color, ralign_width, "%i", gpu_info.load); ImGui::SameLine(0, 1.0f); - ImGui::TextColored(data.colors.gpu_load_low,"%%"); + ImGui::TextColored(gpu_low_color, "%%"); } } else { - right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.load); + right_aligned_text(text_color, ralign_width, "%i", gpu_info.load); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); } @@ -1052,7 +1056,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& // ImGui::Text("%s", "%"); if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_temp]){ ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.temp); + right_aligned_text(text_color, ralign_width, "%i", gpu_info.temp); ImGui::SameLine(0, 1.0f); ImGui::Text("°C"); } @@ -1060,7 +1064,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock]){ ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.CoreClock); + right_aligned_text(text_color, ralign_width, "%i", gpu_info.CoreClock); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("MHz"); @@ -1068,7 +1072,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& } if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_power]) { ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.powerUsage); + right_aligned_text(text_color, ralign_width, "%i", gpu_info.powerUsage); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("W"); @@ -1084,7 +1088,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& cpu_text = params.cpu_text.c_str(); ImGui::TextColored(data.colors.cpu, "%s", cpu_text); ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); + right_aligned_text(data.colors.text, ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); // ImGui::SameLine(150); @@ -1092,7 +1096,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_temp]){ ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); + right_aligned_text(data.colors.text, ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); ImGui::SameLine(0, 1.0f); ImGui::Text("°C"); } @@ -1109,11 +1113,11 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TextColored(data.colors.cpu,"%i", i); ImGui::PopFont(); ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%i", int(cpuData.percent)); + right_aligned_text(data.colors.text, ralign_width, "%i", int(cpuData.percent)); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%i", cpuData.mhz); + right_aligned_text(data.colors.text, ralign_width, "%i", cpuData.mhz); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("MHz"); @@ -1134,7 +1138,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if (params.enabled[OVERLAY_PARAM_ENABLED_io_read]){ ImGui::TableNextCell(); float val = data.io.diff.read * 1000000 / sampling; - right_aligned_text(data.colors.text,ralign_width, val < 100 ? "%.1f" : "%.f", val); + right_aligned_text(data.colors.text, ralign_width, val < 100 ? "%.1f" : "%.f", val); ImGui::SameLine(0,1.0f); ImGui::PushFont(data.font1); ImGui::Text("MiB/s"); @@ -1143,7 +1147,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if (params.enabled[OVERLAY_PARAM_ENABLED_io_write]){ ImGui::TableNextCell(); float val = data.io.diff.write * 1000000 / sampling; - right_aligned_text(data.colors.text,ralign_width, val < 100 ? "%.1f" : "%.f", val); + right_aligned_text(data.colors.text, ralign_width, val < 100 ? "%.1f" : "%.f", val); ImGui::SameLine(0,1.0f); ImGui::PushFont(data.font1); ImGui::Text("MiB/s"); @@ -1154,14 +1158,14 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); ImGui::TextColored(data.colors.vram, "VRAM"); ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%.1f", gpu_info.memoryUsed); + right_aligned_text(data.colors.text, ralign_width, "%.1f", gpu_info.memoryUsed); ImGui::SameLine(0,1.0f); ImGui::PushFont(data.font1); ImGui::Text("GiB"); ImGui::PopFont(); if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_mem_clock]){ ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%i", gpu_info.MemClock); + right_aligned_text(data.colors.text, ralign_width, "%i", gpu_info.MemClock); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("MHz"); @@ -1173,7 +1177,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); ImGui::TextColored(data.colors.ram, "RAM"); ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%.1f", memused); + right_aligned_text(data.colors.text, ralign_width, "%.1f", memused); ImGui::SameLine(0,1.0f); ImGui::PushFont(data.font1); ImGui::Text("GiB"); @@ -1184,13 +1188,13 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%.0f", data.fps); + right_aligned_text(data.colors.text, ralign_width, "%.0f", data.fps); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("FPS"); ImGui::PopFont(); ImGui::TableNextCell(); - right_aligned_text(data.colors.text,ralign_width, "%.1f", 1000 / data.fps); + right_aligned_text(data.colors.text, ralign_width, "%.1f", 1000 / data.fps); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("ms"); From e7db65d4cd14a0aba3e95a6375464b871685820b Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Thu, 1 Oct 2020 19:26:14 -0700 Subject: [PATCH 057/130] add function to return high/low/med, add switch for gpu load change --- src/vulkan.cpp | 48 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 8354abc9..e491f801 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -990,6 +990,19 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size = ImVec2(window_size.x, 200); } + +int change_on_load_temp ( int info, int high, int med) { + if (info >= high){ + return 1; + } + else if (info >= med && info < high) { + return 2; + } + else { + return 3; + } +} + void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan) { ImGui::GetIO().FontGlobalScale = params.font_scale; @@ -1030,21 +1043,26 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& auto gpu_med_color = data.colors.gpu_load_med; auto gpu_low_color = data.colors.gpu_load_low; auto text_color = data.colors.text; + if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){ - if (gpu_info.load >= params.gpu_load_high){ - right_aligned_text(gpu_high_color, ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(gpu_high_color, "%%"); - } - else if (gpu_info.load >= params.gpu_load_med && gpu_info.load < params.gpu_load_high && gpu_info.load > params.gpu_load_low) { - right_aligned_text(gpu_med_color, ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(gpu_med_color, "%%"); - } - else { - right_aligned_text(gpu_low_color, ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(gpu_low_color, "%%"); + int gpu_load = change_on_load_temp(gpu_info.load, params.gpu_load_high, params.gpu_load_med); + // 1 is high, 2 is medium, and 3 is low load/temp + switch (gpu_load) { + case 1: + right_aligned_text(gpu_high_color, ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(gpu_high_color, "%%"); + break; + case 2: + right_aligned_text(gpu_med_color, ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(gpu_med_color, "%%"); + break; + case 3: + right_aligned_text(gpu_low_color, ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(gpu_low_color, "%%"); + break; } } else { @@ -2895,3 +2913,5 @@ extern "C" VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL overlay_GetI if (instance_data->vtable.GetInstanceProcAddr == NULL) return NULL; return instance_data->vtable.GetInstanceProcAddr(instance, funcName); } + + From 891a3944f3eb61839bedcee3102e3784c4214819 Mon Sep 17 00:00:00 2001 From: jackun Date: Sun, 4 Oct 2020 21:49:20 +0300 Subject: [PATCH 058/130] [OpenGL] Default and limit GLSL version to 1.20 if OpenGL < 3.0. Not using anything fancy for now anyway. --- src/gl/imgui_impl_opengl3.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/gl/imgui_impl_opengl3.cpp b/src/gl/imgui_impl_opengl3.cpp index c87e7da2..e44ba290 100644 --- a/src/gl/imgui_impl_opengl3.cpp +++ b/src/gl/imgui_impl_opengl3.cpp @@ -184,7 +184,7 @@ static bool ImGui_ImplOpenGL3_CreateDeviceObjects() glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); // Parse GLSL version string - int glsl_version = 130; + int glsl_version = 120; sscanf(g_GlslVersionString, "#version %d", &glsl_version); const GLchar* vertex_shader_glsl_120 = @@ -422,12 +422,14 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) if (!g_IsGLES) { // Not GL ES - glsl_version = "#version 130"; + glsl_version = "#version 120"; g_GlVersion = major * 100 + minor * 10; if (major >= 4 && minor >= 1) glsl_version = "#version 410"; else if (major > 3 || (major == 3 && minor >= 2)) glsl_version = "#version 150"; + else if (major == 3) + glsl_version = "#version 130"; else if (major < 2) glsl_version = "#version 100"; } else { @@ -443,7 +445,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) else if (g_GlVersion >= 300) glsl_version = "#version 300 es"; else - glsl_version = "#version 130"; + glsl_version = "#version 120"; } // Setup back-end capabilities flags @@ -456,7 +458,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) // Store GLSL version string so we can refer to it later in case we recreate shaders. // Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure. if (glsl_version == NULL) - glsl_version = "#version 130"; + glsl_version = "#version 120"; IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersionString)); strcpy(g_GlslVersionString, glsl_version); From 11d9c3aa97a9789534dc1317e767086a0a69c195 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Sun, 4 Oct 2020 15:54:44 -0700 Subject: [PATCH 059/130] remove param gpu_load_low as it is not needed --- src/overlay_params.h | 5 ++--- src/vulkan.cpp | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/overlay_params.h b/src/overlay_params.h index d47b908f..14d2547a 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -108,8 +108,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(benchmark_percentiles) \ OVERLAY_PARAM_CUSTOM(help) \ OVERLAY_PARAM_CUSTOM(gpu_load_high) \ - OVERLAY_PARAM_CUSTOM(gpu_load_med) \ - OVERLAY_PARAM_CUSTOM(gpu_load_low) + OVERLAY_PARAM_CUSTOM(gpu_load_med) enum overlay_param_position { @@ -170,7 +169,7 @@ struct overlay_params { uint64_t log_duration; unsigned cpu_color, gpu_color, vram_color, ram_color, engine_color, io_color, frametime_color, background_color, text_color, wine_color; unsigned gpu_load_high_color,gpu_load_med_color,gpu_load_low_color; - int gpu_load_high,gpu_load_med,gpu_load_low,gpu_load_change; + int gpu_load_high,gpu_load_med,gpu_load_change; unsigned media_player_color; unsigned tableCols; unsigned render_mango; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index e491f801..3b1610cd 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -2913,5 +2913,3 @@ extern "C" VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL overlay_GetI if (instance_data->vtable.GetInstanceProcAddr == NULL) return NULL; return instance_data->vtable.GetInstanceProcAddr(instance, funcName); } - - From 1c0a5af001047e9a452ff876a303bb8ab299aa9b Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Mon, 5 Oct 2020 16:41:59 -0700 Subject: [PATCH 060/130] Implement cpu load color change --- src/overlay.h | 5 ++++- src/overlay_params.cpp | 14 ++++++++++++-- src/overlay_params.h | 14 +++++++++++--- src/vulkan.cpp | 43 ++++++++++++++++++++++++++++++++++++------ 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/overlay.h b/src/overlay.h index 023c9955..80ca85b1 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -60,7 +60,10 @@ struct swapchain_stats { wine, gpu_load_high, gpu_load_med, - gpu_load_low; + gpu_load_low, + cpu_load_high, + cpu_load_med, + cpu_load_low; } colors; }; diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 3a9702aa..5c78fb1f 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -329,7 +329,11 @@ parse_font_glyph_ranges(const char *str) #define parse_gpu_load_low_color(s) parse_color(s) #define parse_gpu_load_high(s) parse_unsigned(s) #define parse_gpu_load_med(s) parse_unsigned(s) -#define parse_gpu_load_low(s) parse_unsigned(s) +#define parse_cpu_load_high_color(s) parse_color(s) +#define parse_cpu_load_med_color(s) parse_color(s) +#define parse_cpu_load_low_color(s) parse_color(s) +#define parse_cpu_load_high(s) parse_unsigned(s) +#define parse_cpu_load_med(s) parse_unsigned(s) static bool parse_help(const char *str) @@ -490,6 +494,9 @@ parse_overlay_config(struct overlay_params *params, params->gpu_load_high_color=0xb22222; params->gpu_load_med_color=0xfdfd09; params->gpu_load_low_color=0x39f900; + params->cpu_load_high_color=0xb22222; + params->cpu_load_med_color=0xfdfd09; + params->cpu_load_low_color=0x39f900; params->font_scale_media_player = 0.55f; params->log_interval = 100; params->media_player_order = { MP_ORDER_TITLE, MP_ORDER_ARTIST, MP_ORDER_ALBUM }; @@ -571,7 +578,7 @@ parse_overlay_config(struct overlay_params *params, params->font_scale_media_player = 0.55f; // Convert from 0xRRGGBB to ImGui's format - std::array colors = { + std::array colors = { ¶ms->cpu_color, ¶ms->gpu_color, ¶ms->vram_color, @@ -586,6 +593,9 @@ parse_overlay_config(struct overlay_params *params, ¶ms->gpu_load_high_color, ¶ms-> gpu_load_med_color, ¶ms->gpu_load_low_color, + ¶ms->cpu_load_high_color, + ¶ms->cpu_load_med_color, + ¶ms->cpu_load_low_color, }; diff --git a/src/overlay_params.h b/src/overlay_params.h index 14d2547a..b52a1868 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -51,6 +51,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_BOOL(histogram) \ OVERLAY_PARAM_BOOL(wine) \ OVERLAY_PARAM_BOOL(gpu_load_change) \ + OVERLAY_PARAM_BOOL(cpu_load_change) \ OVERLAY_PARAM_CUSTOM(fps_sampling_period) \ OVERLAY_PARAM_CUSTOM(output_folder) \ OVERLAY_PARAM_CUSTOM(output_file) \ @@ -94,6 +95,9 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(gpu_load_high_color) \ OVERLAY_PARAM_CUSTOM(gpu_load_med_color) \ OVERLAY_PARAM_CUSTOM(gpu_load_low_color) \ + OVERLAY_PARAM_CUSTOM(cpu_load_high_color) \ + OVERLAY_PARAM_CUSTOM(cpu_load_med_color) \ + OVERLAY_PARAM_CUSTOM(cpu_load_low_color) \ OVERLAY_PARAM_CUSTOM(alpha) \ OVERLAY_PARAM_CUSTOM(log_duration) \ OVERLAY_PARAM_CUSTOM(pci_dev) \ @@ -108,7 +112,9 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(benchmark_percentiles) \ OVERLAY_PARAM_CUSTOM(help) \ OVERLAY_PARAM_CUSTOM(gpu_load_high) \ - OVERLAY_PARAM_CUSTOM(gpu_load_med) + OVERLAY_PARAM_CUSTOM(gpu_load_med) \ + OVERLAY_PARAM_CUSTOM(cpu_load_high) \ + OVERLAY_PARAM_CUSTOM(cpu_load_med) enum overlay_param_position { @@ -168,8 +174,10 @@ struct overlay_params { int gl_vsync; uint64_t log_duration; unsigned cpu_color, gpu_color, vram_color, ram_color, engine_color, io_color, frametime_color, background_color, text_color, wine_color; - unsigned gpu_load_high_color,gpu_load_med_color,gpu_load_low_color; - int gpu_load_high,gpu_load_med,gpu_load_change; + unsigned gpu_load_high_color, gpu_load_med_color, gpu_load_low_color; + unsigned cpu_load_high_color, cpu_load_med_color, cpu_load_low_color; + int gpu_load_high, gpu_load_med, gpu_load_change; + int cpu_load_high, cpu_load_med, cpu_load_change; unsigned media_player_color; unsigned tableCols; unsigned render_mango; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 3b1610cd..ce81d874 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -992,10 +992,10 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& int change_on_load_temp ( int info, int high, int med) { - if (info >= high){ + if (info >= high) { return 1; - } - else if (info >= med && info < high) { + } + else if (info >= med && info < high) { return 2; } else { @@ -1106,9 +1106,37 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& cpu_text = params.cpu_text.c_str(); ImGui::TextColored(data.colors.cpu, "%s", cpu_text); ImGui::TableNextCell(); - right_aligned_text(data.colors.text, ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); - ImGui::SameLine(0, 1.0f); - ImGui::Text("%%"); + auto cpu_high_color = data.colors.cpu_load_high; + auto cpu_med_color = data.colors.cpu_load_med; + auto cpu_low_color = data.colors.cpu_load_low; + auto text_color = data.colors.text; + int cpu_load_percent = int(cpuStats.GetCPUDataTotal().percent); + if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_load_change]){ + int cpu_load = change_on_load_temp(cpu_load_percent, params.cpu_load_high, params.cpu_load_med); + // 1 is high, 2 is medium, and 3 is low load/temp + switch (cpu_load) { + case 1: + right_aligned_text(cpu_high_color, ralign_width, "%d", cpu_load_percent); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(cpu_high_color, "%%"); + break; + case 2: + right_aligned_text(cpu_med_color, ralign_width, "%d", cpu_load_percent); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(cpu_med_color, "%%"); + break; + case 3: + right_aligned_text(cpu_low_color, ralign_width, "%d", cpu_load_percent); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(cpu_low_color, "%%"); + break; + } + } + else { + right_aligned_text(text_color, ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); + ImGui::SameLine(0, 1.0f); + ImGui::Text("%%"); + } // ImGui::SameLine(150); // ImGui::Text("%s", "%"); @@ -2140,6 +2168,9 @@ void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overl sw_stats.colors.gpu_load_high = convert(params.gpu_load_high_color); sw_stats.colors.gpu_load_med = convert(params.gpu_load_med_color); sw_stats.colors.gpu_load_low = convert(params.gpu_load_low_color); + sw_stats.colors.cpu_load_high = convert(params.cpu_load_high_color); + sw_stats.colors.cpu_load_med = convert(params.cpu_load_med_color); + sw_stats.colors.cpu_load_low = convert(params.cpu_load_low_color); ImGuiStyle& style = ImGui::GetStyle(); style.Colors[ImGuiCol_PlotLines] = convert(params.frametime_color); From 6b71c9c6e388103ed1124840724ebfe46ed117f1 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Tue, 6 Oct 2020 16:19:17 -0700 Subject: [PATCH 061/130] Remove duplicate code --- src/vulkan.cpp | 49 +++++++++++++++++++------------------------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/src/vulkan.cpp b/src/vulkan.cpp index ce81d874..c215c670 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -991,7 +991,7 @@ void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& } -int change_on_load_temp ( int info, int high, int med) { +int change_on_load_temp (int info, int high, int med) { if (info >= high) { return 1; } @@ -1039,39 +1039,33 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& gpu_text = params.gpu_text.c_str(); ImGui::TextColored(data.colors.gpu, "%s", gpu_text); ImGui::TableNextCell(); - auto gpu_high_color = data.colors.gpu_load_high; - auto gpu_med_color = data.colors.gpu_load_med; - auto gpu_low_color = data.colors.gpu_load_low; auto text_color = data.colors.text; - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){ + auto load_color = data.colors.text; int gpu_load = change_on_load_temp(gpu_info.load, params.gpu_load_high, params.gpu_load_med); // 1 is high, 2 is medium, and 3 is low load/temp switch (gpu_load) { case 1: - right_aligned_text(gpu_high_color, ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(gpu_high_color, "%%"); + load_color = data.colors.gpu_load_high; break; case 2: - right_aligned_text(gpu_med_color, ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(gpu_med_color, "%%"); + load_color = data.colors.gpu_load_med; break; case 3: - right_aligned_text(gpu_low_color, ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(gpu_low_color, "%%"); + load_color = data.colors.gpu_load_low; break; } + right_aligned_text(load_color, ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(load_color,"%%"); } else { right_aligned_text(text_color, ralign_width, "%i", gpu_info.load); ImGui::SameLine(0, 1.0f); - ImGui::Text("%%"); + ImGui::TextColored(text_color,"%%"); + // ImGui::SameLine(150); + // ImGui::Text("%s", "%"); } - // ImGui::SameLine(150); - // ImGui::Text("%s", "%"); if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_temp]){ ImGui::TableNextCell(); right_aligned_text(text_color, ralign_width, "%i", gpu_info.temp); @@ -1106,31 +1100,26 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& cpu_text = params.cpu_text.c_str(); ImGui::TextColored(data.colors.cpu, "%s", cpu_text); ImGui::TableNextCell(); - auto cpu_high_color = data.colors.cpu_load_high; - auto cpu_med_color = data.colors.cpu_load_med; - auto cpu_low_color = data.colors.cpu_load_low; auto text_color = data.colors.text; - int cpu_load_percent = int(cpuStats.GetCPUDataTotal().percent); if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_load_change]){ + int cpu_load_percent = int(cpuStats.GetCPUDataTotal().percent); + auto load_color = data.colors.text; int cpu_load = change_on_load_temp(cpu_load_percent, params.cpu_load_high, params.cpu_load_med); // 1 is high, 2 is medium, and 3 is low load/temp switch (cpu_load) { case 1: - right_aligned_text(cpu_high_color, ralign_width, "%d", cpu_load_percent); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(cpu_high_color, "%%"); + load_color = data.colors.cpu_load_high; break; case 2: - right_aligned_text(cpu_med_color, ralign_width, "%d", cpu_load_percent); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(cpu_med_color, "%%"); + load_color = data.colors.cpu_load_med; break; case 3: - right_aligned_text(cpu_low_color, ralign_width, "%d", cpu_load_percent); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(cpu_low_color, "%%"); + load_color = data.colors.cpu_load_low; break; } + right_aligned_text(load_color, ralign_width, "%d", cpu_load_percent); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(load_color, "%%"); } else { right_aligned_text(text_color, ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); From dc0b3a99553e7c11577a15f514d40e097f5c964b Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Tue, 6 Oct 2020 16:44:46 -0700 Subject: [PATCH 062/130] Set param defaults for load color change --- src/overlay_params.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 5c78fb1f..3fe616a4 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -466,6 +466,8 @@ parse_overlay_config(struct overlay_params *params, params->enabled[OVERLAY_PARAM_ENABLED_io_read] = false; params->enabled[OVERLAY_PARAM_ENABLED_io_write] = false; params->enabled[OVERLAY_PARAM_ENABLED_wine] = false; + params->enabled[OVERLAY_PARAM_ENABLED_gpu_load_change] = false; + params->enabled[OVERLAY_PARAM_ENABLED_cpu_load_change] = false; params->fps_sampling_period = 500000; /* 500ms */ params->width = 0; params->height = 140; @@ -503,6 +505,10 @@ parse_overlay_config(struct overlay_params *params, params->permit_upload = 0; params->render_mango = 0; params->benchmark_percentiles = { "97", "AVG", "1", "0.1" }; + params->gpu_load_high = 90; + params->gpu_load_med = 60; + params->cpu_load_high = 90; + params->cpu_load_med= 60; #ifdef HAVE_X11 params->toggle_hud = { XK_Shift_R, XK_F12 }; From 17ae05516135dc571f3d3478f21a2b58bb42e589 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Tue, 6 Oct 2020 16:53:27 -0700 Subject: [PATCH 063/130] Disable cpu/gpu load change from full param output --- src/overlay_params.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 3fe616a4..ced336f8 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -425,6 +425,8 @@ parse_overlay_env(struct overlay_params *params, #undef OVERLAY_PARAM_BOOL #undef OVERLAY_PARAM_CUSTOM params->enabled[OVERLAY_PARAM_ENABLED_histogram] = 0; + params->enabled[OVERLAY_PARAM_ENABLED_gpu_load_change] = 0; + params->enabled[OVERLAY_PARAM_ENABLED_cpu_load_change] = 0; params->enabled[OVERLAY_PARAM_ENABLED_read_cfg] = read_cfg; } #define OVERLAY_PARAM_BOOL(name) \ From 5e486df67f1419a534ef16eb29e94f5abd796ae5 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Tue, 6 Oct 2020 16:59:47 -0700 Subject: [PATCH 064/130] Fix spacing --- src/overlay_params.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index ced336f8..0edc740e 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -495,12 +495,12 @@ parse_overlay_config(struct overlay_params *params, params->media_player_name = ""; params->font_scale = 1.0f; params->wine_color = 0xeb5b5b; - params->gpu_load_high_color=0xb22222; - params->gpu_load_med_color=0xfdfd09; - params->gpu_load_low_color=0x39f900; - params->cpu_load_high_color=0xb22222; - params->cpu_load_med_color=0xfdfd09; - params->cpu_load_low_color=0x39f900; + params->gpu_load_high_color = 0xb22222; + params->gpu_load_med_color = 0xfdfd09; + params->gpu_load_low_color = 0x39f900; + params->cpu_load_high_color = 0xb22222; + params->cpu_load_med_color = 0xfdfd09; + params->cpu_load_low_color = 0x39f900; params->font_scale_media_player = 0.55f; params->log_interval = 100; params->media_player_order = { MP_ORDER_TITLE, MP_ORDER_ARTIST, MP_ORDER_ALBUM }; @@ -510,7 +510,7 @@ parse_overlay_config(struct overlay_params *params, params->gpu_load_high = 90; params->gpu_load_med = 60; params->cpu_load_high = 90; - params->cpu_load_med= 60; + params->cpu_load_med = 60; #ifdef HAVE_X11 params->toggle_hud = { XK_Shift_R, XK_F12 }; @@ -599,7 +599,7 @@ parse_overlay_config(struct overlay_params *params, ¶ms->media_player_color, ¶ms->wine_color, ¶ms->gpu_load_high_color, - ¶ms-> gpu_load_med_color, + ¶ms->gpu_load_med_color, ¶ms->gpu_load_low_color, ¶ms->cpu_load_high_color, ¶ms->cpu_load_med_color, From e1269a18ff0376c21f7d7f2203187bff28e53230 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Mon, 19 Oct 2020 20:41:39 -0700 Subject: [PATCH 065/130] Consolidate gpu load color config --- src/overlay_params.cpp | 28 +++++++++++++++++++--------- src/overlay_params.h | 9 +++------ src/vulkan.cpp | 10 +++++++--- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 0edc740e..216364f6 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -152,6 +152,19 @@ parse_color(const char *str) return strtol(str, NULL, 16); } +static std::vector +parse_load_color(const char *str) +{ + std::vector load_colors; + std::stringstream ss(str); + std::string token; + while (std::getline(ss, token, ',')) { + trim(token); + load_colors.push_back(std::stoi(token, NULL, 16)); + } + return load_colors; +} + static unsigned parse_unsigned(const char *str) { @@ -324,9 +337,7 @@ parse_font_glyph_ranges(const char *str) #define parse_text_color(s) parse_color(s) #define parse_media_player_color(s) parse_color(s) #define parse_wine_color(s) parse_color(s) -#define parse_gpu_load_high_color(s) parse_color(s) -#define parse_gpu_load_med_color(s) parse_color(s) -#define parse_gpu_load_low_color(s) parse_color(s) +#define parse_gpu_load_color(s) parse_load_color(s) #define parse_gpu_load_high(s) parse_unsigned(s) #define parse_gpu_load_med(s) parse_unsigned(s) #define parse_cpu_load_high_color(s) parse_color(s) @@ -495,9 +506,7 @@ parse_overlay_config(struct overlay_params *params, params->media_player_name = ""; params->font_scale = 1.0f; params->wine_color = 0xeb5b5b; - params->gpu_load_high_color = 0xb22222; - params->gpu_load_med_color = 0xfdfd09; - params->gpu_load_low_color = 0x39f900; + params->gpu_load_color = {0xb22222,0xfdfd09,0x39f900}; params->cpu_load_high_color = 0xb22222; params->cpu_load_med_color = 0xfdfd09; params->cpu_load_low_color = 0x39f900; @@ -512,6 +521,7 @@ parse_overlay_config(struct overlay_params *params, params->cpu_load_high = 90; params->cpu_load_med = 60; + #ifdef HAVE_X11 params->toggle_hud = { XK_Shift_R, XK_F12 }; params->toggle_fps_limit = { XK_Shift_L, XK_F1 }; @@ -598,12 +608,12 @@ parse_overlay_config(struct overlay_params *params, ¶ms->text_color, ¶ms->media_player_color, ¶ms->wine_color, - ¶ms->gpu_load_high_color, - ¶ms->gpu_load_med_color, - ¶ms->gpu_load_low_color, ¶ms->cpu_load_high_color, ¶ms->cpu_load_med_color, ¶ms->cpu_load_low_color, + ¶ms->gpu_load_color[0], + ¶ms->gpu_load_color[1], + ¶ms->gpu_load_color[2], }; diff --git a/src/overlay_params.h b/src/overlay_params.h index b52a1868..84e880ef 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -92,9 +92,6 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(io_color) \ OVERLAY_PARAM_CUSTOM(text_color) \ OVERLAY_PARAM_CUSTOM (wine_color) \ - OVERLAY_PARAM_CUSTOM(gpu_load_high_color) \ - OVERLAY_PARAM_CUSTOM(gpu_load_med_color) \ - OVERLAY_PARAM_CUSTOM(gpu_load_low_color) \ OVERLAY_PARAM_CUSTOM(cpu_load_high_color) \ OVERLAY_PARAM_CUSTOM(cpu_load_med_color) \ OVERLAY_PARAM_CUSTOM(cpu_load_low_color) \ @@ -114,7 +111,8 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(gpu_load_high) \ OVERLAY_PARAM_CUSTOM(gpu_load_med) \ OVERLAY_PARAM_CUSTOM(cpu_load_high) \ - OVERLAY_PARAM_CUSTOM(cpu_load_med) + OVERLAY_PARAM_CUSTOM(cpu_load_med) \ + OVERLAY_PARAM_CUSTOM (gpu_load_color) enum overlay_param_position { @@ -174,8 +172,8 @@ struct overlay_params { int gl_vsync; uint64_t log_duration; unsigned cpu_color, gpu_color, vram_color, ram_color, engine_color, io_color, frametime_color, background_color, text_color, wine_color; - unsigned gpu_load_high_color, gpu_load_med_color, gpu_load_low_color; unsigned cpu_load_high_color, cpu_load_med_color, cpu_load_low_color; + std::vector gpu_load_color; int gpu_load_high, gpu_load_med, gpu_load_change; int cpu_load_high, cpu_load_med, cpu_load_change; unsigned media_player_color; @@ -198,7 +196,6 @@ struct overlay_params { unsigned log_interval; std::vector media_player_order; std::vector benchmark_percentiles; - std::string font_file, font_file_text; uint32_t font_glyph_ranges; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index c215c670..9ab35240 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -1046,6 +1046,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& // 1 is high, 2 is medium, and 3 is low load/temp switch (gpu_load) { case 1: + ///load_color = data.colors.gpu_load_high; load_color = data.colors.gpu_load_high; break; case 2: @@ -2154,13 +2155,16 @@ void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overl sw_stats.colors.text = convert(params.text_color); sw_stats.colors.media_player = convert(params.media_player_color); sw_stats.colors.wine = convert(params.wine_color); - sw_stats.colors.gpu_load_high = convert(params.gpu_load_high_color); - sw_stats.colors.gpu_load_med = convert(params.gpu_load_med_color); - sw_stats.colors.gpu_load_low = convert(params.gpu_load_low_color); + sw_stats.colors.gpu_load_high = convert(params.gpu_load_color[0]); + sw_stats.colors.gpu_load_med = convert(params.gpu_load_color[1]); + sw_stats.colors.gpu_load_low = convert(params.gpu_load_color[2]); + sw_stats.colors.cpu_load_high = convert(params.cpu_load_high_color); sw_stats.colors.cpu_load_med = convert(params.cpu_load_med_color); sw_stats.colors.cpu_load_low = convert(params.cpu_load_low_color); + + ImGuiStyle& style = ImGui::GetStyle(); style.Colors[ImGuiCol_PlotLines] = convert(params.frametime_color); style.Colors[ImGuiCol_PlotHistogram] = convert(params.frametime_color); From daa23d49db2017a2da2652682a0e457e614a9b0a Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Mon, 19 Oct 2020 21:06:10 -0700 Subject: [PATCH 066/130] Consolidate cpu load color config --- src/overlay_params.cpp | 16 ++++++---------- src/overlay_params.h | 8 +++----- src/vulkan.cpp | 8 +++----- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 216364f6..6c4ccd97 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -338,11 +338,9 @@ parse_font_glyph_ranges(const char *str) #define parse_media_player_color(s) parse_color(s) #define parse_wine_color(s) parse_color(s) #define parse_gpu_load_color(s) parse_load_color(s) +#define parse_cpu_load_color(s) parse_load_color(s) #define parse_gpu_load_high(s) parse_unsigned(s) #define parse_gpu_load_med(s) parse_unsigned(s) -#define parse_cpu_load_high_color(s) parse_color(s) -#define parse_cpu_load_med_color(s) parse_color(s) -#define parse_cpu_load_low_color(s) parse_color(s) #define parse_cpu_load_high(s) parse_unsigned(s) #define parse_cpu_load_med(s) parse_unsigned(s) @@ -506,10 +504,8 @@ parse_overlay_config(struct overlay_params *params, params->media_player_name = ""; params->font_scale = 1.0f; params->wine_color = 0xeb5b5b; - params->gpu_load_color = {0xb22222,0xfdfd09,0x39f900}; - params->cpu_load_high_color = 0xb22222; - params->cpu_load_med_color = 0xfdfd09; - params->cpu_load_low_color = 0x39f900; + params->gpu_load_color = { 0xb22222, 0xfdfd09, 0x39f900 }; + params->cpu_load_color = { 0xb22222, 0xfdfd09, 0x39f900 }; params->font_scale_media_player = 0.55f; params->log_interval = 100; params->media_player_order = { MP_ORDER_TITLE, MP_ORDER_ARTIST, MP_ORDER_ALBUM }; @@ -608,12 +604,12 @@ parse_overlay_config(struct overlay_params *params, ¶ms->text_color, ¶ms->media_player_color, ¶ms->wine_color, - ¶ms->cpu_load_high_color, - ¶ms->cpu_load_med_color, - ¶ms->cpu_load_low_color, ¶ms->gpu_load_color[0], ¶ms->gpu_load_color[1], ¶ms->gpu_load_color[2], + ¶ms->cpu_load_color[0], + ¶ms->cpu_load_color[1], + ¶ms->cpu_load_color[2], }; diff --git a/src/overlay_params.h b/src/overlay_params.h index 84e880ef..48dde29d 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -92,9 +92,6 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(io_color) \ OVERLAY_PARAM_CUSTOM(text_color) \ OVERLAY_PARAM_CUSTOM (wine_color) \ - OVERLAY_PARAM_CUSTOM(cpu_load_high_color) \ - OVERLAY_PARAM_CUSTOM(cpu_load_med_color) \ - OVERLAY_PARAM_CUSTOM(cpu_load_low_color) \ OVERLAY_PARAM_CUSTOM(alpha) \ OVERLAY_PARAM_CUSTOM(log_duration) \ OVERLAY_PARAM_CUSTOM(pci_dev) \ @@ -112,7 +109,8 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(gpu_load_med) \ OVERLAY_PARAM_CUSTOM(cpu_load_high) \ OVERLAY_PARAM_CUSTOM(cpu_load_med) \ - OVERLAY_PARAM_CUSTOM (gpu_load_color) + OVERLAY_PARAM_CUSTOM (gpu_load_color) \ + OVERLAY_PARAM_CUSTOM (cpu_load_color) enum overlay_param_position { @@ -172,8 +170,8 @@ struct overlay_params { int gl_vsync; uint64_t log_duration; unsigned cpu_color, gpu_color, vram_color, ram_color, engine_color, io_color, frametime_color, background_color, text_color, wine_color; - unsigned cpu_load_high_color, cpu_load_med_color, cpu_load_low_color; std::vector gpu_load_color; + std::vector cpu_load_color; int gpu_load_high, gpu_load_med, gpu_load_change; int cpu_load_high, cpu_load_med, cpu_load_change; unsigned media_player_color; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 9ab35240..5ed9f6a9 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -1046,7 +1046,6 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& // 1 is high, 2 is medium, and 3 is low load/temp switch (gpu_load) { case 1: - ///load_color = data.colors.gpu_load_high; load_color = data.colors.gpu_load_high; break; case 2: @@ -2158,10 +2157,9 @@ void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overl sw_stats.colors.gpu_load_high = convert(params.gpu_load_color[0]); sw_stats.colors.gpu_load_med = convert(params.gpu_load_color[1]); sw_stats.colors.gpu_load_low = convert(params.gpu_load_color[2]); - - sw_stats.colors.cpu_load_high = convert(params.cpu_load_high_color); - sw_stats.colors.cpu_load_med = convert(params.cpu_load_med_color); - sw_stats.colors.cpu_load_low = convert(params.cpu_load_low_color); + sw_stats.colors.cpu_load_high = convert(params.cpu_load_color[0]); + sw_stats.colors.cpu_load_med = convert(params.cpu_load_color[1]); + sw_stats.colors.cpu_load_low = convert(params.cpu_load_color[2]); From c53939587a839aa14f8d9f751e635ca2577f5824 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Mon, 19 Oct 2020 22:11:26 -0700 Subject: [PATCH 067/130] Consolidate gpu/cpu load value config --- src/overlay_params.cpp | 27 +++++++++++++++++++-------- src/overlay_params.h | 8 ++++---- src/vulkan.cpp | 4 ++-- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 6c4ccd97..44cc86dd 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -165,6 +165,20 @@ parse_load_color(const char *str) return load_colors; } +static std::vector +parse_load_value(const char *str) +{ + std::vector load_value; + std::stringstream ss(str); + std::string token; + while (std::getline(ss, token, ',')) { + trim(token); + load_value.push_back(std::stoi(token)); + } + return load_value; +} + + static unsigned parse_unsigned(const char *str) { @@ -339,10 +353,8 @@ parse_font_glyph_ranges(const char *str) #define parse_wine_color(s) parse_color(s) #define parse_gpu_load_color(s) parse_load_color(s) #define parse_cpu_load_color(s) parse_load_color(s) -#define parse_gpu_load_high(s) parse_unsigned(s) -#define parse_gpu_load_med(s) parse_unsigned(s) -#define parse_cpu_load_high(s) parse_unsigned(s) -#define parse_cpu_load_med(s) parse_unsigned(s) +#define parse_gpu_load_value(s) parse_load_value(s) +#define parse_cpu_load_value(s) parse_load_value(s) static bool parse_help(const char *str) @@ -512,10 +524,9 @@ parse_overlay_config(struct overlay_params *params, params->permit_upload = 0; params->render_mango = 0; params->benchmark_percentiles = { "97", "AVG", "1", "0.1" }; - params->gpu_load_high = 90; - params->gpu_load_med = 60; - params->cpu_load_high = 90; - params->cpu_load_med = 60; + params->gpu_load_value = { 90, 60 }; + params->cpu_load_value = { 90, 60 }; + #ifdef HAVE_X11 diff --git a/src/overlay_params.h b/src/overlay_params.h index 48dde29d..53edcd0e 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -105,10 +105,8 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(render_mango) \ OVERLAY_PARAM_CUSTOM(benchmark_percentiles) \ OVERLAY_PARAM_CUSTOM(help) \ - OVERLAY_PARAM_CUSTOM(gpu_load_high) \ - OVERLAY_PARAM_CUSTOM(gpu_load_med) \ - OVERLAY_PARAM_CUSTOM(cpu_load_high) \ - OVERLAY_PARAM_CUSTOM(cpu_load_med) \ + OVERLAY_PARAM_CUSTOM(gpu_load_value) \ + OVERLAY_PARAM_CUSTOM(cpu_load_value) \ OVERLAY_PARAM_CUSTOM (gpu_load_color) \ OVERLAY_PARAM_CUSTOM (cpu_load_color) @@ -172,6 +170,8 @@ struct overlay_params { unsigned cpu_color, gpu_color, vram_color, ram_color, engine_color, io_color, frametime_color, background_color, text_color, wine_color; std::vector gpu_load_color; std::vector cpu_load_color; + std::vector gpu_load_value; + std::vector cpu_load_value; int gpu_load_high, gpu_load_med, gpu_load_change; int cpu_load_high, cpu_load_med, cpu_load_change; unsigned media_player_color; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 5ed9f6a9..563080ef 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -1042,7 +1042,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& auto text_color = data.colors.text; if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){ auto load_color = data.colors.text; - int gpu_load = change_on_load_temp(gpu_info.load, params.gpu_load_high, params.gpu_load_med); + int gpu_load = change_on_load_temp(gpu_info.load, params.gpu_load_value[0], params.gpu_load_value[1]); // 1 is high, 2 is medium, and 3 is low load/temp switch (gpu_load) { case 1: @@ -1104,7 +1104,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_load_change]){ int cpu_load_percent = int(cpuStats.GetCPUDataTotal().percent); auto load_color = data.colors.text; - int cpu_load = change_on_load_temp(cpu_load_percent, params.cpu_load_high, params.cpu_load_med); + int cpu_load = change_on_load_temp(cpu_load_percent, params.cpu_load_value[0], params.cpu_load_value[1]); // 1 is high, 2 is medium, and 3 is low load/temp switch (cpu_load) { case 1: From 3e446f7c111224947d5a8e9b0418d251d1e0606b Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Tue, 20 Oct 2020 20:42:57 -0700 Subject: [PATCH 068/130] Remove unused variables --- src/overlay_params.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/overlay_params.h b/src/overlay_params.h index 53edcd0e..a86ad872 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -172,8 +172,7 @@ struct overlay_params { std::vector cpu_load_color; std::vector gpu_load_value; std::vector cpu_load_value; - int gpu_load_high, gpu_load_med, gpu_load_change; - int cpu_load_high, cpu_load_med, cpu_load_change; + int gpu_load_change, cpu_load_change; unsigned media_player_color; unsigned tableCols; unsigned render_mango; From 76c2129ae25eb97cb65f4842f855f26394429298 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Tue, 20 Oct 2020 20:46:35 -0700 Subject: [PATCH 069/130] Remove more unused variables --- src/overlay_params.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlay_params.h b/src/overlay_params.h index a86ad872..02983d20 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -172,7 +172,7 @@ struct overlay_params { std::vector cpu_load_color; std::vector gpu_load_value; std::vector cpu_load_value; - int gpu_load_change, cpu_load_change; + //int gpu_load_change, cpu_load_change; unsigned media_player_color; unsigned tableCols; unsigned render_mango; From ec322b556e972ab2a7fe57303eb66e2ac1ccaf20 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Tue, 20 Oct 2020 21:14:04 -0700 Subject: [PATCH 070/130] Formatting fixes, remove commented code --- src/overlay_params.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/overlay_params.h b/src/overlay_params.h index 02983d20..b814e185 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -107,8 +107,8 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(help) \ OVERLAY_PARAM_CUSTOM(gpu_load_value) \ OVERLAY_PARAM_CUSTOM(cpu_load_value) \ - OVERLAY_PARAM_CUSTOM (gpu_load_color) \ - OVERLAY_PARAM_CUSTOM (cpu_load_color) + OVERLAY_PARAM_CUSTOM(gpu_load_color) \ + OVERLAY_PARAM_CUSTOM(cpu_load_color) enum overlay_param_position { @@ -172,7 +172,6 @@ struct overlay_params { std::vector cpu_load_color; std::vector gpu_load_value; std::vector cpu_load_value; - //int gpu_load_change, cpu_load_change; unsigned media_player_color; unsigned tableCols; unsigned render_mango; From 9974992f7a526e5cf67eddb1d5637156d36a3154 Mon Sep 17 00:00:00 2001 From: jackun Date: Thu, 22 Oct 2020 19:22:54 +0300 Subject: [PATCH 071/130] Some distros annoyingly prefix `tls/[x86_64|i686]` with arch triplet --- bin/mangohud-setup.sh | 3 +++ build.sh | 3 +++ 2 files changed, 6 insertions(+) diff --git a/bin/mangohud-setup.sh b/bin/mangohud-setup.sh index da5ec320..232706e8 100755 --- a/bin/mangohud-setup.sh +++ b/bin/mangohud-setup.sh @@ -58,6 +58,9 @@ mangohud_install() { mkdir -p /usr/lib/mangohud/tls ln -sv ../lib /usr/lib/mangohud/tls/x86_64 ln -sv ../lib32 /usr/lib/mangohud/tls/i686 + # Some distros search in $prefix/x86_64-linux-gnu/tls/x86_64 etc instead + ln -sv . /usr/lib/mangohud/lib/i686-linux-gnu + ln -sv . /usr/lib/mangohud/lib/x86_64-linux-gnu # $LIB can be "lib/tls/x86_64"? ln -sv ../tls /usr/lib/mangohud/lib/tls #ln -sv lib /usr/lib/mangohud/aarch64-linux-gnu diff --git a/build.sh b/build.sh index 05b08462..269e9a8b 100755 --- a/build.sh +++ b/build.sh @@ -217,6 +217,9 @@ install() { mkdir -p /usr/lib/mangohud/tls ln -sv ../lib /usr/lib/mangohud/tls/x86_64 ln -sv ../lib32 /usr/lib/mangohud/tls/i686 + # Some distros search in $prefix/x86_64-linux-gnu/tls/x86_64 etc instead + ln -sv . /usr/lib/mangohud/lib/i686-linux-gnu + ln -sv . /usr/lib/mangohud/lib/x86_64-linux-gnu # $LIB can be "lib/tls/x86_64"? ln -sv ../tls /usr/lib/mangohud/lib/tls #ln -sv lib /usr/lib/mangohud/aarch64-linux-gnu From b9b20d11177f62c6cf58a381a31b8e034f32b992 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Mon, 2 Nov 2020 13:56:52 +0100 Subject: [PATCH 072/130] Remove render_mango as it's no longer needed --- src/font.cpp | 2 - src/overlay_params.cpp | 2 - src/overlay_params.h | 2 - src/vulkan.cpp | 83 +----------------------------------------- 4 files changed, 1 insertion(+), 88 deletions(-) diff --git a/src/font.cpp b/src/font.cpp index 691d3882..a5abb5d9 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -13,8 +13,6 @@ void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& te float font_size_text = params.font_size_text; if (font_size_text < FLT_EPSILON) font_size_text = font_size; - if(params.render_mango) - font_size = 42; static const ImWchar default_range[] = { 0x0020, 0x00FF, // Basic Latin + Latin Supplement diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 44cc86dd..3f8717c7 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -338,7 +338,6 @@ parse_font_glyph_ranges(const char *str) #define parse_background_alpha(s) parse_float(s) #define parse_alpha(s) parse_float(s) #define parse_permit_upload(s) parse_unsigned(s) -#define parse_render_mango(s) parse_unsigned(s) #define parse_cpu_color(s) parse_color(s) #define parse_gpu_color(s) parse_color(s) @@ -522,7 +521,6 @@ parse_overlay_config(struct overlay_params *params, params->log_interval = 100; params->media_player_order = { MP_ORDER_TITLE, MP_ORDER_ARTIST, MP_ORDER_ALBUM }; params->permit_upload = 0; - params->render_mango = 0; params->benchmark_percentiles = { "97", "AVG", "1", "0.1" }; params->gpu_load_value = { 90, 60 }; params->cpu_load_value = { 90, 60 }; diff --git a/src/overlay_params.h b/src/overlay_params.h index b814e185..658e0da4 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -102,7 +102,6 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(gpu_text) \ OVERLAY_PARAM_CUSTOM(log_interval) \ OVERLAY_PARAM_CUSTOM(permit_upload) \ - OVERLAY_PARAM_CUSTOM(render_mango) \ OVERLAY_PARAM_CUSTOM(benchmark_percentiles) \ OVERLAY_PARAM_CUSTOM(help) \ OVERLAY_PARAM_CUSTOM(gpu_load_value) \ @@ -174,7 +173,6 @@ struct overlay_params { std::vector cpu_load_value; unsigned media_player_color; unsigned tableCols; - unsigned render_mango; float font_size, font_scale; float font_size_text; float font_scale_media_player; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 563080ef..3e419673 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -915,82 +915,6 @@ void render_benchmark(swapchain_stats& data, struct overlay_params& params, ImVe ImGui::End(); } -void render_mango(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan){ - static int tableCols = 2; - static float ralign_width = 0, old_scale = 0; - window_size = ImVec2(300, params.height); - - if (old_scale != params.font_scale) { - ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; - old_scale = params.font_scale; - } - ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); - ImGui::BeginTable("hud", tableCols); - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats]){ - ImGui::TableNextRow(); - const char* gpu_text; - if (params.gpu_text.empty()) - gpu_text = "GPU"; - else - gpu_text = params.gpu_text.c_str(); - ImGui::TextColored(data.colors.gpu, "%s", gpu_text); - ImGui::TableNextCell(); - right_aligned_text(data.colors.text, ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::Text("%%"); - } - if(params.enabled[OVERLAY_PARAM_ENABLED_cpu_stats]){ - ImGui::TableNextRow(); - const char* cpu_text; - if (params.cpu_text.empty()) - cpu_text = "CPU"; - else - cpu_text = params.cpu_text.c_str(); - ImGui::TextColored(data.colors.cpu, "%s", cpu_text); - ImGui::TableNextCell(); - right_aligned_text(data.colors.text, ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); - ImGui::SameLine(0, 1.0f); - ImGui::Text("%%"); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_fps]){ - ImGui::TableNextRow(); - ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); - ImGui::TableNextCell(); - right_aligned_text(data.colors.text, ralign_width, "%.0f", data.fps); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("FPS"); - ImGui::PopFont(); - } - ImGui::EndTable(); - if (params.enabled[OVERLAY_PARAM_ENABLED_frame_timing]){ - ImGui::Dummy(ImVec2(0.0f, 8.0f)); - ImGui::PushFont(data.font1); - ImGui::TextColored(data.colors.engine, "%s", "Frametime"); - ImGui::PopFont(); - - char hash[40]; - snprintf(hash, sizeof(hash), "##%s", overlay_param_names[OVERLAY_PARAM_ENABLED_frame_timing]); - data.stat_selector = OVERLAY_PLOTS_frame_timing; - data.time_dividor = 1000.0f; - - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); - double min_time = 0.0f; - double max_time = 50.0f; - ImGui::PlotLines(hash, get_time_stat, &data, - ARRAY_SIZE(data.frames_stats), 0, - NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); - - ImGui::PopStyleColor(); - } - if(logger->is_active()) - ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(data.main_window_pos.x + window_size.x - 15, data.main_window_pos.y + 15), 10, params.engine_color, 20); - ImGui::End(); - window_size = ImVec2(window_size.x, 200); -} - - int change_on_load_temp (int info, int high, int med) { if (info >= high) { return 1; @@ -1359,12 +1283,7 @@ static void compute_swapchain_display(struct swapchain_data *data) { scoped_lock lk(instance_data->notifier.mutex); position_layer(data->sw_stats, instance_data->params, data->window_size); -#ifdef __gnu_linux__ - if(instance_data->params.render_mango) - render_mango(data->sw_stats, instance_data->params, data->window_size, true); - else - render_imgui(data->sw_stats, instance_data->params, data->window_size, true); -#endif + render_imgui(data->sw_stats, instance_data->params, data->window_size, true); } ImGui::PopStyleVar(3); From b75f2944a11af7870b16e88f5fe0f4f456386803 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Wed, 21 Oct 2020 21:39:53 -0700 Subject: [PATCH 073/130] Add struct for gpu color change data --- src/vulkan.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 3e419673..4e765c23 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -927,6 +927,17 @@ int change_on_load_temp (int info, int high, int med) { } } + +struct LOAD_DATA { + ImVec4 color_high; + ImVec4 color_med; + ImVec4 color_low; + unsigned high_load; + unsigned med_load; +}; + + + void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan) { ImGui::GetIO().FontGlobalScale = params.font_scale; @@ -966,6 +977,13 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& auto text_color = data.colors.text; if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){ auto load_color = data.colors.text; + struct LOAD_DATA gpu_data = {data.colors.gpu_load_high, + data.colors.gpu_load_med, + data.colors.gpu_load_low, + params.gpu_load_value[0], + params.gpu_load_value[1] + }; + int gpu_load = change_on_load_temp(gpu_info.load, params.gpu_load_value[0], params.gpu_load_value[1]); // 1 is high, 2 is medium, and 3 is low load/temp switch (gpu_load) { From 0a12632679c567749fc8e4e46fd51acd2cad9c0c Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Thu, 22 Oct 2020 07:17:14 +0200 Subject: [PATCH 074/130] Gradual color change --- src/overlay.h | 8 ++++++ src/vulkan.cpp | 73 +++++++++++++++++--------------------------------- 2 files changed, 33 insertions(+), 48 deletions(-) diff --git a/src/overlay.h b/src/overlay.h index 80ca85b1..2f3b7d76 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -81,6 +81,14 @@ struct benchmark_stats { std::vector> percentile_data; }; +struct LOAD_DATA { + ImVec4 color_high; + ImVec4 color_med; + ImVec4 color_low; + unsigned high_load; + unsigned med_load; +}; + extern struct fps_limit fps_limit_stats; extern int32_t deviceID; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 4e765c23..c8e44b65 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -915,29 +915,23 @@ void render_benchmark(swapchain_stats& data, struct overlay_params& params, ImVe ImGui::End(); } -int change_on_load_temp (int info, int high, int med) { - if (info >= high) { - return 1; - } - else if (info >= med && info < high) { - return 2; - } - else { - return 3; + +ImVec4 change_on_load_temp (struct LOAD_DATA& data, int current) { + if (current >= data.med_load){ + float diff = float(current - data.med_load) / float(data.high_load - data.med_load); + float x = (data.color_high.x - data.color_med.x) * diff; + float y = (data.color_high.y - data.color_med.y) * diff; + float z = (data.color_high.z - data.color_med.z) * diff; + return ImVec4(data.color_med.x + x, data.color_med.y + y, data.color_med.z + z, 1.0); + } else { + float diff = float(current) / float(data.med_load); + float x = (data.color_med.x - data.color_low.x) * diff; + float y = (data.color_med.y - data.color_low.y) * diff; + float z = (data.color_med.z - data.color_low.z) * diff; + return ImVec4(data.color_low.x + x, data.color_low.y + y, data.color_low.z + z, 1.0); } } - -struct LOAD_DATA { - ImVec4 color_high; - ImVec4 color_med; - ImVec4 color_low; - unsigned high_load; - unsigned med_load; -}; - - - void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan) { ImGui::GetIO().FontGlobalScale = params.font_scale; @@ -976,7 +970,6 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextCell(); auto text_color = data.colors.text; if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){ - auto load_color = data.colors.text; struct LOAD_DATA gpu_data = {data.colors.gpu_load_high, data.colors.gpu_load_med, data.colors.gpu_load_low, @@ -984,19 +977,8 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& params.gpu_load_value[1] }; - int gpu_load = change_on_load_temp(gpu_info.load, params.gpu_load_value[0], params.gpu_load_value[1]); - // 1 is high, 2 is medium, and 3 is low load/temp - switch (gpu_load) { - case 1: - load_color = data.colors.gpu_load_high; - break; - case 2: - load_color = data.colors.gpu_load_med; - break; - case 3: - load_color = data.colors.gpu_load_low; - break; - } + + auto load_color = change_on_load_temp(gpu_data, gpu_info.load); right_aligned_text(load_color, ralign_width, "%i", gpu_info.load); ImGui::SameLine(0, 1.0f); ImGui::TextColored(load_color,"%%"); @@ -1045,20 +1027,15 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& auto text_color = data.colors.text; if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_load_change]){ int cpu_load_percent = int(cpuStats.GetCPUDataTotal().percent); - auto load_color = data.colors.text; - int cpu_load = change_on_load_temp(cpu_load_percent, params.cpu_load_value[0], params.cpu_load_value[1]); - // 1 is high, 2 is medium, and 3 is low load/temp - switch (cpu_load) { - case 1: - load_color = data.colors.cpu_load_high; - break; - case 2: - load_color = data.colors.cpu_load_med; - break; - case 3: - load_color = data.colors.cpu_load_low; - break; - } + struct LOAD_DATA cpu_data = {data.colors.cpu_load_high, + data.colors.cpu_load_med, + data.colors.cpu_load_low, + params.cpu_load_value[0], + params.cpu_load_value[1] + }; + + + auto load_color = change_on_load_temp(cpu_data, cpu_load_percent); right_aligned_text(load_color, ralign_width, "%d", cpu_load_percent); ImGui::SameLine(0, 1.0f); ImGui::TextColored(load_color, "%%"); From 2496ab35416263817424df510e2fd96bb023112a Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Thu, 22 Oct 2020 16:56:17 -0700 Subject: [PATCH 075/130] After parsing load colors make sure it has a size of 3 --- src/overlay_params.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 3f8717c7..1dd95bd5 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -162,6 +162,10 @@ parse_load_color(const char *str) trim(token); load_colors.push_back(std::stoi(token, NULL, 16)); } + while (load_colors.size() != 3) { + load_colors.push_back(std::stoi("FFFFFF" , NULL, 16)); + } + return load_colors; } From 466fc1a0084d0c7b4a1b1bc95826753df11319b3 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Sun, 25 Oct 2020 10:22:05 -0700 Subject: [PATCH 076/130] If load is high set the defined high color --- src/vulkan.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vulkan.cpp b/src/vulkan.cpp index c8e44b65..5e9a4c62 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -917,7 +917,10 @@ void render_benchmark(swapchain_stats& data, struct overlay_params& params, ImVe ImVec4 change_on_load_temp (struct LOAD_DATA& data, int current) { - if (current >= data.med_load){ + if (current >= data.high_load){ + return data.color_high; + } + else if (current >= data.med_load){ float diff = float(current - data.med_load) / float(data.high_load - data.med_load); float x = (data.color_high.x - data.color_med.x) * diff; float y = (data.color_high.y - data.color_med.y) * diff; From 06f8641363b553021a46b5f9cae6488d82ed176d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hor=C3=A1=C4=8Dek?= Date: Wed, 4 Nov 2020 11:35:29 +0100 Subject: [PATCH 077/130] Fix for FPS limit breaking Fixes #127 --- src/vulkan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 3e419673..ed78179c 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -2425,7 +2425,7 @@ void FpsLimiter(struct fps_limit& stats){ auto adjustedSleep = stats.sleepTime - stats.frameOverhead; this_thread::sleep_for(adjustedSleep); stats.frameOverhead = ((Clock::now() - stats.frameStart) - adjustedSleep); - if (stats.frameOverhead > stats.targetFrameTime) + if (stats.frameOverhead > stats.targetFrameTime / 2) stats.frameOverhead = Clock::duration(0); } } From fde20cac81af8abfe2bac7e0696171880910e586 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Fri, 6 Nov 2020 22:04:10 +0100 Subject: [PATCH 078/130] Collect total vram for Nvidia --- src/gpu.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gpu.cpp b/src/gpu.cpp index 57724f38..0c8119d0 100644 --- a/src/gpu.cpp +++ b/src/gpu.cpp @@ -34,6 +34,7 @@ void getNvidiaGpuInfo(){ gpu_info.CoreClock = nvidiaCoreClock; gpu_info.MemClock = nvidiaMemClock; gpu_info.powerUsage = nvidiaPowerUsage / 1000; + gpu_info.memoryTotal = nvidiaMemory.total / (1024.f * 1024.f * 1024.f); return; } #endif @@ -46,6 +47,7 @@ void getNvidiaGpuInfo(){ gpu_info.CoreClock = nvctrl_info.CoreClock; gpu_info.MemClock = nvctrl_info.MemClock; gpu_info.powerUsage = 0; + gpu_info.memoryTotal = nvctrl_info.memoryTotal; return; } #endif From 7a8a8d2b009aa2ac53d9693fa089b3303f47b9db Mon Sep 17 00:00:00 2001 From: Stephan Lachnit Date: Sun, 8 Nov 2020 11:49:52 +0100 Subject: [PATCH 079/130] update vulkan-headers to 1.2.158 Signed-off-by: Stephan Lachnit --- subprojects/vulkan-headers.wrap | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/subprojects/vulkan-headers.wrap b/subprojects/vulkan-headers.wrap index eca519fa..bc390b0f 100644 --- a/subprojects/vulkan-headers.wrap +++ b/subprojects/vulkan-headers.wrap @@ -1,10 +1,8 @@ [wrap-file] -directory = Vulkan-Headers-1.2.142 - -source_url = https://github.com/KhronosGroup/Vulkan-Headers/archive/v1.2.142.tar.gz -source_filename = v1.2.142.tar.gz -source_hash = 6770503b0e06bd45e8cb1dba1e40ad37097d1100c2de7cd45c07de3b2d383a3e - -patch_url = https://wrapdb.mesonbuild.com/v1/projects/vulkan-headers/1.2.142/1/get_zip -patch_filename = vulkan-headers-1.2.142-1-wrap.zip -patch_hash = ca4ebafdf6eff48261ac87ec674bf82bf2cb7e2aedf45ef1cf5ea6326e27c123 +directory = Vulkan-Headers-1.2.158 +source_url = https://github.com/KhronosGroup/Vulkan-Headers/archive/v1.2.158.tar.gz +source_filename = v1.2.158.tar.gz +source_hash = 53361271cfe274df8782e1e47bdc9e61b7af432ba30acbfe31723f9df2c257f3 +patch_url = https://wrapdb.mesonbuild.com/v1/projects/vulkan-headers/1.2.158/1/get_zip +patch_filename = vulkan-headers-1.2.158-1-wrap.zip +patch_hash = 5c791eaecf0b0a71bd1d854dc77ee131a242e14a108fdebd917ffa03491949d2 From 7471d42cac05815e557e29324f1b5e496f2f99fe Mon Sep 17 00:00:00 2001 From: jackun Date: Mon, 9 Nov 2020 20:11:16 +0200 Subject: [PATCH 080/130] Fix dbus for GCC 5 --- src/dbus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dbus.cpp b/src/dbus.cpp index a6fc76f8..0acccc3e 100644 --- a/src/dbus.cpp +++ b/src/dbus.cpp @@ -204,7 +204,7 @@ bool dbus_manager::select_active_player() { if (m_active_player.empty()) { auto it = std::find_if(m_name_owners.begin(), m_name_owners.end(), [this, &meta](auto& entry){ auto& name = entry.first; - get_media_player_metadata(meta, name); + this->get_media_player_metadata(meta, name); if(meta.playing) { return true; } From 378cc1e089110caf9a36ca6ae7345de4cb79f6a3 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Tue, 3 Nov 2020 15:34:18 +0100 Subject: [PATCH 081/130] Push params to HudElements options --- src/config.cpp | 7 +++++-- src/hud_elements.cpp | 3 +++ src/hud_elements.h | 9 +++++++++ src/meson.build | 1 + 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/hud_elements.cpp create mode 100644 src/hud_elements.h diff --git a/src/config.cpp b/src/config.cpp index 7d33106b..a5cfe3fd 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -6,7 +6,7 @@ #include "config.h" #include "file_utils.h" #include "string_utils.h" - +#include "hud_elements.h" std::string program_name; void parseConfigLine(std::string line, std::unordered_map& options) { @@ -24,8 +24,10 @@ void parseConfigLine(std::string line, std::unordered_map& paths) @@ -67,6 +69,7 @@ void enumerate_config_files(std::vector& paths) } void parseConfigFile(overlay_params& params) { + HUDElements.options.clear(); params.options.clear(); std::vector paths; const char *cfg_file = getenv("MANGOHUD_CONFIGFILE"); diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp new file mode 100644 index 00000000..93375875 --- /dev/null +++ b/src/hud_elements.cpp @@ -0,0 +1,3 @@ +#include "hud_elements.h" + +HudElements HUDElements; \ No newline at end of file diff --git a/src/hud_elements.h b/src/hud_elements.h new file mode 100644 index 00000000..865715d9 --- /dev/null +++ b/src/hud_elements.h @@ -0,0 +1,9 @@ +#pragma once +#include "overlay.h" +#include "overlay_params.h" +class HudElements{ + public: + std::vector options; +}; + +extern HudElements HUDElements; \ No newline at end of file diff --git a/src/meson.build b/src/meson.build index 6f02da73..da4847e2 100644 --- a/src/meson.build +++ b/src/meson.build @@ -27,6 +27,7 @@ foreach s : ['overlay.frag', 'overlay.vert'] endforeach vklayer_files = files( + 'hud_elements.cpp', 'overlay.cpp', 'overlay_params.cpp', 'font.cpp', From aebd3353ab0ac98948cec890b00a2fce6a8630cc Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Tue, 3 Nov 2020 15:35:10 +0100 Subject: [PATCH 082/130] Move most hud elements into HudElement functions --- src/hud_elements.cpp | 377 +++++++++++++++++++++++++++++++++++++++++ src/hud_elements.h | 24 +++ src/overlay.h | 13 +- src/overlay_params.cpp | 5 + src/overlay_params.h | 3 +- src/vulkan.cpp | 308 +-------------------------------- 6 files changed, 427 insertions(+), 303 deletions(-) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 93375875..e01a127b 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -1,3 +1,380 @@ +#include #include "hud_elements.h" +#include "cpu.h" +#include "memory.h" +#include "mesa/util/macros.h" +// void HudElements::newRow(){ +// ImGui::TableNextRow(); +// } + +// void HudElements::text(){ +// auto text = HUDElements.options.at(HUDElements.place); +// text.erase(std::remove(text.begin(), text.end(), '%'), text.end()); +// size_t underscores_found = text.find("_"); +// // remove all underscores +// for (size_t i = 0; i < underscores_found; i++) +// { +// text.replace(text.find("_"), 1, " "); +// } + +// printf("%s\n", text.c_str()); +// ImGui::Text(text.c_str()); +// } + +void HudElements::time(){ + ImGui::TableNextRow(); + ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.00f), "%s", HUDElements.sw_stats->time.c_str()); +} + +void HudElements::version(){ + ImGui::TableNextRow(); + ImGui::Text("%s", MANGOHUD_VERSION); +} + +void HudElements::gpu_stats(){ + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_stats]){ + ImGui::TableNextRow(); + const char* gpu_text; + if (HUDElements.params->gpu_text.empty()) + gpu_text = "GPU"; + else + gpu_text = HUDElements.params->gpu_text.c_str(); + ImGui::TextColored(HUDElements.sw_stats->colors.gpu, "%s", gpu_text); + ImGui::TableNextCell(); + auto text_color = HUDElements.sw_stats->colors.text; + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){ + struct LOAD_DATA gpu_data = {HUDElements.sw_stats->colors.gpu_load_high, + HUDElements.sw_stats->colors.gpu_load_med, + HUDElements.sw_stats->colors.gpu_load_low, + HUDElements.params->gpu_load_value[0], + HUDElements.params->gpu_load_value[1] + }; + + + auto load_color = change_on_load_temp(gpu_data, gpu_info.load); + right_aligned_text(load_color, HUDElements.ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(load_color,"%%"); + } + else { + right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(text_color,"%%"); + // ImGui::SameLine(150); + // ImGui::Text("%s", "%"); + } + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_temp]){ + ImGui::TableNextCell(); + right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.temp); + ImGui::SameLine(0, 1.0f); + ImGui::Text("°C"); + } + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock] || HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_power]) + ImGui::TableNextRow(); + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock]){ + ImGui::TableNextCell(); + right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.CoreClock); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("MHz"); + ImGui::PopFont(); + } + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_power]) { + ImGui::TableNextCell(); + right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.powerUsage); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("W"); + ImGui::PopFont(); + } + } +} + +void HudElements::cpu_stats(){ + if(HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_stats]){ + ImGui::TableNextRow(); + const char* cpu_text; + if (HUDElements.params->cpu_text.empty()) + cpu_text = "CPU"; + else + cpu_text = HUDElements.params->cpu_text.c_str(); + ImGui::TextColored(HUDElements.sw_stats->colors.cpu, "%s", cpu_text); + ImGui::TableNextCell(); + auto text_color = HUDElements.sw_stats->colors.text; + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_load_change]){ + int cpu_load_percent = int(cpuStats.GetCPUDataTotal().percent); + struct LOAD_DATA cpu_data = {HUDElements.sw_stats->colors.cpu_load_high, + HUDElements.sw_stats->colors.cpu_load_med, + HUDElements.sw_stats->colors.cpu_load_low, + HUDElements.params->cpu_load_value[0], + HUDElements.params->cpu_load_value[1] + }; + + + auto load_color = change_on_load_temp(cpu_data, cpu_load_percent); + right_aligned_text(load_color, HUDElements.ralign_width, "%d", cpu_load_percent); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(load_color, "%%"); + } + else { + right_aligned_text(text_color, HUDElements.ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); + ImGui::SameLine(0, 1.0f); + ImGui::Text("%%"); + } + + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_temp]){ + ImGui::TableNextCell(); + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); + ImGui::SameLine(0, 1.0f); + ImGui::Text("°C"); + } + } +} + +void HudElements::core_load(){ + int i = 0; + for (const CPUData &cpuData : cpuStats.GetCPUData()) + { + ImGui::TableNextRow(); + ImGui::TextColored(HUDElements.sw_stats->colors.cpu, "CPU"); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.cpu,"%i", i); + ImGui::PopFont(); + ImGui::TableNextCell(); + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", int(cpuData.percent)); + ImGui::SameLine(0, 1.0f); + ImGui::Text("%%"); + ImGui::TableNextCell(); + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuData.mhz); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("MHz"); + ImGui::PopFont(); + i++; + } +} +void HudElements::io_stats(){ + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read] || HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]){ + auto sampling = HUDElements.params->fps_sampling_period; + ImGui::TableNextRow(); + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read] && !HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]) + ImGui::TextColored(HUDElements.sw_stats->colors.io, "IO RD"); + else if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read] && HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]) + ImGui::TextColored(HUDElements.sw_stats->colors.io, "IO RW"); + else if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write] && !HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read]) + ImGui::TextColored(HUDElements.sw_stats->colors.io, "IO WR"); + + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read]){ + ImGui::TableNextCell(); + float val = HUDElements.sw_stats->io.diff.read * 1000000 / sampling; + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, val < 100 ? "%.1f" : "%.f", val); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("MiB/s"); + ImGui::PopFont(); + } + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]){ + ImGui::TableNextCell(); + float val = HUDElements.sw_stats->io.diff.write * 1000000 / sampling; + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, val < 100 ? "%.1f" : "%.f", val); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("MiB/s"); + ImGui::PopFont(); + } + } +} + +void HudElements::vram(){ + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_vram]){ + ImGui::TableNextRow(); + ImGui::TextColored(HUDElements.sw_stats->colors.vram, "VRAM"); + ImGui::TableNextCell(); + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.1f", gpu_info.memoryUsed); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("GiB"); + ImGui::PopFont(); + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_mem_clock]){ + ImGui::TableNextCell(); + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", gpu_info.MemClock); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("MHz"); + ImGui::PopFont(); + } + } +} +void HudElements::ram(){ +#ifdef __gnu_linux__ + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_ram]){ + ImGui::TableNextRow(); + ImGui::TextColored(HUDElements.sw_stats->colors.ram, "RAM"); + ImGui::TableNextCell(); + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.1f", memused); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("GiB"); + ImGui::PopFont(); + } +#endif +} + +void HudElements::fps(){ +if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_fps]){ + ImGui::TableNextRow(); + if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_fps] && HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_engine_version]){ + ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", HUDElements.is_vulkan ? HUDElements.sw_stats->engineName.c_str() : "OpenGL"); + } + ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", HUDElements.is_vulkan ? HUDElements.sw_stats->engineName.c_str() : "OpenGL"); + ImGui::TableNextCell(); + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.0f", HUDElements.sw_stats->fps); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("FPS"); + ImGui::PopFont(); + ImGui::TableNextCell(); + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.1f", 1000 / HUDElements.sw_stats->fps); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("ms"); + ImGui::PopFont(); + } +} + +void HudElements::gpu_name(){ + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_name] && !HUDElements.sw_stats->gpuName.empty()){ + ImGui::TableNextRow(); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.engine, + "%s", HUDElements.sw_stats->gpuName.c_str()); + ImGui::PopFont(); + } +} +void HudElements::engine_version(){ + ImGui::TableNextRow(); + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_engine_version]){ + ImGui::PushFont(HUDElements.sw_stats->font1); + if (HUDElements.is_vulkan) { + if ((HUDElements.sw_stats->engineName == "DXVK" || HUDElements.sw_stats->engineName == "VKD3D")){ + ImGui::TextColored(HUDElements.sw_stats->colors.engine, + "%s/%d.%d.%d", HUDElements.sw_stats->engineVersion.c_str(), + HUDElements.sw_stats->version_vk.major, + HUDElements.sw_stats->version_vk.minor, + HUDElements.sw_stats->version_vk.patch); + } else { + ImGui::TextColored(HUDElements.sw_stats->colors.engine, + "%d.%d.%d", + HUDElements.sw_stats->version_vk.major, + HUDElements.sw_stats->version_vk.minor, + HUDElements.sw_stats->version_vk.patch); + } + } else { + ImGui::TextColored(HUDElements.sw_stats->colors.engine, + "%d.%d%s", HUDElements.sw_stats->version_gl.major, HUDElements.sw_stats->version_gl.minor, + HUDElements.sw_stats->version_gl.is_gles ? " ES" : ""); + } + // ImGui::SameLine(); + ImGui::PopFont(); + } +} + +void HudElements::vulkan_driver(){ + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_vulkan_driver] && !HUDElements.sw_stats->driverName.empty()){ + ImGui::TableNextRow(); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.engine, + "%s", HUDElements.sw_stats->driverName.c_str()); + ImGui::PopFont(); + } +} + +void HudElements::arch(){ + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_arch]){ + ImGui::TableNextRow(); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "" MANGOHUD_ARCH); + ImGui::PopFont(); + } +} + +void HudElements::wine(){ + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_wine]){ + ImGui::TableNextRow(); + if (!wineVersion.empty()){ + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.wine, "%s", wineVersion.c_str()); + ImGui::PopFont(); + } + } +} + +void HudElements::frame_timing(){ + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_frame_timing]){ + ImGui::TableNextRow(); + ImGui::Dummy(ImVec2(0.0f, real_font_size.y)); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "Frametime"); + ImGui::PopFont(); + ImGui::TableNextRow(); + char hash[40]; + snprintf(hash, sizeof(hash), "##%s", overlay_param_names[OVERLAY_PARAM_ENABLED_frame_timing]); + HUDElements.sw_stats->stat_selector = OVERLAY_PLOTS_frame_timing; + HUDElements.sw_stats->time_dividor = 1000.0f; + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); + double min_time = 0.0f; + double max_time = 50.0f; + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_histogram]){ + ImGui::PlotHistogram(hash, get_time_stat, HUDElements.sw_stats, + ARRAY_SIZE(HUDElements.sw_stats->frames_stats), 0, + NULL, min_time, max_time, + ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); + } else { + ImGui::PlotLines(hash, get_time_stat, HUDElements.sw_stats, + ARRAY_SIZE(HUDElements.sw_stats->frames_stats), 0, + NULL, min_time, max_time, + ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); + } + ImGui::PopStyleColor(); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("%.1f ms", 1000 / HUDElements.sw_stats->fps); //frame_timing / 1000.f); + ImGui::PopFont(); + } +} + +void HudElements::sort_elements(std::string string){ + if (string == "version") + HUDElements.ordered_functions.push_back(HUDElements.version); + if (string == "time") + HUDElements.ordered_functions.push_back(HUDElements.time); + if (string == "gpu_stats") + HUDElements.ordered_functions.push_back(HUDElements.gpu_stats); + if (string == "cpu_stats") + HUDElements.ordered_functions.push_back(HUDElements.cpu_stats); + if (string == "core_load") + HUDElements.ordered_functions.push_back(HUDElements.core_load); + if (string == "io_stats") + HUDElements.ordered_functions.push_back(HUDElements.io_stats); + if (string == "vram") + HUDElements.ordered_functions.push_back(HUDElements.vram); + if (string == "ram") + HUDElements.ordered_functions.push_back(HUDElements.ram); + if (string == "fps") + HUDElements.ordered_functions.push_back(HUDElements.fps); + if (string == "engine_version") + HUDElements.ordered_functions.push_back(HUDElements.engine_version); + if (string == "gpu_name") + HUDElements.ordered_functions.push_back(HUDElements.gpu_name); + if (string == "vulkan_driver") + HUDElements.ordered_functions.push_back(HUDElements.vulkan_driver); + if (string == "arch") + HUDElements.ordered_functions.push_back(HUDElements.arch); + if (string == "wine") + HUDElements.ordered_functions.push_back(HUDElements.wine); + if (string == "frame_timing") + HUDElements.ordered_functions.push_back(HUDElements.frame_timing); +} HudElements HUDElements; \ No newline at end of file diff --git a/src/hud_elements.h b/src/hud_elements.h index 865715d9..73d33de4 100644 --- a/src/hud_elements.h +++ b/src/hud_elements.h @@ -1,9 +1,33 @@ #pragma once #include "overlay.h" #include "overlay_params.h" +#include + class HudElements{ public: + struct swapchain_stats *sw_stats; + struct overlay_params *params; + float ralign_width; + float old_scale; + bool is_vulkan; std::vector options; + std::vector ordered_functions; + void sort_elements(std::string string); + static void version(); + static void time(); + static void gpu_stats(); + static void cpu_stats(); + static void core_load(); + static void io_stats(); + static void vram(); + static void ram(); + static void fps(); + static void engine_version(); + static void gpu_name(); + static void vulkan_driver(); + static void arch(); + static void wine(); + static void frame_timing(); }; extern HudElements HUDElements; \ No newline at end of file diff --git a/src/overlay.h b/src/overlay.h index 2f3b7d76..04226c27 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -9,7 +9,13 @@ #include "overlay_params.h" #include "iostats.h" #include "timing.hpp" - +#include "hud_elements.h" +#include "version.h" +#include "gpu.h" +#ifdef HAVE_DBUS +#include "dbus_info.h" +extern float g_overflow; +#endif struct frame_stat { uint64_t stats[OVERLAY_PLOTS_MAX]; }; @@ -94,6 +100,7 @@ extern int32_t deviceID; extern struct benchmark_stats benchmark; extern ImVec2 real_font_size; +extern std::string wineVersion; void position_layer(struct swapchain_stats& data, struct overlay_params& params, ImVec2 window_size); void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan); @@ -108,5 +115,7 @@ void get_device_name(int32_t vendorID, int32_t deviceID, struct swapchain_stats& void calculate_benchmark_data(void *params_void); void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& text_font); void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overlay_params& params); - +void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...); +ImVec4 change_on_load_temp (struct LOAD_DATA& data, int current); +float get_time_stat(void *_data, int _idx); #endif //MANGOHUD_OVERLAY_H diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 1dd95bd5..abdea58f 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -20,6 +20,7 @@ #include "overlay.h" #include "config.h" #include "string_utils.h" +#include "hud_elements.h" #include "mesa/util/os_socket.h" @@ -491,6 +492,7 @@ parse_overlay_config(struct overlay_params *params, params->enabled[OVERLAY_PARAM_ENABLED_read_cfg] = false; params->enabled[OVERLAY_PARAM_ENABLED_io_read] = false; params->enabled[OVERLAY_PARAM_ENABLED_io_write] = false; + params->enabled[OVERLAY_PARAM_ENABLED_io_stats] = false; params->enabled[OVERLAY_PARAM_ENABLED_wine] = false; params->enabled[OVERLAY_PARAM_ENABLED_gpu_load_change] = false; params->enabled[OVERLAY_PARAM_ENABLED_cpu_load_change] = false; @@ -668,4 +670,7 @@ parse_overlay_config(struct overlay_params *params, printf("MANGOHUD: output_file is Deprecated, use output_folder instead\n"); auto real_size = params->font_size * params->font_scale; real_font_size = ImVec2(real_size, real_size / 2); + HUDElements.ordered_functions.clear(); + for (auto& option : HUDElements.options) + HUDElements.sort_elements(option); } diff --git a/src/overlay_params.h b/src/overlay_params.h index 658e0da4..6f68b543 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -39,6 +39,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_BOOL(read_cfg) \ OVERLAY_PARAM_BOOL(io_read) \ OVERLAY_PARAM_BOOL(io_write) \ + OVERLAY_PARAM_BOOL(io_stats) \ OVERLAY_PARAM_BOOL(gpu_mem_clock) \ OVERLAY_PARAM_BOOL(gpu_core_clock) \ OVERLAY_PARAM_BOOL(gpu_power) \ @@ -159,7 +160,7 @@ struct overlay_params { bool help; bool no_display; bool full; - bool io_read, io_write; + bool io_read, io_write, io_stats; unsigned width; unsigned height; int offset_x, offset_y; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 89fb6302..1038ee3a 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -61,12 +61,10 @@ #include "memory.h" #include "notify.h" #include "blacklist.h" -#include "version.h" #include "pci_ids.h" #include "timing.hpp" #ifdef HAVE_DBUS -#include "dbus_info.h" float g_overflow = 50.f /* 3333ms * 0.5 / 16.6667 / 2 (to edge and back) */; #endif @@ -689,7 +687,7 @@ static void snapshot_swapchain_frame(struct swapchain_data *data) // } } -static float get_time_stat(void *_data, int _idx) +float get_time_stat(void *_data, int _idx) { struct swapchain_stats *data = (struct swapchain_stats *) _data; if ((ARRAY_SIZE(data->frames_stats) - _idx) > data->n_frames) @@ -740,7 +738,7 @@ void position_layer(struct swapchain_stats& data, struct overlay_params& params, } } -static void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...) +void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...) { ImVec2 pos = ImGui::GetCursorPos(); char buffer[32] {}; @@ -777,7 +775,7 @@ float get_ticker_limited_pos(float pos, float tw, float& left_limit, float& righ } #ifdef HAVE_DBUS -static void render_mpris_metadata(struct overlay_params& params, mutexed_metadata& meta, uint64_t frame_timing, bool is_main) +void render_mpris_metadata(struct overlay_params& params, mutexed_metadata& meta, uint64_t frame_timing, bool is_main) { if (meta.meta.valid) { auto color = ImGui::ColorConvertU32ToFloat4(params.media_player_color); @@ -937,6 +935,8 @@ ImVec4 change_on_load_temp (struct LOAD_DATA& data, int current) { void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan) { + HUDElements.sw_stats = &data; HUDElements.params = ¶ms; + HUDElements.is_vulkan = is_vulkan; ImGui::GetIO().FontGlobalScale = params.font_scale; if(not logger) logger = std::make_unique(¶ms); uint32_t f_idx = (data.n_frames - 1) % ARRAY_SIZE(data.frames_stats); @@ -947,308 +947,16 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& auto now = Clock::now(); if (old_scale != params.font_scale) { - ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; + HUDElements.ralign_width = ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; old_scale = params.font_scale; } if (!params.no_display){ ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); ImGui::BeginTable("hud", params.tableCols, ImGuiTableFlags_NoClipX); - if (params.enabled[OVERLAY_PARAM_ENABLED_version]){ - ImGui::TableNextCell(); - ImGui::Text("%s", MANGOHUD_VERSION); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_time]){ - ImGui::TableNextRow(); - ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.00f), "%s", data.time.c_str()); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats]){ - ImGui::TableNextRow(); - const char* gpu_text; - if (params.gpu_text.empty()) - gpu_text = "GPU"; - else - gpu_text = params.gpu_text.c_str(); - ImGui::TextColored(data.colors.gpu, "%s", gpu_text); - ImGui::TableNextCell(); - auto text_color = data.colors.text; - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){ - struct LOAD_DATA gpu_data = {data.colors.gpu_load_high, - data.colors.gpu_load_med, - data.colors.gpu_load_low, - params.gpu_load_value[0], - params.gpu_load_value[1] - }; - - - auto load_color = change_on_load_temp(gpu_data, gpu_info.load); - right_aligned_text(load_color, ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(load_color,"%%"); - } - else { - right_aligned_text(text_color, ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(text_color,"%%"); - // ImGui::SameLine(150); - // ImGui::Text("%s", "%"); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_temp]){ - ImGui::TableNextCell(); - right_aligned_text(text_color, ralign_width, "%i", gpu_info.temp); - ImGui::SameLine(0, 1.0f); - ImGui::Text("°C"); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock] || params.enabled[OVERLAY_PARAM_ENABLED_gpu_power]) - ImGui::TableNextRow(); - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock]){ - ImGui::TableNextCell(); - right_aligned_text(text_color, ralign_width, "%i", gpu_info.CoreClock); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("MHz"); - ImGui::PopFont(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_power]) { - ImGui::TableNextCell(); - right_aligned_text(text_color, ralign_width, "%i", gpu_info.powerUsage); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("W"); - ImGui::PopFont(); - } - } - if(params.enabled[OVERLAY_PARAM_ENABLED_cpu_stats]){ - ImGui::TableNextRow(); - const char* cpu_text; - if (params.cpu_text.empty()) - cpu_text = "CPU"; - else - cpu_text = params.cpu_text.c_str(); - ImGui::TextColored(data.colors.cpu, "%s", cpu_text); - ImGui::TableNextCell(); - auto text_color = data.colors.text; - if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_load_change]){ - int cpu_load_percent = int(cpuStats.GetCPUDataTotal().percent); - struct LOAD_DATA cpu_data = {data.colors.cpu_load_high, - data.colors.cpu_load_med, - data.colors.cpu_load_low, - params.cpu_load_value[0], - params.cpu_load_value[1] - }; - - - auto load_color = change_on_load_temp(cpu_data, cpu_load_percent); - right_aligned_text(load_color, ralign_width, "%d", cpu_load_percent); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(load_color, "%%"); - } - else { - right_aligned_text(text_color, ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); - ImGui::SameLine(0, 1.0f); - ImGui::Text("%%"); - } - // ImGui::SameLine(150); - // ImGui::Text("%s", "%"); - - if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_temp]){ - ImGui::TableNextCell(); - right_aligned_text(data.colors.text, ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); - ImGui::SameLine(0, 1.0f); - ImGui::Text("°C"); - } - } - - if (params.enabled[OVERLAY_PARAM_ENABLED_core_load]){ - int i = 0; - for (const CPUData &cpuData : cpuStats.GetCPUData()) - { - ImGui::TableNextRow(); - ImGui::TextColored(data.colors.cpu, "CPU"); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::TextColored(data.colors.cpu,"%i", i); - ImGui::PopFont(); - ImGui::TableNextCell(); - right_aligned_text(data.colors.text, ralign_width, "%i", int(cpuData.percent)); - ImGui::SameLine(0, 1.0f); - ImGui::Text("%%"); - ImGui::TableNextCell(); - right_aligned_text(data.colors.text, ralign_width, "%i", cpuData.mhz); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("MHz"); - ImGui::PopFont(); - i++; - } - } - if (params.enabled[OVERLAY_PARAM_ENABLED_io_read] || params.enabled[OVERLAY_PARAM_ENABLED_io_write]){ - auto sampling = params.fps_sampling_period; - ImGui::TableNextRow(); - if (params.enabled[OVERLAY_PARAM_ENABLED_io_read] && !params.enabled[OVERLAY_PARAM_ENABLED_io_write]) - ImGui::TextColored(data.colors.io, "IO RD"); - else if (params.enabled[OVERLAY_PARAM_ENABLED_io_read] && params.enabled[OVERLAY_PARAM_ENABLED_io_write]) - ImGui::TextColored(data.colors.io, "IO RW"); - else if (params.enabled[OVERLAY_PARAM_ENABLED_io_write] && !params.enabled[OVERLAY_PARAM_ENABLED_io_read]) - ImGui::TextColored(data.colors.io, "IO WR"); - - if (params.enabled[OVERLAY_PARAM_ENABLED_io_read]){ - ImGui::TableNextCell(); - float val = data.io.diff.read * 1000000 / sampling; - right_aligned_text(data.colors.text, ralign_width, val < 100 ? "%.1f" : "%.f", val); - ImGui::SameLine(0,1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("MiB/s"); - ImGui::PopFont(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_io_write]){ - ImGui::TableNextCell(); - float val = data.io.diff.write * 1000000 / sampling; - right_aligned_text(data.colors.text, ralign_width, val < 100 ? "%.1f" : "%.f", val); - ImGui::SameLine(0,1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("MiB/s"); - ImGui::PopFont(); - } - } - if (params.enabled[OVERLAY_PARAM_ENABLED_vram]){ - ImGui::TableNextRow(); - ImGui::TextColored(data.colors.vram, "VRAM"); - ImGui::TableNextCell(); - right_aligned_text(data.colors.text, ralign_width, "%.1f", gpu_info.memoryUsed); - ImGui::SameLine(0,1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("GiB"); - ImGui::PopFont(); - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_mem_clock]){ - ImGui::TableNextCell(); - right_aligned_text(data.colors.text, ralign_width, "%i", gpu_info.MemClock); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("MHz"); - ImGui::PopFont(); - } - } -#ifdef __gnu_linux__ - if (params.enabled[OVERLAY_PARAM_ENABLED_ram]){ - ImGui::TableNextRow(); - ImGui::TextColored(data.colors.ram, "RAM"); - ImGui::TableNextCell(); - right_aligned_text(data.colors.text, ralign_width, "%.1f", memused); - ImGui::SameLine(0,1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("GiB"); - ImGui::PopFont(); - } -#endif - if (params.enabled[OVERLAY_PARAM_ENABLED_fps]){ - ImGui::TableNextRow(); - ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); - ImGui::TableNextCell(); - right_aligned_text(data.colors.text, ralign_width, "%.0f", data.fps); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("FPS"); - ImGui::PopFont(); - ImGui::TableNextCell(); - right_aligned_text(data.colors.text, ralign_width, "%.1f", 1000 / data.fps); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("ms"); - ImGui::PopFont(); - } - if (!params.enabled[OVERLAY_PARAM_ENABLED_fps] && params.enabled[OVERLAY_PARAM_ENABLED_engine_version]){ - ImGui::TableNextRow(); - ImGui::TextColored(data.colors.engine, "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); - } + for (auto& func : HUDElements.ordered_functions) + func(); ImGui::EndTable(); - if (params.enabled[OVERLAY_PARAM_ENABLED_engine_version]){ - ImGui::PushFont(data.font1); - ImGui::Dummy(ImVec2(0, 8.0f)); - if (is_vulkan) { - if ((data.engineName == "DXVK" || data.engineName == "VKD3D")){ - ImGui::TextColored(data.colors.engine, - "%s/%d.%d.%d", data.engineVersion.c_str(), - data.version_vk.major, - data.version_vk.minor, - data.version_vk.patch); - } else { - ImGui::TextColored(data.colors.engine, - "%d.%d.%d", - data.version_vk.major, - data.version_vk.minor, - data.version_vk.patch); - } - } else { - ImGui::TextColored(data.colors.engine, - "%d.%d%s", data.version_gl.major, data.version_gl.minor, - data.version_gl.is_gles ? " ES" : ""); - } - // ImGui::SameLine(); - ImGui::PopFont(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_name] && !data.gpuName.empty()){ - ImGui::PushFont(data.font1); - ImGui::Dummy(ImVec2(0.0,5.0f)); - ImGui::TextColored(data.colors.engine, - "%s", data.gpuName.c_str()); - ImGui::PopFont(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_vulkan_driver] && !data.driverName.empty()){ - ImGui::PushFont(data.font1); - ImGui::Dummy(ImVec2(0.0,5.0f)); - ImGui::TextColored(data.colors.engine, - "%s", data.driverName.c_str()); - ImGui::PopFont(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_arch]){ - ImGui::PushFont(data.font1); - ImGui::Dummy(ImVec2(0.0,5.0f)); - ImGui::TextColored(data.colors.engine, "%s", "" MANGOHUD_ARCH); - ImGui::PopFont(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_wine]){ - if (!wineVersion.empty()){ - //ImGui::TextColored(data.colors.wine, "%s", "WINE"); - ImGui::PushFont(data.font1); - ImGui::Dummy(ImVec2(0.0,5.0f)); - ImGui::TextColored(data.colors.wine, "%s", wineVersion.c_str()); - ImGui::PopFont(); - } - } - if (params.enabled[OVERLAY_PARAM_ENABLED_frame_timing]){ - ImGui::Dummy(ImVec2(0.0f, real_font_size.y)); - ImGui::PushFont(data.font1); - ImGui::TextColored(data.colors.engine, "%s", "Frametime"); - ImGui::PopFont(); - - char hash[40]; - snprintf(hash, sizeof(hash), "##%s", overlay_param_names[OVERLAY_PARAM_ENABLED_frame_timing]); - data.stat_selector = OVERLAY_PLOTS_frame_timing; - data.time_dividor = 1000.0f; - - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); - double min_time = 0.0f; - double max_time = 50.0f; - if (params.enabled[OVERLAY_PARAM_ENABLED_histogram]){ - ImGui::PlotHistogram(hash, get_time_stat, &data, - ARRAY_SIZE(data.frames_stats), 0, - NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth() - real_font_size.x * 2.2, 50)); - } else { - ImGui::PlotLines(hash, get_time_stat, &data, - ARRAY_SIZE(data.frames_stats), 0, - NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth() - real_font_size.x * 2.2, 50)); - } - ImGui::PopStyleColor(); - } - if (params.enabled[OVERLAY_PARAM_ENABLED_frame_timing]){ - ImGui::SameLine(0,1.0f); - ImGui::PushFont(data.font1); - ImGui::Text("%.1f ms", 1000 / data.fps); //frame_timing / 1000.f); - ImGui::PopFont(); - } #ifdef HAVE_DBUS ImFont scaled_font = *data.font_text; From ee7f7058c2c9171d6d16f9c1c26d1404b090421d Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Tue, 3 Nov 2020 21:46:18 +0100 Subject: [PATCH 083/130] No need to use HudElements object in sort_elements --- src/hud_elements.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index e01a127b..6bb3b647 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -346,35 +346,35 @@ void HudElements::frame_timing(){ void HudElements::sort_elements(std::string string){ if (string == "version") - HUDElements.ordered_functions.push_back(HUDElements.version); + ordered_functions.push_back(&version); if (string == "time") - HUDElements.ordered_functions.push_back(HUDElements.time); + ordered_functions.push_back(time); if (string == "gpu_stats") - HUDElements.ordered_functions.push_back(HUDElements.gpu_stats); + ordered_functions.push_back(gpu_stats); if (string == "cpu_stats") - HUDElements.ordered_functions.push_back(HUDElements.cpu_stats); + ordered_functions.push_back(cpu_stats); if (string == "core_load") - HUDElements.ordered_functions.push_back(HUDElements.core_load); + ordered_functions.push_back(core_load); if (string == "io_stats") - HUDElements.ordered_functions.push_back(HUDElements.io_stats); + ordered_functions.push_back(io_stats); if (string == "vram") - HUDElements.ordered_functions.push_back(HUDElements.vram); + ordered_functions.push_back(vram); if (string == "ram") - HUDElements.ordered_functions.push_back(HUDElements.ram); + ordered_functions.push_back(ram); if (string == "fps") - HUDElements.ordered_functions.push_back(HUDElements.fps); + ordered_functions.push_back(fps); if (string == "engine_version") - HUDElements.ordered_functions.push_back(HUDElements.engine_version); + ordered_functions.push_back(engine_version); if (string == "gpu_name") - HUDElements.ordered_functions.push_back(HUDElements.gpu_name); + ordered_functions.push_back(gpu_name); if (string == "vulkan_driver") - HUDElements.ordered_functions.push_back(HUDElements.vulkan_driver); + ordered_functions.push_back(vulkan_driver); if (string == "arch") - HUDElements.ordered_functions.push_back(HUDElements.arch); + ordered_functions.push_back(arch); if (string == "wine") - HUDElements.ordered_functions.push_back(HUDElements.wine); + ordered_functions.push_back(wine); if (string == "frame_timing") - HUDElements.ordered_functions.push_back(HUDElements.frame_timing); + ordered_functions.push_back(frame_timing); } HudElements HUDElements; \ No newline at end of file From dbfbd05ecf3f10c6d9c9a6222a98f83ca07ea6a1 Mon Sep 17 00:00:00 2001 From: jackun Date: Tue, 3 Nov 2020 22:58:40 +0200 Subject: [PATCH 084/130] Add `media_player` to HudElements --- src/hud_elements.cpp | 20 +++++++++++++++++++- src/hud_elements.h | 3 ++- src/overlay.h | 5 +++++ src/vulkan.cpp | 14 -------------- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 6bb3b647..b1583552 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -344,6 +344,22 @@ void HudElements::frame_timing(){ } } +void HudElements::media_player(){ +#ifdef HAVE_DBUS + ImGui::TableNextRow(); + uint32_t f_idx = (HUDElements.sw_stats->n_frames - 1) % ARRAY_SIZE(HUDElements.sw_stats->frames_stats); + uint64_t frame_timing = HUDElements.sw_stats->frames_stats[f_idx].stats[OVERLAY_PLOTS_frame_timing]; + ImFont scaled_font = *HUDElements.sw_stats->font_text; + scaled_font.Scale = HUDElements.params->font_scale_media_player; + ImGui::PushFont(&scaled_font); + { + std::lock_guard lck(main_metadata.mtx); + render_mpris_metadata(*HUDElements.params, main_metadata, frame_timing, true); + } + ImGui::PopFont(); +#endif +} + void HudElements::sort_elements(std::string string){ if (string == "version") ordered_functions.push_back(&version); @@ -375,6 +391,8 @@ void HudElements::sort_elements(std::string string){ ordered_functions.push_back(wine); if (string == "frame_timing") ordered_functions.push_back(frame_timing); + if (string == "media_player") + ordered_functions.push_back(media_player); } -HudElements HUDElements; \ No newline at end of file +HudElements HUDElements; diff --git a/src/hud_elements.h b/src/hud_elements.h index 73d33de4..b4a5fd94 100644 --- a/src/hud_elements.h +++ b/src/hud_elements.h @@ -28,6 +28,7 @@ class HudElements{ static void arch(); static void wine(); static void frame_timing(); + static void media_player(); }; -extern HudElements HUDElements; \ No newline at end of file +extern HudElements HUDElements; diff --git a/src/overlay.h b/src/overlay.h index 04226c27..0973a8fa 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -118,4 +118,9 @@ void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overl void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...); ImVec4 change_on_load_temp (struct LOAD_DATA& data, int current); float get_time_stat(void *_data, int _idx); + +#ifdef HAVE_DBUS +void render_mpris_metadata(struct overlay_params& params, mutexed_metadata& meta, uint64_t frame_timing, bool is_main); +#endif + #endif //MANGOHUD_OVERLAY_H diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 1038ee3a..52a00fb2 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -939,8 +939,6 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& HUDElements.is_vulkan = is_vulkan; ImGui::GetIO().FontGlobalScale = params.font_scale; if(not logger) logger = std::make_unique(¶ms); - uint32_t f_idx = (data.n_frames - 1) % ARRAY_SIZE(data.frames_stats); - uint64_t frame_timing = data.frames_stats[f_idx].stats[OVERLAY_PLOTS_frame_timing]; static float ralign_width = 0, old_scale = 0; window_size = ImVec2(params.width, params.height); unsigned height = ImGui::GetIO().DisplaySize.y; @@ -958,18 +956,6 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& func(); ImGui::EndTable(); -#ifdef HAVE_DBUS - ImFont scaled_font = *data.font_text; - scaled_font.Scale = params.font_scale_media_player; - ImGui::PushFont(&scaled_font); - { - std::lock_guard lck(main_metadata.mtx); - render_mpris_metadata(params, main_metadata, frame_timing, true); - } - //render_mpris_metadata(params, generic_mpris, frame_timing, false); - ImGui::PopFont(); -#endif - if(logger->is_active()) 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); From 6e7747c73ce39bdf9266347e8a8e67218f17e12f Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Tue, 3 Nov 2020 22:28:48 +0100 Subject: [PATCH 085/130] Add sorting for env var --- src/hud_elements.cpp | 2 +- src/overlay_params.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index b1583552..efcd3c8d 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -362,7 +362,7 @@ void HudElements::media_player(){ void HudElements::sort_elements(std::string string){ if (string == "version") - ordered_functions.push_back(&version); + ordered_functions.push_back(version); if (string == "time") ordered_functions.push_back(time); if (string == "gpu_stats") diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index abdea58f..ca69ad30 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -441,6 +441,7 @@ parse_overlay_env(struct overlay_params *params, char key[256], value[256]; while ((num = parse_string(env, key, value)) != 0) { env += num; + HUDElements.sort_elements(key); if (!strcmp("full", key)) { bool read_cfg = params->enabled[OVERLAY_PARAM_ENABLED_read_cfg]; #define OVERLAY_PARAM_BOOL(name) \ @@ -559,7 +560,7 @@ parse_overlay_config(struct overlay_params *params, #define parse_reload_cfg(x) params->reload_cfg #endif - + HUDElements.ordered_functions.clear(); // first pass with env var if (env) parse_overlay_env(params, env); @@ -600,8 +601,8 @@ parse_overlay_config(struct overlay_params *params, } // second pass, override config file settings with MANGOHUD_CONFIG - if (env && read_cfg) - parse_overlay_env(params, env); + // if (env && read_cfg) + // parse_overlay_env(params, env); if (params->font_scale_media_player <= 0.f) params->font_scale_media_player = 0.55f; @@ -670,7 +671,6 @@ parse_overlay_config(struct overlay_params *params, printf("MANGOHUD: output_file is Deprecated, use output_folder instead\n"); auto real_size = params->font_size * params->font_scale; real_font_size = ImVec2(real_size, real_size / 2); - HUDElements.ordered_functions.clear(); for (auto& option : HUDElements.options) HUDElements.sort_elements(option); } From cc3892499780290cbbfb935cb4cca7032ff92862 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sat, 7 Nov 2020 00:01:23 +0100 Subject: [PATCH 086/130] Added graphs --- src/config.cpp | 2 +- src/hud_elements.cpp | 229 +++++++++++++++++++++++++++++------------ src/hud_elements.h | 11 +- src/overlay.cpp | 9 +- src/overlay.h | 2 + src/overlay_params.cpp | 2 +- src/overlay_params.h | 8 +- src/vulkan.cpp | 7 +- 8 files changed, 188 insertions(+), 82 deletions(-) diff --git a/src/config.cpp b/src/config.cpp index a5cfe3fd..ebfc2ffd 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -25,7 +25,7 @@ void parseConfigLine(std::string line, std::unordered_mapcolors.text; if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_load_change]){ - int cpu_load_percent = int(cpuStats.GetCPUDataTotal().percent); - struct LOAD_DATA cpu_data = {HUDElements.sw_stats->colors.cpu_load_high, - HUDElements.sw_stats->colors.cpu_load_med, - HUDElements.sw_stats->colors.cpu_load_low, - HUDElements.params->cpu_load_value[0], - HUDElements.params->cpu_load_value[1] - }; + int cpu_load_percent = int(cpuStats.GetCPUDataTotal().percent); + struct LOAD_DATA cpu_data = {HUDElements.sw_stats->colors.cpu_load_high, + HUDElements.sw_stats->colors.cpu_load_med, + HUDElements.sw_stats->colors.cpu_load_low, + HUDElements.params->cpu_load_value[0], + HUDElements.params->cpu_load_value[1] + }; - auto load_color = change_on_load_temp(cpu_data, cpu_load_percent); - right_aligned_text(load_color, HUDElements.ralign_width, "%d", cpu_load_percent); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(load_color, "%%"); + auto load_color = change_on_load_temp(cpu_data, cpu_load_percent); + right_aligned_text(load_color, HUDElements.ralign_width, "%d", cpu_load_percent); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(load_color, "%%"); } else { - right_aligned_text(text_color, HUDElements.ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); - ImGui::SameLine(0, 1.0f); - ImGui::Text("%%"); + right_aligned_text(text_color, HUDElements.ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent)); + ImGui::SameLine(0, 1.0f); + ImGui::Text("%%"); } if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_temp]){ - ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); - ImGui::SameLine(0, 1.0f); - ImGui::Text("°C"); + ImGui::TableNextCell(); + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); + ImGui::SameLine(0, 1.0f); + ImGui::Text("°C"); } } } @@ -360,39 +343,149 @@ void HudElements::media_player(){ #endif } -void HudElements::sort_elements(std::string string){ - if (string == "version") - ordered_functions.push_back(version); - if (string == "time") - ordered_functions.push_back(time); - if (string == "gpu_stats") - ordered_functions.push_back(gpu_stats); - if (string == "cpu_stats") - ordered_functions.push_back(cpu_stats); - if (string == "core_load") - ordered_functions.push_back(core_load); - if (string == "io_stats") - ordered_functions.push_back(io_stats); - if (string == "vram") - ordered_functions.push_back(vram); - if (string == "ram") - ordered_functions.push_back(ram); - if (string == "fps") - ordered_functions.push_back(fps); - if (string == "engine_version") - ordered_functions.push_back(engine_version); - if (string == "gpu_name") - ordered_functions.push_back(gpu_name); - if (string == "vulkan_driver") - ordered_functions.push_back(vulkan_driver); - if (string == "arch") - ordered_functions.push_back(arch); - if (string == "wine") - ordered_functions.push_back(wine); - if (string == "frame_timing") - ordered_functions.push_back(frame_timing); - if (string == "media_player") - ordered_functions.push_back(media_player); +void HudElements::graphs(){ + + ImGui::Dummy(ImVec2(0.0f, real_font_size.y)); + std::string value = HUDElements.ordered_functions[HUDElements.place].second; + std::vector arr; + + for (size_t i = 0; i < 50; i++) + { + arr.push_back(0); + } + if (value == "cpu_load"){ + for (auto& it : graph_data){ + arr.push_back(float(it.cpu_load)); + arr.erase(arr.begin()); + } + HUDElements.max = 100; HUDElements.min = 0; + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "CPU Load"); + ImGui::PopFont(); + } + + if (value == "gpu_load"){ + for (auto& it : graph_data){ + arr.push_back(float(it.gpu_load)); + arr.erase(arr.begin()); + } + HUDElements.max = 100; HUDElements.min = 0; + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "GPU Load"); + ImGui::PopFont(); + } + + if (value == "gpu_core_clock"){ + for (auto& it : graph_data){ + arr.push_back(float(it.gpu_core_clock)); + arr.erase(arr.begin()); + } + if (int(arr.back()) > HUDElements.gpu_core_max) + HUDElements.gpu_core_max = arr.back(); + HUDElements.max = HUDElements.gpu_core_max; + HUDElements.min = 0; + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "GPU Core Clock"); + ImGui::PopFont(); + } + + if (value == "gpu_mem_clock"){ + for (auto& it : graph_data){ + arr.push_back(float(it.gpu_mem_clock)); + arr.erase(arr.begin()); + } + if (int(arr.back()) > HUDElements.gpu_mem_max) + HUDElements.gpu_mem_max = arr.back(); + HUDElements.max = HUDElements.gpu_mem_max; + HUDElements.min = 0; + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "GPU Mem Clock"); + ImGui::PopFont(); + } + + if (value == "vram"){ + for (auto& it : graph_data){ + arr.push_back(float(it.gpu_vram_used)); + arr.erase(arr.begin()); + } + HUDElements.max = gpu_info.memoryTotal; + HUDElements.min = 0; + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "VRAM"); + ImGui::PopFont(); + } + + if (value == "ram"){ + if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_ram]) + HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_ram] = true; + for (auto& it : graph_data){ + arr.push_back(float(it.ram_used)); + arr.erase(arr.begin()); + } + HUDElements.max = memmax; + HUDElements.min = 0; + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "RAM"); + ImGui::PopFont(); + } + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); + ImGui::TableNextRow(); + ImGui::PlotLines("", arr.data(), + arr.size(), 0, + NULL, HUDElements.min, HUDElements.max, + ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); + ImGui::PopStyleColor(1); +} + +void HudElements::sort_elements(std::pair option){ + auto param = option.first; + auto value = option.second; + + if (param == "version") + ordered_functions.push_back({version, value}); + if (param == "time") + ordered_functions.push_back({time, value}); + if (param == "gpu_stats") + ordered_functions.push_back({gpu_stats, value}); + if (param == "cpu_stats") + ordered_functions.push_back({cpu_stats, value}); + if (param == "core_load") + ordered_functions.push_back({core_load, value}); + if (param == "io_stats") + ordered_functions.push_back({io_stats, value}); + if (param == "vram") + ordered_functions.push_back({vram, value}); + if (param == "ram") + ordered_functions.push_back({ram, value}); + if (param == "fps") + ordered_functions.push_back({fps, value}); + if (param == "engine_version") + ordered_functions.push_back({engine_version, value}); + if (param == "gpu_name") + ordered_functions.push_back({gpu_name, value}); + if (param == "vulkan_driver") + ordered_functions.push_back({vulkan_driver, value}); + if (param == "arch") + ordered_functions.push_back({arch, value}); + if (param == "wine") + ordered_functions.push_back({wine, value}); + if (param == "frame_timing") + ordered_functions.push_back({frame_timing, value}); + if (param == "media_player") + ordered_functions.push_back({media_player, value}); + if (param == "graphs"){ + std::vector permitted_params = { + "gpu_load", "cpu_load", "gpu_core_clock", "gpu_mem_clock", + "vram", "ram" + }; + std::stringstream ss; ss << value; + while (std::getline(ss, value, '+')) { + if (std::find(permitted_params.begin(), permitted_params.end(), value) != permitted_params.end()) + ordered_functions.push_back({graphs, value}); + else + printf("MANGOHUD: Unrecognized graph type: %s\n", value.c_str()); + } + } } HudElements HUDElements; diff --git a/src/hud_elements.h b/src/hud_elements.h index b4a5fd94..2f3022c2 100644 --- a/src/hud_elements.h +++ b/src/hud_elements.h @@ -2,6 +2,8 @@ #include "overlay.h" #include "overlay_params.h" #include +#include +#include class HudElements{ public: @@ -10,9 +12,11 @@ class HudElements{ float ralign_width; float old_scale; bool is_vulkan; - std::vector options; - std::vector ordered_functions; - void sort_elements(std::string string); + int place; + std::vector> options; + std::vector> ordered_functions; + int min, max, gpu_core_max, gpu_mem_max; + void sort_elements(std::pair option); static void version(); static void time(); static void gpu_stats(); @@ -29,6 +33,7 @@ class HudElements{ static void wine(); static void frame_timing(); static void media_player(); + static void graphs(); }; extern HudElements HUDElements; diff --git a/src/overlay.cpp b/src/overlay.cpp index 68d676f9..6569478c 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -14,6 +14,7 @@ struct benchmark_stats benchmark; struct fps_limit fps_limit_stats {}; ImVec2 real_font_size; +std::vector graph_data; void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& params, uint32_t vendorID) { @@ -55,7 +56,11 @@ void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& par currentLogData.cpu_load = cpuStats.GetCPUDataTotal().percent; currentLogData.cpu_temp = cpuStats.GetCPUDataTotal().temp; - + // Save data for graphs + if (graph_data.size() > 50) + graph_data.erase(graph_data.begin()); + graph_data.push_back({0, 0, cpuStats.GetCPUDataTotal().percent, gpu_info.load, cpuStats.GetCPUDataTotal().temp, + gpu_info.temp, gpu_info.CoreClock, gpu_info.MemClock, gpu_info.memoryUsed, memused}); logger->notify_data_valid(); } @@ -63,7 +68,6 @@ void update_hud_info(struct swapchain_stats& sw_stats, struct overlay_params& pa if(not logger) logger = std::make_unique(¶ms); uint32_t f_idx = sw_stats.n_frames % ARRAY_SIZE(sw_stats.frames_stats); uint64_t now = os_time_get(); /* us */ - double elapsed = (double)(now - sw_stats.last_fps_update); /* us */ fps = 1000000.0f * sw_stats.n_frames_since_update / elapsed; if (logger->is_active()) @@ -76,7 +80,6 @@ void update_hud_info(struct swapchain_stats& sw_stats, struct overlay_params& pa frametime = now - sw_stats.last_present_time; if (elapsed >= params.fps_sampling_period) { - std::thread(update_hw_info, std::ref(sw_stats), std::ref(params), vendorID).detach(); sw_stats.fps = fps; diff --git a/src/overlay.h b/src/overlay.h index 0973a8fa..b3b5360f 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -12,6 +12,7 @@ #include "hud_elements.h" #include "version.h" #include "gpu.h" +#include "logging.h" #ifdef HAVE_DBUS #include "dbus_info.h" extern float g_overflow; @@ -101,6 +102,7 @@ extern int32_t deviceID; extern struct benchmark_stats benchmark; extern ImVec2 real_font_size; extern std::string wineVersion; +extern std::vector graph_data; void position_layer(struct swapchain_stats& data, struct overlay_params& params, ImVec2 window_size); void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan); diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index ca69ad30..2c573992 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -441,7 +441,7 @@ parse_overlay_env(struct overlay_params *params, char key[256], value[256]; while ((num = parse_string(env, key, value)) != 0) { env += num; - HUDElements.sort_elements(key); + HUDElements.sort_elements({key, value}); if (!strcmp("full", key)) { bool read_cfg = params->enabled[OVERLAY_PARAM_ENABLED_read_cfg]; #define OVERLAY_PARAM_BOOL(name) \ diff --git a/src/overlay_params.h b/src/overlay_params.h index 6f68b543..68d97483 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -53,6 +53,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_BOOL(wine) \ OVERLAY_PARAM_BOOL(gpu_load_change) \ OVERLAY_PARAM_BOOL(cpu_load_change) \ + OVERLAY_PARAM_BOOL(graphs) \ OVERLAY_PARAM_CUSTOM(fps_sampling_period) \ OVERLAY_PARAM_CUSTOM(output_folder) \ OVERLAY_PARAM_CUSTOM(output_file) \ @@ -92,7 +93,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(background_color) \ OVERLAY_PARAM_CUSTOM(io_color) \ OVERLAY_PARAM_CUSTOM(text_color) \ - OVERLAY_PARAM_CUSTOM (wine_color) \ + OVERLAY_PARAM_CUSTOM(wine_color) \ OVERLAY_PARAM_CUSTOM(alpha) \ OVERLAY_PARAM_CUSTOM(log_duration) \ OVERLAY_PARAM_CUSTOM(pci_dev) \ @@ -107,9 +108,8 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(help) \ OVERLAY_PARAM_CUSTOM(gpu_load_value) \ OVERLAY_PARAM_CUSTOM(cpu_load_value) \ - OVERLAY_PARAM_CUSTOM(gpu_load_color) \ - OVERLAY_PARAM_CUSTOM(cpu_load_color) - + OVERLAY_PARAM_CUSTOM(gpu_load_color) \ + OVERLAY_PARAM_CUSTOM(cpu_load_color) \ enum overlay_param_position { LAYER_POSITION_TOP_LEFT, diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 52a00fb2..d1eae394 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -952,8 +952,11 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if (!params.no_display){ ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); ImGui::BeginTable("hud", params.tableCols, ImGuiTableFlags_NoClipX); - for (auto& func : HUDElements.ordered_functions) - func(); + HUDElements.place = 0; + for (auto& func : HUDElements.ordered_functions){ + func.first(); + HUDElements.place += 1; + } ImGui::EndTable(); if(logger->is_active()) From 8ebc56d4f7140308e33bebfed9ca2ae3b109d97f Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sun, 8 Nov 2020 18:25:26 +0100 Subject: [PATCH 087/130] CPU/GPU Temp graphs --- src/hud_elements.cpp | 32 +++++++++++++++++++++++++++++++- src/hud_elements.h | 2 +- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 9f11a05f..0f698498 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -374,6 +374,36 @@ void HudElements::graphs(){ ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "GPU Load"); ImGui::PopFont(); } + + if (value == "cpu_temp"){ + if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_temp]) + HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_temp] = true; + for (auto& it : graph_data){ + arr.push_back(float(it.cpu_temp)); + arr.erase(arr.begin()); + } + if (int(arr.back()) > HUDElements.cpu_temp_max) + HUDElements.cpu_temp_max = arr.back(); + HUDElements.max = HUDElements.cpu_temp_max; + HUDElements.min = 0; + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "CPU Temp"); + ImGui::PopFont(); + } + + if (value == "gpu_temp"){ + for (auto& it : graph_data){ + arr.push_back(float(it.gpu_temp)); + arr.erase(arr.begin()); + } + if (int(arr.back()) > HUDElements.gpu_temp_max) + HUDElements.gpu_temp_max = arr.back(); + HUDElements.max = HUDElements.gpu_temp_max; + HUDElements.min = 0; + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "GPU Temp"); + ImGui::PopFont(); + } if (value == "gpu_core_clock"){ for (auto& it : graph_data){ @@ -476,7 +506,7 @@ void HudElements::sort_elements(std::pair option){ if (param == "graphs"){ std::vector permitted_params = { "gpu_load", "cpu_load", "gpu_core_clock", "gpu_mem_clock", - "vram", "ram" + "vram", "ram", "cpu_temp", "gpu_temp" }; std::stringstream ss; ss << value; while (std::getline(ss, value, '+')) { diff --git a/src/hud_elements.h b/src/hud_elements.h index 2f3022c2..425fc3e3 100644 --- a/src/hud_elements.h +++ b/src/hud_elements.h @@ -15,7 +15,7 @@ class HudElements{ int place; std::vector> options; std::vector> ordered_functions; - int min, max, gpu_core_max, gpu_mem_max; + int min, max, gpu_core_max, gpu_mem_max, cpu_temp_max, gpu_temp_max; void sort_elements(std::pair option); static void version(); static void time(); From 0c57171497566c008e119b1934250a3508b850ed Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Sun, 8 Nov 2020 18:27:22 +0100 Subject: [PATCH 088/130] Make sure gpu_temp is being logged --- src/hud_elements.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 0f698498..336cba99 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -392,6 +392,8 @@ void HudElements::graphs(){ } if (value == "gpu_temp"){ + if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_temp]) + HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_temp] = true; for (auto& it : graph_data){ arr.push_back(float(it.gpu_temp)); arr.erase(arr.begin()); From 366de9a9ddbbb84e07c944773abdad9099dcf64b Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Mon, 9 Nov 2020 01:33:38 +0100 Subject: [PATCH 089/130] Legacy elements --- src/hud_elements.cpp | 96 ++++++++++++++++++++++-------------------- src/hud_elements.h | 5 +++ src/overlay_params.cpp | 10 ++++- src/overlay_params.h | 1 + 4 files changed, 65 insertions(+), 47 deletions(-) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 336cba99..1936092b 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -5,13 +5,17 @@ #include "mesa/util/macros.h" void HudElements::time(){ - ImGui::TableNextRow(); - ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.00f), "%s", HUDElements.sw_stats->time.c_str()); + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_time]){ + ImGui::TableNextRow(); + ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.00f), "%s", HUDElements.sw_stats->time.c_str()); + } } void HudElements::version(){ - ImGui::TableNextRow(); - ImGui::Text("%s", MANGOHUD_VERSION); + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_version]){ + ImGui::TableNextRow(); + ImGui::Text("%s", MANGOHUD_VERSION); + } } void HudElements::gpu_stats(){ @@ -115,6 +119,7 @@ void HudElements::cpu_stats(){ } void HudElements::core_load(){ + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_core_load]){ int i = 0; for (const CPUData &cpuData : cpuStats.GetCPUData()) { @@ -136,6 +141,7 @@ void HudElements::core_load(){ ImGui::PopFont(); i++; } + } } void HudElements::io_stats(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read] || HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]){ @@ -236,8 +242,8 @@ void HudElements::gpu_name(){ } } void HudElements::engine_version(){ - ImGui::TableNextRow(); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_engine_version]){ + ImGui::TableNextRow(); ImGui::PushFont(HUDElements.sw_stats->font1); if (HUDElements.is_vulkan) { if ((HUDElements.sw_stats->engineName == "DXVK" || HUDElements.sw_stats->engineName == "VKD3D")){ @@ -258,7 +264,6 @@ void HudElements::engine_version(){ "%d.%d%s", HUDElements.sw_stats->version_gl.major, HUDElements.sw_stats->version_gl.minor, HUDElements.sw_stats->version_gl.is_gles ? " ES" : ""); } - // ImGui::SameLine(); ImGui::PopFont(); } } @@ -473,51 +478,52 @@ void HudElements::sort_elements(std::pair option){ auto param = option.first; auto value = option.second; - if (param == "version") - ordered_functions.push_back({version, value}); - if (param == "time") - ordered_functions.push_back({time, value}); - if (param == "gpu_stats") - ordered_functions.push_back({gpu_stats, value}); - if (param == "cpu_stats") - ordered_functions.push_back({cpu_stats, value}); - if (param == "core_load") - ordered_functions.push_back({core_load, value}); - if (param == "io_stats") - ordered_functions.push_back({io_stats, value}); - if (param == "vram") - ordered_functions.push_back({vram, value}); - if (param == "ram") - ordered_functions.push_back({ram, value}); - if (param == "fps") - ordered_functions.push_back({fps, value}); - if (param == "engine_version") - ordered_functions.push_back({engine_version, value}); - if (param == "gpu_name") - ordered_functions.push_back({gpu_name, value}); - if (param == "vulkan_driver") - ordered_functions.push_back({vulkan_driver, value}); - if (param == "arch") - ordered_functions.push_back({arch, value}); - if (param == "wine") - ordered_functions.push_back({wine, value}); - if (param == "frame_timing") - ordered_functions.push_back({frame_timing, value}); - if (param == "media_player") - ordered_functions.push_back({media_player, value}); + if (param == "version") { ordered_functions.push_back({version, value}); } + if (param == "time") { ordered_functions.push_back({time, value}); } + if (param == "gpu_stats") { ordered_functions.push_back({gpu_stats, value}); } + if (param == "cpu_stats") { ordered_functions.push_back({cpu_stats, value}); } + if (param == "core_load") { ordered_functions.push_back({core_load, value}); } + if (param == "io_stats") { ordered_functions.push_back({io_stats, value}); } + if (param == "vram") { ordered_functions.push_back({vram, value}); } + if (param == "ram") { ordered_functions.push_back({ram, value}); } + if (param == "fps") { ordered_functions.push_back({fps, value}); } + if (param == "engine_version") { ordered_functions.push_back({engine_version, value}); } + if (param == "gpu_name") { ordered_functions.push_back({gpu_name, value}); } + if (param == "vulkan_driver") { ordered_functions.push_back({vulkan_driver, value}); } + if (param == "arch") { ordered_functions.push_back({arch, value}); } + if (param == "wine") { ordered_functions.push_back({wine, value}); } + if (param == "frame_timing") { ordered_functions.push_back({frame_timing, value}); } + if (param == "media_player") { ordered_functions.push_back({media_player, value}); } if (param == "graphs"){ - std::vector permitted_params = { - "gpu_load", "cpu_load", "gpu_core_clock", "gpu_mem_clock", - "vram", "ram", "cpu_temp", "gpu_temp" - }; - std::stringstream ss; ss << value; - while (std::getline(ss, value, '+')) { - if (std::find(permitted_params.begin(), permitted_params.end(), value) != permitted_params.end()) + stringstream ss; ss << value; + while (getline(ss, value, '+')) { + if (find(permitted_params.begin(), permitted_params.end(), value) != permitted_params.end()) ordered_functions.push_back({graphs, value}); else printf("MANGOHUD: Unrecognized graph type: %s\n", value.c_str()); } } + return; +} + +void HudElements::legacy_elements(){ + string value = "NULL"; + ordered_functions.push_back({time, value}); + ordered_functions.push_back({version, value}); + ordered_functions.push_back({gpu_stats, value}); + ordered_functions.push_back({cpu_stats, value}); + ordered_functions.push_back({core_load, value}); + ordered_functions.push_back({io_stats, value}); + ordered_functions.push_back({vram, value}); + ordered_functions.push_back({ram, value}); + ordered_functions.push_back({fps, value}); + ordered_functions.push_back({engine_version, value}); + ordered_functions.push_back({gpu_name, value}); + ordered_functions.push_back({vulkan_driver, value}); + ordered_functions.push_back({arch, value}); + ordered_functions.push_back({wine, value}); + ordered_functions.push_back({frame_timing, value}); + ordered_functions.push_back({media_player, value}); } HudElements HUDElements; diff --git a/src/hud_elements.h b/src/hud_elements.h index 425fc3e3..c1ebc64b 100644 --- a/src/hud_elements.h +++ b/src/hud_elements.h @@ -16,7 +16,12 @@ class HudElements{ std::vector> options; std::vector> ordered_functions; int min, max, gpu_core_max, gpu_mem_max, cpu_temp_max, gpu_temp_max; + std::vector permitted_params = { + "gpu_load", "cpu_load", "gpu_core_clock", "gpu_mem_clock", + "vram", "ram", "cpu_temp", "gpu_temp" + }; void sort_elements(std::pair option); + void legacy_elements(); static void version(); static void time(); static void gpu_stats(); diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 2c573992..6a8a3fb4 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -497,6 +497,7 @@ parse_overlay_config(struct overlay_params *params, params->enabled[OVERLAY_PARAM_ENABLED_wine] = false; params->enabled[OVERLAY_PARAM_ENABLED_gpu_load_change] = false; params->enabled[OVERLAY_PARAM_ENABLED_cpu_load_change] = false; + params->enabled[OVERLAY_PARAM_ENABLED_legacy_layout] = true; params->fps_sampling_period = 500000; /* 500ms */ params->width = 0; params->height = 140; @@ -671,6 +672,11 @@ parse_overlay_config(struct overlay_params *params, printf("MANGOHUD: output_file is Deprecated, use output_folder instead\n"); auto real_size = params->font_size * params->font_scale; real_font_size = ImVec2(real_size, real_size / 2); - for (auto& option : HUDElements.options) - HUDElements.sort_elements(option); + HUDElements.params = params; + if (params->enabled[OVERLAY_PARAM_ENABLED_legacy_layout]){ + HUDElements.legacy_elements(); + } else { + for (auto& option : HUDElements.options) + HUDElements.sort_elements(option); + } } diff --git a/src/overlay_params.h b/src/overlay_params.h index 68d97483..57eeea15 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -54,6 +54,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_BOOL(gpu_load_change) \ OVERLAY_PARAM_BOOL(cpu_load_change) \ OVERLAY_PARAM_BOOL(graphs) \ + OVERLAY_PARAM_BOOL(legacy_layout) \ OVERLAY_PARAM_CUSTOM(fps_sampling_period) \ OVERLAY_PARAM_CUSTOM(output_folder) \ OVERLAY_PARAM_CUSTOM(output_file) \ From 3c75cc6c60866362afa9ba4122059b46bc226b02 Mon Sep 17 00:00:00 2001 From: jackun Date: Tue, 10 Nov 2020 09:31:34 +0200 Subject: [PATCH 090/130] rm -fr whitespace around __gnu_linux__ --- src/vulkan.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vulkan.cpp b/src/vulkan.cpp index d1eae394..98b96fbd 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -460,7 +460,7 @@ struct overlay_draw *get_overlay_draw(struct swapchain_data *data) void init_cpu_stats(overlay_params& params) { -#ifdef __gnu_linux__ +#ifdef __gnu_linux__ auto& enabled = params.enabled; enabled[OVERLAY_PARAM_ENABLED_cpu_stats] = cpuStats.Init() && enabled[OVERLAY_PARAM_ENABLED_cpu_stats]; @@ -984,7 +984,7 @@ static void compute_swapchain_display(struct swapchain_data *data) ImGui::EndFrame(); ImGui::Render(); - + } static uint32_t vk_memory_type(struct device_data *data, @@ -2015,7 +2015,7 @@ static struct overlay_draw *before_present(struct swapchain_data *swapchain_data void get_device_name(int32_t vendorID, int32_t deviceID, struct swapchain_stats& sw_stats) { -#ifdef __gnu_linux__ +#ifdef __gnu_linux__ string desc = pci_ids[vendorID].second[deviceID].desc; size_t position = desc.find("["); if (position != std::string::npos) { @@ -2438,7 +2438,7 @@ static VkResult overlay_CreateInstance( if (!is_blacklisted()) { parse_overlay_config(&instance_data->params, getenv("MANGOHUD_CONFIG")); -#ifdef __gnu_linux__ +#ifdef __gnu_linux__ instance_data->notifier.params = &instance_data->params; start_notifier(instance_data->notifier); #endif @@ -2471,7 +2471,7 @@ static void overlay_DestroyInstance( instance_data_map_physical_devices(instance_data, false); instance_data->vtable.DestroyInstance(instance, pAllocator); if (!is_blacklisted()) -#ifdef __gnu_linux__ +#ifdef __gnu_linux__ stop_notifier(instance_data->notifier); #endif destroy_instance_data(instance_data); From b177b2ac1f8f649a92aa1dd406a8b1ed1b733a81 Mon Sep 17 00:00:00 2001 From: jackun Date: Tue, 10 Nov 2020 09:04:13 +0200 Subject: [PATCH 091/130] Partial revert 63b50abeded5099910f3a70df820266628d3fac6 --- bin/mangohud-setup.sh | 10 ++++++++++ build.sh | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/bin/mangohud-setup.sh b/bin/mangohud-setup.sh index 232706e8..f64c9c51 100755 --- a/bin/mangohud-setup.sh +++ b/bin/mangohud-setup.sh @@ -63,6 +63,16 @@ mangohud_install() { ln -sv . /usr/lib/mangohud/lib/x86_64-linux-gnu # $LIB can be "lib/tls/x86_64"? ln -sv ../tls /usr/lib/mangohud/lib/tls + + ln -sv lib /usr/lib/mangohud/lib64 + ln -sv lib /usr/lib/mangohud/x86_64 + ln -sv lib /usr/lib/mangohud/x86_64-linux-gnu + ln -sv . /usr/lib/mangohud/lib/x86_64 + ln -sv lib32 /usr/lib/mangohud/i686 + ln -sv lib32 /usr/lib/mangohud/i386-linux-gnu + ln -sv ../lib32 /usr/lib/mangohud/lib/i386-linux-gnu + ln -sv lib32 /usr/lib/mangohud/i686-linux-gnu + ln -sv ../lib32 /usr/lib/mangohud/lib/i686-linux-gnu #ln -sv lib /usr/lib/mangohud/aarch64-linux-gnu #ln -sv lib /usr/lib/mangohud/arm-linux-gnueabihf diff --git a/build.sh b/build.sh index 269e9a8b..81fc8bf5 100755 --- a/build.sh +++ b/build.sh @@ -222,6 +222,16 @@ install() { ln -sv . /usr/lib/mangohud/lib/x86_64-linux-gnu # $LIB can be "lib/tls/x86_64"? ln -sv ../tls /usr/lib/mangohud/lib/tls + + ln -sv lib /usr/lib/mangohud/lib64 + ln -sv lib /usr/lib/mangohud/x86_64 + ln -sv lib /usr/lib/mangohud/x86_64-linux-gnu + ln -sv . /usr/lib/mangohud/lib/x86_64 + ln -sv lib32 /usr/lib/mangohud/i686 + ln -sv lib32 /usr/lib/mangohud/i386-linux-gnu + ln -sv ../lib32 /usr/lib/mangohud/lib/i386-linux-gnu + ln -sv lib32 /usr/lib/mangohud/i686-linux-gnu + ln -sv ../lib32 /usr/lib/mangohud/lib/i686-linux-gnu #ln -sv lib /usr/lib/mangohud/aarch64-linux-gnu #ln -sv lib /usr/lib/mangohud/arm-linux-gnueabihf From ed2e06e68d389ce127003a24dacc80e105978bdd Mon Sep 17 00:00:00 2001 From: jackun Date: Tue, 10 Nov 2020 15:41:22 +0200 Subject: [PATCH 092/130] Fix minhook repo url --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index b6ae151c..7525fc2f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "modules/minhook"] path = modules/minhook - url = https://github.com/TsudaKageyu/minhook + url = https://github.com/flightlessmango/minhook From 553bf50e6a4d24a29dd4102c5955402918e85140 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Wed, 11 Nov 2020 23:11:21 +0100 Subject: [PATCH 093/130] Added cpu_mhz param --- src/cpu.cpp | 4 ++++ src/cpu.h | 1 + src/hud_elements.cpp | 10 ++++++++++ src/overlay_params.h | 1 + 4 files changed, 16 insertions(+) diff --git a/src/cpu.cpp b/src/cpu.cpp index 0acdc68e..6799b1b3 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -220,6 +220,10 @@ bool CPUStats::UpdateCoreMhz() { i++; } } + m_cpuDataTotal.cpu_mhz = 0; + for (auto data : m_cpuData) + m_cpuDataTotal.cpu_mhz += data.mhz; + m_cpuDataTotal.cpu_mhz /= m_cpuData.size(); return true; } diff --git a/src/cpu.h b/src/cpu.h index 1b2c29d8..29124b22 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -35,6 +35,7 @@ typedef struct CPUData_ { float percent; int mhz; int temp; + int cpu_mhz; } CPUData; class CPUStats diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 1936092b..7e17f523 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -115,6 +115,16 @@ void HudElements::cpu_stats(){ ImGui::SameLine(0, 1.0f); ImGui::Text("°C"); } + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_mhz]) + ImGui::TableNextRow(); + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_mhz]){ + ImGui::TableNextCell(); + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().cpu_mhz); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("MHz"); + ImGui::PopFont(); + } } } diff --git a/src/overlay_params.h b/src/overlay_params.h index 57eeea15..d3da03d1 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -55,6 +55,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_BOOL(cpu_load_change) \ OVERLAY_PARAM_BOOL(graphs) \ OVERLAY_PARAM_BOOL(legacy_layout) \ + OVERLAY_PARAM_BOOL(cpu_mhz) \ OVERLAY_PARAM_CUSTOM(fps_sampling_period) \ OVERLAY_PARAM_CUSTOM(output_folder) \ OVERLAY_PARAM_CUSTOM(output_file) \ From 00c9841ff60cf659e547a9e127b1bb7ba230101b Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Thu, 12 Nov 2020 03:35:01 +0100 Subject: [PATCH 094/130] Histogram option for all graphs --- src/hud_elements.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 7e17f523..1dd071a2 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -477,10 +477,18 @@ void HudElements::graphs(){ } ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); ImGui::TableNextRow(); - ImGui::PlotLines("", arr.data(), - arr.size(), 0, - NULL, HUDElements.min, HUDElements.max, - ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); + if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_histogram]){ + ImGui::PlotLines("", arr.data(), + arr.size(), 0, + NULL, HUDElements.min, HUDElements.max, + ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); + } else { + ImGui::PlotHistogram("", arr.data(), + arr.size(), 0, + NULL, HUDElements.min, HUDElements.max, + ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); + } + ImGui::PopStyleColor(1); } From 3726c90c7a0b7fc40d349690634e2cb40a150eee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hor=C3=A1=C4=8Dek?= Date: Thu, 12 Nov 2020 22:27:35 +0100 Subject: [PATCH 095/130] Add cpu_power --- README.md | 2 +- bin/MangoHud.conf | 1 + src/cpu.cpp | 294 +++++++++++++++++++++++++++++++++++++++++ src/cpu.h | 71 ++++++++++ src/hud_elements.cpp | 10 +- src/overlay.cpp | 2 + src/overlay_params.cpp | 1 + src/overlay_params.h | 1 + src/vulkan.cpp | 2 + 9 files changed, 382 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0781683c..d44e4b01 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `log_interval` | Change the default log interval, `100` is default | | `vulkan_driver` | Displays used vulkan driver, radv/amdgpu-pro/amdvlk | | `gpu_name` | Displays GPU name from pci.ids | -| `gpu_power` | Display GPU draw in watts | +| `cpu_power`
`gpu_power` | Display CPU/GPU draw in watts | | `engine_version` | Display OpenGL or vulkan and vulkan-based render engine's version | | `permit_upload` | Allow uploading of logs to Flightlessmango.com | | `upload_log` | Change keybind for uploading log | diff --git a/bin/MangoHud.conf b/bin/MangoHud.conf index 4eba14eb..a8be6995 100644 --- a/bin/MangoHud.conf +++ b/bin/MangoHud.conf @@ -19,6 +19,7 @@ ### Display the current CPU information cpu_stats # cpu_temp +# cpu_power # cpu_text = "CPU" ### Display the current GPU information diff --git a/src/cpu.cpp b/src/cpu.cpp index 6799b1b3..6d106e54 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -240,6 +240,113 @@ bool CPUStats::UpdateCpuTemp() { return ret; } +static bool get_cpu_power_k10temp(CPUPowerData* cpuPowerData, int& power) { + CPUPowerData_k10temp* powerData_k10temp = (CPUPowerData_k10temp*)cpuPowerData; + + if (!powerData_k10temp->coreVoltageFile || !powerData_k10temp->coreCurrentFile || !powerData_k10temp->socVoltageFile || !powerData_k10temp->socCurrentFile) + return false; + + rewind(powerData_k10temp->coreVoltageFile); + rewind(powerData_k10temp->coreCurrentFile); + rewind(powerData_k10temp->socVoltageFile); + rewind(powerData_k10temp->socCurrentFile); + + fflush(powerData_k10temp->coreVoltageFile); + fflush(powerData_k10temp->coreCurrentFile); + fflush(powerData_k10temp->socVoltageFile); + fflush(powerData_k10temp->socCurrentFile); + + int coreVoltage, coreCurrent; + int socVoltage, socCurrent; + + if (fscanf(powerData_k10temp->coreVoltageFile, "%d", &coreVoltage) != 1) + return false; + if (fscanf(powerData_k10temp->coreCurrentFile, "%d", &coreCurrent) != 1) + return false; + if (fscanf(powerData_k10temp->socVoltageFile, "%d", &socVoltage) != 1) + return false; + if (fscanf(powerData_k10temp->socCurrentFile, "%d", &socCurrent) != 1) + return false; + + power = (coreVoltage * coreCurrent + socVoltage * socCurrent) / 1000000; + + return true; +} + +static bool get_cpu_power_zenpower(CPUPowerData* cpuPowerData, int& power) { + CPUPowerData_zenpower* powerData_zenpower = (CPUPowerData_zenpower*)cpuPowerData; + + if (!powerData_zenpower->corePowerFile || !powerData_zenpower->socPowerFile) + return false; + + rewind(powerData_zenpower->corePowerFile); + rewind(powerData_zenpower->socPowerFile); + + fflush(powerData_zenpower->corePowerFile); + fflush(powerData_zenpower->socPowerFile); + + int corePower, socPower; + + if (fscanf(powerData_zenpower->corePowerFile, "%d", &corePower) != 1) + return false; + if (fscanf(powerData_zenpower->socPowerFile, "%d", &socPower) != 1) + return false; + + power = (corePower + socPower) / 1000000; + + return true; +} + +static bool get_cpu_power_rapl(CPUPowerData* cpuPowerData, int& power) { + CPUPowerData_rapl* powerData_rapl = (CPUPowerData_rapl*)cpuPowerData; + + if (!powerData_rapl->energyCounterFile) + return false; + + rewind(powerData_rapl->energyCounterFile); + fflush(powerData_rapl->energyCounterFile); + + int energyCounterValue = 0; + if (fscanf(powerData_rapl->energyCounterFile, "%d", &energyCounterValue) != 1) + return false; + + Clock::time_point now = Clock::now(); + Clock::duration timeDiff = now - powerData_rapl->lastCounterValueTime; + int energyCounterDiff = energyCounterValue - powerData_rapl->lastCounterValue; + + power = (int)((float)energyCounterDiff / (float)timeDiff.count() * 1000); + + powerData_rapl->lastCounterValue = energyCounterValue; + powerData_rapl->lastCounterValueTime = now; + + return true; +} + +bool CPUStats::UpdateCpuPower() { + if(!m_cpuPowerData) + return false; + + int power = 0; + + switch(m_cpuPowerData->source) { + case CPU_POWER_K10TEMP: + if (!get_cpu_power_k10temp(m_cpuPowerData.get(), power)) return false; + break; + case CPU_POWER_ZENPOWER: + if (!get_cpu_power_zenpower(m_cpuPowerData.get(), power)) return false; + break; + case CPU_POWER_RAPL: + if (!get_cpu_power_rapl(m_cpuPowerData.get(), power)) return false; + break; + default: + return false; + } + + m_cpuDataTotal.power = power; + + return true; +} + static bool find_temp_input(const std::string path, std::string& input, const std::string& name) { auto files = ls(path.c_str(), "temp", LS_FILES); @@ -321,4 +428,191 @@ bool CPUStats::GetCpuFile() { return true; } +static bool find_voltage_input(const std::string path, std::string& input, const std::string& name) +{ + auto files = ls(path.c_str(), "in", LS_FILES); + for (auto& file : files) { + if (!ends_with(file, "_label")) + continue; + + auto label = read_line(path + "/" + file); + if (label != name) + continue; + + auto uscore = file.find_first_of("_"); + if (uscore != std::string::npos) { + file.erase(uscore, std::string::npos); + input = path + "/" + file + "_input"; + return true; + } + } + return false; +} + +static bool find_current_input(const std::string path, std::string& input, const std::string& name) +{ + auto files = ls(path.c_str(), "curr", LS_FILES); + for (auto& file : files) { + if (!ends_with(file, "_label")) + continue; + + auto label = read_line(path + "/" + file); + if (label != name) + continue; + + auto uscore = file.find_first_of("_"); + if (uscore != std::string::npos) { + file.erase(uscore, std::string::npos); + input = path + "/" + file + "_input"; + return true; + } + } + return false; +} + +static bool find_power_input(const std::string path, std::string& input, const std::string& name) +{ + auto files = ls(path.c_str(), "power", LS_FILES); + for (auto& file : files) { + if (!ends_with(file, "_label")) + continue; + + auto label = read_line(path + "/" + file); + if (label != name) + continue; + + auto uscore = file.find_first_of("_"); + if (uscore != std::string::npos) { + file.erase(uscore, std::string::npos); + input = path + "/" + file + "_input"; + return true; + } + } + return false; +} + +CPUPowerData_k10temp* init_cpu_power_data_k10temp(const std::string path) { + CPUPowerData_k10temp* powerData = new CPUPowerData_k10temp(); + + std::string coreVoltageInput, coreCurrentInput; + std::string socVoltageInput, socCurrentInput; + + if(!find_voltage_input(path, coreVoltageInput, "Vcore")) goto error; + if(!find_current_input(path, coreCurrentInput, "Icore")) goto error; + if(!find_voltage_input(path, socVoltageInput, "Vsoc")) goto error; + if(!find_current_input(path, socCurrentInput, "Isoc")) goto error; + +#ifndef NDEBUG + std::cerr << "hwmon: using input: " << coreVoltageInput << std::endl; + std::cerr << "hwmon: using input: " << coreCurrentInput << std::endl; + std::cerr << "hwmon: using input: " << socVoltageInput << std::endl; + std::cerr << "hwmon: using input: " << socCurrentInput << std::endl; +#endif + + powerData->coreVoltageFile = fopen(coreVoltageInput.c_str(), "r"); + powerData->coreCurrentFile = fopen(coreCurrentInput.c_str(), "r"); + powerData->socVoltageFile = fopen(socVoltageInput.c_str(), "r"); + powerData->socCurrentFile = fopen(socCurrentInput.c_str(), "r"); + goto success; + +error: + delete powerData; + return nullptr; + +success: + return powerData; +} + +CPUPowerData_zenpower* init_cpu_power_data_zenpower(const std::string path) { + CPUPowerData_zenpower* powerData = new CPUPowerData_zenpower(); + + std::string corePowerInput, socPowerInput; + + if(!find_power_input(path, corePowerInput, "SVI2_P_Core")) goto error; + if(!find_power_input(path, socPowerInput, "SVI2_P_SoC")) goto error; + +#ifndef NDEBUG + std::cerr << "hwmon: using input: " << corePowerInput << std::endl; + std::cerr << "hwmon: using input: " << socPowerInput << std::endl; +#endif + + powerData->corePowerFile = fopen(corePowerInput.c_str(), "r"); + powerData->socPowerFile = fopen(socPowerInput.c_str(), "r"); + goto success; + +error: + delete powerData; + return nullptr; + +success: + return powerData; +} + +CPUPowerData_rapl* init_cpu_power_data_rapl(const std::string path) { + CPUPowerData_rapl* powerData = new CPUPowerData_rapl(); + + std::string energyCounterPath = path + "/energy_uj"; + if (!file_exists(energyCounterPath)) goto error; + + powerData->energyCounterFile = fopen(energyCounterPath.c_str(), "r"); + goto success; + +error: + delete powerData; + return nullptr; + +success: + return powerData; +} + +bool CPUStats::InitCpuPowerData() { + if(m_cpuPowerData != nullptr) + return true; + + std::string name, path; + std::string hwmon = "/sys/class/hwmon/"; + + CPUPowerData* cpuPowerData = nullptr; + + auto dirs = ls(hwmon.c_str()); + for (auto& dir : dirs) { + path = hwmon + dir; + name = read_line(path + "/name"); +#ifndef NDEBUG + std::cerr << "hwmon: sensor name: " << name << std::endl; +#endif + if (name == "k10temp") { + cpuPowerData = (CPUPowerData*)init_cpu_power_data_k10temp(path); + break; + } else if (name == "zenpower") { + cpuPowerData = (CPUPowerData*)init_cpu_power_data_zenpower(path); + break; + } + } + + if (!cpuPowerData) { + std::string powercap = "/sys/class/powercap/"; + auto powercap_dirs = ls(powercap.c_str()); + for (auto& dir : powercap_dirs) { + path = powercap + dir; + name = read_line(path + "/name"); +#ifndef NDEBUG + std::cerr << "powercap: name: " << name << std::endl; +#endif + if (name == "package-0") { + cpuPowerData = (CPUPowerData*)init_cpu_power_data_rapl(path); + break; + } + } + } + + if(cpuPowerData == nullptr) { + std::cerr << "MANGOHUD: Failed to initialize CPU power data" << std::endl; + return false; + } + + m_cpuPowerData.reset(cpuPowerData); + return true; +} + CPUStats cpuStats; diff --git a/src/cpu.h b/src/cpu.h index 29124b22..53943acf 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -5,6 +5,9 @@ #include #include #include +#include + +#include "timing.hpp" typedef struct CPUData_ { unsigned long long int totalTime; @@ -36,8 +39,73 @@ typedef struct CPUData_ { int mhz; int temp; int cpu_mhz; + int power; } CPUData; +enum { + CPU_POWER_K10TEMP, + CPU_POWER_ZENPOWER, + CPU_POWER_RAPL +}; + +struct CPUPowerData { + int source; +}; + +struct CPUPowerData_k10temp : public CPUPowerData { + CPUPowerData_k10temp() { + this->source = CPU_POWER_K10TEMP; + }; + + ~CPUPowerData_k10temp() { + if(this->coreVoltageFile) + fclose(this->coreVoltageFile); + if(this->coreCurrentFile) + fclose(this->coreCurrentFile); + if(this->socVoltageFile) + fclose(this->socVoltageFile); + if(this->socCurrentFile) + fclose(this->socCurrentFile); + }; + + FILE* coreVoltageFile; + FILE* coreCurrentFile; + FILE* socVoltageFile; + FILE* socCurrentFile; +}; + +struct CPUPowerData_zenpower : public CPUPowerData { + CPUPowerData_zenpower() { + this->source = CPU_POWER_ZENPOWER; + }; + + ~CPUPowerData_zenpower() { + if(this->corePowerFile) + fclose(this->corePowerFile); + if(this->socPowerFile) + fclose(this->socPowerFile); + }; + + FILE* corePowerFile; + FILE* socPowerFile; +}; + +struct CPUPowerData_rapl : public CPUPowerData { + CPUPowerData_rapl() { + this->source = CPU_POWER_RAPL; + this->lastCounterValueTime = Clock::now(); + }; + + ~CPUPowerData_rapl() { + if(this->energyCounterFile) + fclose(this->energyCounterFile); + }; + + FILE* energyCounterFile; + int lastCounterValue; + Clock::time_point lastCounterValueTime; +}; + class CPUStats { public: @@ -52,7 +120,9 @@ public: bool UpdateCPUData(); bool UpdateCoreMhz(); bool UpdateCpuTemp(); + bool UpdateCpuPower(); bool GetCpuFile(); + bool InitCpuPowerData(); double GetCPUPeriod() { return m_cpuPeriod; } const std::vector& GetCPUData() const { @@ -70,6 +140,7 @@ private: bool m_updatedCPUs = false; // TODO use caching or just update? bool m_inited = false; FILE *m_cpuTempFile = nullptr; + std::unique_ptr m_cpuPowerData; }; extern CPUStats cpuStats; diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 1dd071a2..a03631c0 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -115,7 +115,7 @@ void HudElements::cpu_stats(){ ImGui::SameLine(0, 1.0f); ImGui::Text("°C"); } - if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_mhz]) + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_mhz] || HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_power]) ImGui::TableNextRow(); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_mhz]){ ImGui::TableNextCell(); @@ -125,6 +125,14 @@ void HudElements::cpu_stats(){ ImGui::Text("MHz"); ImGui::PopFont(); } + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_power]){ + ImGui::TableNextCell(); + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().power); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("W"); + ImGui::PopFont(); + } } } diff --git a/src/overlay.cpp b/src/overlay.cpp index 6569478c..a03015fa 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -26,6 +26,8 @@ void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& par cpuStats.UpdateCoreMhz(); if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_temp] || logger->is_active()) cpuStats.UpdateCpuTemp(); + if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_power]) + cpuStats.UpdateCpuPower(); #endif } if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] || logger->is_active()) { diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 6a8a3fb4..68ea1e81 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -485,6 +485,7 @@ parse_overlay_config(struct overlay_params *params, params->enabled[OVERLAY_PARAM_ENABLED_frame_timing] = true; params->enabled[OVERLAY_PARAM_ENABLED_core_load] = false; params->enabled[OVERLAY_PARAM_ENABLED_cpu_temp] = false; + params->enabled[OVERLAY_PARAM_ENABLED_cpu_power] = false; params->enabled[OVERLAY_PARAM_ENABLED_gpu_temp] = false; params->enabled[OVERLAY_PARAM_ENABLED_cpu_stats] = true; params->enabled[OVERLAY_PARAM_ENABLED_gpu_stats] = true; diff --git a/src/overlay_params.h b/src/overlay_params.h index d3da03d1..46f0793d 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -29,6 +29,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_BOOL(frame_timing) \ OVERLAY_PARAM_BOOL(core_load) \ OVERLAY_PARAM_BOOL(cpu_temp) \ + OVERLAY_PARAM_BOOL(cpu_power) \ OVERLAY_PARAM_BOOL(gpu_temp) \ OVERLAY_PARAM_BOOL(cpu_stats) \ OVERLAY_PARAM_BOOL(gpu_stats) \ diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 98b96fbd..3c2c8b5c 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -466,6 +466,8 @@ void init_cpu_stats(overlay_params& params) && enabled[OVERLAY_PARAM_ENABLED_cpu_stats]; enabled[OVERLAY_PARAM_ENABLED_cpu_temp] = cpuStats.GetCpuFile() && enabled[OVERLAY_PARAM_ENABLED_cpu_temp]; + enabled[OVERLAY_PARAM_ENABLED_cpu_power] = cpuStats.InitCpuPowerData() + && enabled[OVERLAY_PARAM_ENABLED_cpu_power]; #endif } From 02a34ba890d9bc0ff0a6571bb55fe1fca651d963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hor=C3=A1=C4=8Dek?= Date: Thu, 12 Nov 2020 13:19:22 +0100 Subject: [PATCH 096/130] Fix cpu_mhz when core_load is disabled --- src/overlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlay.cpp b/src/overlay.cpp index 6569478c..ea56084f 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -22,7 +22,7 @@ void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& par cpuStats.UpdateCPUData(); #ifdef __gnu_linux__ - if (params.enabled[OVERLAY_PARAM_ENABLED_core_load]) + if (params.enabled[OVERLAY_PARAM_ENABLED_core_load] || params.enabled[OVERLAY_PARAM_ENABLED_cpu_mhz]) cpuStats.UpdateCoreMhz(); if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_temp] || logger->is_active()) cpuStats.UpdateCpuTemp(); From 83494790269d6814fbea48d92bba1e0a7cc448bb Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Fri, 13 Nov 2020 22:22:01 +0100 Subject: [PATCH 097/130] Document cpu_mhz and cpu_load_change --- README.md | 8 ++++++++ bin/MangoHud.conf | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/README.md b/README.md index 0781683c..5f18f3c7 100644 --- a/README.md +++ b/README.md @@ -177,6 +177,14 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `benchmark_percentiles` | Configure which framerate percentiles are shown in the logging summary. Default is `97+AVG+1+0.1` | | `wine` | Shows current Wine or Proton version in use | | `wine_color` | Change color of the wine/proton text | +| `cpu_mhz` | Shows the CPUs current MHz | +| `gpu_load_change` | Changes the color of the GPU load depending on load | +| `gpu_load_color` | Set the colors for the gpu load change low,medium and high. e.g `gpu_load_color=0000FF,00FFFF,FF00FF` | +| `gpu_load_value` | Set the values for medium and high load e.g `gpu_load_value=50,90` | +| `cpu_load_change` | Changes the color of the CPU load depending on load | +| `cpu_load_color` | Set the colors for the gpu load change low,medium and high. e.g `cpu_load_color=0000FF,00FFFF,FF00FF` | +| `cpu_load_value` | Set the values for medium and high load e.g `cpu_load_value=50,90` | + Example: `MANGOHUD_CONFIG=cpu_temp,gpu_temp,position=top-right,height=500,font_size=32` Note: Width and Height are set automatically based on the font_size, but can be overridden. diff --git a/bin/MangoHud.conf b/bin/MangoHud.conf index 4eba14eb..a897c3e9 100644 --- a/bin/MangoHud.conf +++ b/bin/MangoHud.conf @@ -20,6 +20,10 @@ cpu_stats # cpu_temp # cpu_text = "CPU" +# cpu_mhz +# cpu_load_change +# cpu_load_value +# cpu_load_color ### Display the current GPU information gpu_stats @@ -30,6 +34,9 @@ gpu_stats # gpu_power # gpu_text = "GPU" # vulkan_driver +# gpu_load_change +# gpu_load_value +# gpu_load_color ### Display loaded MangoHud architecture # arch From 60ffab4350810f65f164a1e341de4a802bb5977c Mon Sep 17 00:00:00 2001 From: jackun Date: Wed, 23 Sep 2020 14:02:27 +0300 Subject: [PATCH 098/130] Add `no_small_font` option for unified font size --- README.md | 1 + bin/MangoHud.conf | 1 + src/font.cpp | 10 ++++++++-- src/overlay_params.cpp | 4 ++++ src/overlay_params.h | 2 ++ 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5f18f3c7..e4da54ec 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `font_file` | Change default font (set location to .TTF/.OTF file ) | | `font_file_text` | Change text font. Otherwise `font_file` is used | | `font_glyph_ranges` | Specify extra font glyph ranges, comma separated: `korean`, `chinese`, `chinese_simplified`, `japanese`, `cyrillic`, `thai`, `vietnamese`, `latin_ext_a`, `latin_ext_b`. If you experience crashes or text is just squares, reduce font size or glyph ranges. | +| `no_small_font` | Use primary font size for smaller text like units | | `width=`
`height=` | Customizeable hud dimensions (in pixels) | | `position=` | Location of the hud: `top-left` (default), `top-right`, `bottom-left`, `bottom-right`, `top-center` | | `offset_x` `offset_y` | Hud position offsets | diff --git a/bin/MangoHud.conf b/bin/MangoHud.conf index a897c3e9..5e0e9a43 100644 --- a/bin/MangoHud.conf +++ b/bin/MangoHud.conf @@ -58,6 +58,7 @@ font_size=24 # font_scale=1.0 # font_size_text=24 # font_scale_media_player = 0.55 +# no_small_font ### Change default font (set location to .TTF/.OTF file ) ## Set font for the whole hud diff --git a/src/font.cpp b/src/font.cpp index a5abb5d9..ff51de87 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -56,11 +56,17 @@ void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& te // ImGui takes ownership of the data, no need to free it if (!params.font_file.empty() && file_exists(params.font_file)) { io.Fonts->AddFontFromFileTTF(params.font_file.c_str(), font_size, nullptr, same_font && same_size ? glyph_ranges.Data : default_range); - small_font = io.Fonts->AddFontFromFileTTF(params.font_file.c_str(), font_size * 0.55f, nullptr, default_range); + if (params.no_small_font) + small_font = io.Fonts->Fonts[0]; + else + small_font = io.Fonts->AddFontFromFileTTF(params.font_file.c_str(), font_size * 0.55f, nullptr, default_range); } else { const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_size, nullptr, default_range); - small_font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_size * 0.55f, nullptr, default_range); + if (params.no_small_font) + small_font = io.Fonts->Fonts[0]; + else + small_font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_size * 0.55f, nullptr, default_range); } auto font_file_text = params.font_file_text; diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 6a8a3fb4..5b22c8b6 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -343,6 +343,7 @@ parse_font_glyph_ranges(const char *str) #define parse_background_alpha(s) parse_float(s) #define parse_alpha(s) parse_float(s) #define parse_permit_upload(s) parse_unsigned(s) +#define parse_no_small_font(s) parse_unsigned(s) != 0 #define parse_cpu_color(s) parse_color(s) #define parse_gpu_color(s) parse_color(s) @@ -651,6 +652,9 @@ parse_overlay_config(struct overlay_params *params, } else { params->width = params->font_size * params->font_scale * 11.7; } + // Treat it like hud would need to be ~7 characters wider with default font. + if (params->no_small_font) + params->width += 7 * params->font_size * params->font_scale; } // set frametime limit diff --git a/src/overlay_params.h b/src/overlay_params.h index d3da03d1..798ddc76 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -62,6 +62,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(font_file) \ OVERLAY_PARAM_CUSTOM(font_file_text) \ OVERLAY_PARAM_CUSTOM(font_glyph_ranges) \ + OVERLAY_PARAM_CUSTOM(no_small_font) \ OVERLAY_PARAM_CUSTOM(font_size) \ OVERLAY_PARAM_CUSTOM(font_size_text) \ OVERLAY_PARAM_CUSTOM(font_scale) \ @@ -176,6 +177,7 @@ struct overlay_params { std::vector cpu_load_value; unsigned media_player_color; unsigned tableCols; + bool no_small_font; float font_size, font_scale; float font_size_text; float font_scale_media_player; From e5015283a8f84a5fc314907dd9f7c15af6e8ba3e Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Mon, 16 Nov 2020 12:53:38 +0100 Subject: [PATCH 099/130] cellpadding_y param --- README.md | 1 + src/overlay_params.cpp | 2 ++ src/overlay_params.h | 2 ++ src/vulkan.cpp | 2 +- 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e4da54ec..234762d1 100644 --- a/README.md +++ b/README.md @@ -185,6 +185,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `cpu_load_change` | Changes the color of the CPU load depending on load | | `cpu_load_color` | Set the colors for the gpu load change low,medium and high. e.g `cpu_load_color=0000FF,00FFFF,FF00FF` | | `cpu_load_value` | Set the values for medium and high load e.g `cpu_load_value=50,90` | +| `cellpadding_y` | Set the vertical cellpadding, default is `-0.085` | Example: `MANGOHUD_CONFIG=cpu_temp,gpu_temp,position=top-right,height=500,font_size=32` diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 5b22c8b6..1db0f7ce 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -344,6 +344,7 @@ parse_font_glyph_ranges(const char *str) #define parse_alpha(s) parse_float(s) #define parse_permit_upload(s) parse_unsigned(s) #define parse_no_small_font(s) parse_unsigned(s) != 0 +#define parse_cellpadding_y(s) parse_float(s) #define parse_cpu_color(s) parse_color(s) #define parse_gpu_color(s) parse_color(s) @@ -533,6 +534,7 @@ parse_overlay_config(struct overlay_params *params, params->benchmark_percentiles = { "97", "AVG", "1", "0.1" }; params->gpu_load_value = { 90, 60 }; params->cpu_load_value = { 90, 60 }; + params->cellpadding_y = -0.085; diff --git a/src/overlay_params.h b/src/overlay_params.h index 798ddc76..314ad188 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -113,6 +113,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(cpu_load_value) \ OVERLAY_PARAM_CUSTOM(gpu_load_color) \ OVERLAY_PARAM_CUSTOM(cpu_load_color) \ + OVERLAY_PARAM_CUSTOM(cellpadding_y) \ enum overlay_param_position { LAYER_POSITION_TOP_LEFT, @@ -182,6 +183,7 @@ struct overlay_params { float font_size_text; float font_scale_media_player; float background_alpha, alpha; + float cellpadding_y; std::vector toggle_hud; std::vector toggle_fps_limit; std::vector toggle_logging; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 98b96fbd..e2c2e61c 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -1782,7 +1782,7 @@ void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overl style.Colors[ImGuiCol_PlotHistogram] = convert(params.frametime_color); style.Colors[ImGuiCol_WindowBg] = convert(params.background_color); style.Colors[ImGuiCol_Text] = convert(params.text_color); - style.CellPadding.y = -0.085 * real_font_size.y; + style.CellPadding.y = params.cellpadding_y * real_font_size.y; } // TODO probably needs colorspace check too From 7a2a2eafc9f476b4e3719e83de6b96f88ef6a20f Mon Sep 17 00:00:00 2001 From: jackun Date: Mon, 16 Nov 2020 23:35:45 +0200 Subject: [PATCH 100/130] Clear already parsed HUD elements when using legacy layout --- src/hud_elements.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 1dd071a2..242f6c70 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -526,6 +526,7 @@ void HudElements::sort_elements(std::pair option){ void HudElements::legacy_elements(){ string value = "NULL"; + ordered_functions.clear(); ordered_functions.push_back({time, value}); ordered_functions.push_back({version, value}); ordered_functions.push_back({gpu_stats, value}); From d677f72a7a51dd71e18dff02282c018ab48bd0e3 Mon Sep 17 00:00:00 2001 From: jackun Date: Tue, 10 Nov 2020 18:09:45 +0200 Subject: [PATCH 101/130] Build script for creating and building in Steam runtime docker --- build-srt.sh | 155 +++++++++++++++++---------------------- build-with-srt-docker.sh | 37 ++++++++++ steamrt.Dockerfile.in | 20 +++++ 3 files changed, 124 insertions(+), 88 deletions(-) create mode 100755 build-with-srt-docker.sh create mode 100644 steamrt.Dockerfile.in diff --git a/build-srt.sh b/build-srt.sh index b8938e8b..572c0e5f 100755 --- a/build-srt.sh +++ b/build-srt.sh @@ -1,24 +1,20 @@ #!/usr/bin/env bash -set -e - # Specialized build script for Steam Runtime SDK docker +set -e -OS_RELEASE_FILES=("/etc/os-release" "/usr/lib/os-release") -XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}" -XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" -DATA_DIR="$XDG_DATA_HOME/MangoHud" -CONFIG_DIR="$XDG_CONFIG_HOME/MangoHud" -LAYER="build/release/usr/share/vulkan/implicit_layer.d/mangohud.json" -INSTALL_DIR="build/package/" -IMPLICIT_LAYER_DIR="$XDG_DATA_HOME/vulkan/implicit_layer.d" +IFS=" " read -ra debian_chroot < /etc/debian_chroot +LOCAL_CC=${CC:-gcc-5} +LOCAL_CXX=${CXX:-g++-5} +RUNTIME=${RUNTIME:-${debian_chroot[1]}} +SRT_VERSION=${SRT_VERSION:-${debian_chroot[2]}} VERSION=$(git describe --long --tags --always | sed 's/\([^-]*-g\)/r\1/;s/-/./g;s/^v//') dependencies() { - if [[ ! -f build/release/usr/lib64/libMangoHud.so ]]; then + if [[ ! -f build-srt/release/usr/lib/libMangoHud.so ]]; then install() { set +e - for i in $(eval echo $DEPS); do + for i in ${DEPS[@]}; do dpkg-query -s "$i" &> /dev/null if [[ $? == 1 ]]; then INSTALL="$INSTALL""$i " @@ -32,19 +28,26 @@ dependencies() { } echo "# Checking Dependencies" - DEPS="{gcc-5-multilib,g++-5-multilib,unzip}" + DEPS=(${LOCAL_CC}-multilib ${LOCAL_CXX}-multilib unzip) install - # py3.2 is weird - ln -sf python3.5 /usr/bin/python3 + + # use py3.5 with scout, otherwise hope python is new enough + set +e + which python3.5 >/dev/null + if [ $? -eq 0 ]; then + # py3.2 is weird + ln -sf python3.5 /usr/bin/python3 + fi + set -e if [[ ! -f ./bin/get-pip.py ]]; then curl https://bootstrap.pypa.io/get-pip.py -o bin/get-pip.py - python3.5 ./bin/get-pip.py fi + python3 ./bin/get-pip.py - if [[ $(pip3.5 show meson; echo $?) == 1 || $(pip3.5 show mako; echo $?) == 1 ]]; then - pip3.5 install meson mako + if [[ $(pip3 show meson >/dev/null; echo $?) == 1 || $(pip3 show mako >/dev/null; echo $?) == 1 ]]; then + pip3 install meson mako fi if [[ ! -f /usr/include/NVCtrl/NVCtrl.h ]]; then @@ -66,83 +69,49 @@ dependencies() { configure() { dependencies git submodule update --init - if [[ ! -f "build/meson64/build.ninja" ]]; then - export CC="gcc-5" - export CXX="g++-5" - meson build/meson64 --libdir lib/mangohud/lib64 --prefix /usr -Dappend_libdir_mangohud=false ${CONFIGURE_OPTS} + if [[ ! -f "build-srt/meson64/build.ninja" ]]; then + export CC="${LOCAL_CC}" + export CXX="${LOCAL_CXX}" + meson build-srt/meson64 --libdir lib/mangohud/lib --prefix /usr -Dappend_libdir_mangohud=false -Dld_libdir_prefix=true $@ ${CONFIGURE_OPTS} fi - if [[ ! -f "build/meson32/build.ninja" ]]; then - export CC="gcc-5 -m32" - export CXX="g++-5 -m32" + if [[ ! -f "build-srt/meson32/build.ninja" ]]; then + export CC="${LOCAL_CC} -m32" + export CXX="${LOCAL_CXX} -m32" export PKG_CONFIG_PATH="/usr/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig:/usr/lib/pkgconfig:${PKG_CONFIG_PATH_32}" - export LLVM_CONFIG="/usr/bin/llvm-config32" - meson build/meson32 --libdir lib/mangohud/lib32 --prefix /usr -Dappend_libdir_mangohud=false ${CONFIGURE_OPTS} + meson build-srt/meson32 --libdir lib/mangohud/lib32 --prefix /usr -Dappend_libdir_mangohud=false -Dld_libdir_prefix=true $@ ${CONFIGURE_OPTS} fi } build() { - if [[ ! -f "build/meson64/build.ninja" || ! -f "build/meson32/build.ninja" ]]; then + if [[ ! -f "build-srt/meson64/build.ninja" || ! -f "build-srt/meson32/build.ninja" ]]; then configure fi - DESTDIR="$PWD/build/release" ninja -C build/meson32 install - DESTDIR="$PWD/build/release" ninja -C build/meson64 install + DESTDIR="$PWD/build-srt/release" ninja -C build-srt/meson32 install + DESTDIR="$PWD/build-srt/release" ninja -C build-srt/meson64 install } package() { - LIB="build/release/usr/lib/mangohud/lib64/libMangoHud.so" - LIB32="build/release/usr/lib/mangohud/lib32/libMangoHud.so" - if [[ ! -f "$LIB" || "$LIB" -ot "build/meson64/src/libMangoHud.so" ]]; then + LIB="build-srt/release/usr/lib/mangohud/lib/libMangoHud.so" + LIB32="build-srt/release/usr/lib/mangohud/lib32/libMangoHud.so" + if [[ ! -f "$LIB" || "$LIB" -ot "build-srt/meson64/src/libMangoHud.so" ]]; then build fi tar --numeric-owner --owner=0 --group=0 \ - -C build/release -cvf "build/MangoHud-package.tar" . + -C build-srt/release -cvf "build-srt/MangoHud-package.tar" . } release() { - rm build/MangoHud-package.tar - mkdir -p build/MangoHud + rm build-srt/MangoHud-package.tar + mkdir -p build-srt/MangoHud package - cp --preserve=mode bin/mangohud-setup.sh build/MangoHud/mangohud-setup.sh - cp build/MangoHud-package.tar build/MangoHud/MangoHud-package.tar + cp --preserve=mode bin/mangohud-setup.sh build-srt/MangoHud/mangohud-setup.sh + cp build-srt/MangoHud-package.tar build-srt/MangoHud/MangoHud-package.tar tar --numeric-owner --owner=0 --group=0 \ - -C build -czvf build/MangoHud-$VERSION.tar.gz MangoHud -} - -install() { - rm -rf "$HOME/.local/share/MangoHud/" - rm -f "$HOME/.local/share/vulkan/implicit_layer.d/"{mangohud32.json,mangohud64.json} - - [ "$UID" -eq 0 ] || mkdir -pv "${CONFIG_DIR}" - [ "$UID" -eq 0 ] || exec sudo bash "$0" install - - /usr/bin/install -vm644 -D ./build/release/usr/lib/mangohud/lib32/libMangoHud.so /usr/lib/mangohud/lib32/libMangoHud.so - /usr/bin/install -vm644 -D ./build/release/usr/lib/mangohud/lib64/libMangoHud.so /usr/lib/mangohud/lib64/libMangoHud.so - /usr/bin/install -vm644 -D ./build/release/usr/lib/mangohud/lib32/libMangoHud_dlsym.so /usr/lib/mangohud/lib32/libMangoHud_dlsym.so - /usr/bin/install -vm644 -D ./build/release/usr/lib/mangohud/lib64/libMangoHud_dlsym.so /usr/lib/mangohud/lib64/libMangoHud_dlsym.so - /usr/bin/install -vm644 -D ./build/release/usr/share/vulkan/implicit_layer.d/MangoHud.x86.json /usr/share/vulkan/implicit_layer.d/MangoHud.x86.json - /usr/bin/install -vm644 -D ./build/release/usr/share/vulkan/implicit_layer.d/MangoHud.x86_64.json /usr/share/vulkan/implicit_layer.d/MangoHud.x86_64.json - /usr/bin/install -vm644 -D ./build/release/usr/share/doc/mangohud/MangoHud.conf.example /usr/share/doc/mangohud/MangoHud.conf.example - - /usr/bin/install -vm755 ./build/release/usr/bin/mangohud.x86 /usr/bin/mangohud.x86 - /usr/bin/install -vm755 ./build/release/usr/bin/mangohud /usr/bin/mangohud - - echo "MangoHud Installed" + -C build-srt -czvf build-srt/MangoHud-${VERSION}_${RUNTIME}-${SRT_VERSION}.tar.gz MangoHud } clean() { - rm -rf "build" -} - -uninstall() { - [ "$UID" -eq 0 ] || exec sudo bash "$0" uninstall - rm -rfv "/usr/lib/mangohud" - rm -rfv "/usr/share/doc/mangohud" - rm -fv "/usr/share/vulkan/implicit_layer.d/mangohud.json" - rm -fv "/usr/share/vulkan/implicit_layer.d/MangoHud.json" - rm -fv "/usr/share/vulkan/implicit_layer.d/MangoHud.x86.json" - rm -fv "/usr/share/vulkan/implicit_layer.d/MangoHud.x86_64.json" - rm -fv "/usr/bin/mangohud" - rm -fv "/usr/bin/mangohud.x86" + rm -rf "build-srt/" } usage() { @@ -157,29 +126,39 @@ usage() { echo -e "\tconfigure\tEnsures that dependencies are installed, updates git submodules, and generates files needed for building MangoHud. This is automatically run by the build command" echo -e "\tbuild\t\tIf needed runs configure and then builds (compiles) MangoHud" echo -e "\tpackage\t\tRuns build if needed and then builds a tar package from MangoHud" - echo -e "\tinstall\t\tInstall MangoHud onto your system" echo -e "\tclean\t\tRemoves build directory" - echo -e "\tuninstall\tRemoves installed MangoHud files from your system" echo -e "\trelease\t\tBuilds a MangoHud release tar package" } -for a in $@; do - case $a in - "") build;; - "pull") git pull;; - "configure") configure;; - "build") build;; +if [[ -z $@ ]]; then + usage no-args +fi + +while [ $# -gt 0 ]; do + OPTS=() + arg="$1" + shift + + while [ $# -gt 0 ] ; do + case $1 in + -*) + OPTS+=("$1") + shift + ;; + *) + break + ;; + esac; + done + + echo -e "\e[1mCommand:\e[92m" $arg "\e[94m"${OPTS[@]}"\e[39m\e[0m" + case $arg in + "configure") configure ${OPTS[@]};; + "build") build ${OPTS[@]};; "package") package;; - "install") install;; "clean") clean;; - "uninstall") uninstall;; "release") release;; *) usage esac done - -if [[ -z $@ ]]; then - usage no-args -fi - diff --git a/build-with-srt-docker.sh b/build-with-srt-docker.sh new file mode 100755 index 00000000..b06a86ff --- /dev/null +++ b/build-with-srt-docker.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +set -u + +if [ $# -eq 2 ]; then + echo Specify runtime version too + exit 1 +fi + +SRCDIR=$PWD +BRANCH="${1:-master}" +# soldier 0.20201022.1 or newer +# scout 0.20201104.0 or newer +RUNTIME="${2:-soldier}" +VERSION="${3:-0.20201022.1}" +IMAGE="steamrt_${RUNTIME}_amd64:mango-${VERSION}" +BASEURL="https://repo.steampowered.com/steamrt-images-${RUNTIME}/snapshots/${VERSION}" + +echo -e "\e[1mBuilding branch \e[92m${BRANCH}\e[39m using \e[92m${RUNTIME}:${VERSION}\e[39m runtime\e[0m" + +if ! docker inspect --type=image ${IMAGE} 2>&1 >/dev/null ; then + rm -fr ./cache/empty + set -e + mkdir -p ./cache/empty + sed "s/%RUNTIME%/${RUNTIME}/g" steamrt.Dockerfile.in > ./cache/steamrt.Dockerfile + + wget -P ./cache -c ${BASEURL}/com.valvesoftware.SteamRuntime.Sdk-amd64,i386-${RUNTIME}-sysroot.tar.gz + cp --reflink=always "./cache/com.valvesoftware.SteamRuntime.Sdk-amd64,i386-${RUNTIME}-sysroot.tar.gz" ./cache/empty/ + docker build -f ./cache/steamrt.Dockerfile -t ${IMAGE} ./cache/empty +fi + +docker run --entrypoint=/bin/sh --rm -i -v "${SRCDIR}/srt-output:/output" ${IMAGE} << EOF +export RUNTIME=${RUNTIME} +export SRT_VERSION=${VERSION} +git clone git://github.com/flightlessmango/MangoHud.git . --branch ${BRANCH} --recurse-submodules --progress +./build-srt.sh clean build package release +cp -v build-srt/MangoHud*tar.gz /output/ +EOF diff --git a/steamrt.Dockerfile.in b/steamrt.Dockerfile.in new file mode 100644 index 00000000..a6ea0ad5 --- /dev/null +++ b/steamrt.Dockerfile.in @@ -0,0 +1,20 @@ +FROM scratch +ADD com.valvesoftware.SteamRuntime.Sdk-amd64,i386-%RUNTIME%-sysroot.tar.gz / +WORKDIR /build +RUN \ +set -e; \ +mkdir -p /run/systemd; \ +echo 'docker' > /run/systemd/container; \ +mkdir -p /prep; cd /prep; \ +curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py; \ +if [ ! -f /usr/bin/unzip ]; then apt-get update; apt-get -y install unzip; fi; \ +if [ -f /usr/bin/python3.5 ]; then ln -sf python3.5 /usr/bin/python3; fi; \ +python3 ./get-pip.py; \ +pip3 install meson mako; \ +curl -LO http://mirrors.kernel.org/ubuntu/pool/main/n/nvidia-settings/libxnvctrl0_440.64-0ubuntu1_amd64.deb; \ +curl -LO http://mirrors.kernel.org/ubuntu/pool/main/n/nvidia-settings/libxnvctrl-dev_440.64-0ubuntu1_amd64.deb; \ +dpkg -i libxnvctrl0_440.64-0ubuntu1_amd64.deb libxnvctrl-dev_440.64-0ubuntu1_amd64.deb; \ +cd /; rm -fr /prep; \ +: + +CMD ["/bin/bash"] From 92146c58339ab81389fb92accf6fb94ff397aa98 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Mon, 16 Nov 2020 15:37:03 -0800 Subject: [PATCH 102/130] Add frametime param to enable/disable frametime data next to fps --- README.md | 1 + bin/MangoHud.conf | 6 +++++- src/hud_elements.cpp | 14 ++++++++------ src/overlay_params.cpp | 1 + src/overlay_params.h | 1 + 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 234762d1..a38d124c 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `cpu_load_color` | Set the colors for the gpu load change low,medium and high. e.g `cpu_load_color=0000FF,00FFFF,FF00FF` | | `cpu_load_value` | Set the values for medium and high load e.g `cpu_load_value=50,90` | | `cellpadding_y` | Set the vertical cellpadding, default is `-0.085` | +| `frametime` | Display frametime next to fps text | Example: `MANGOHUD_CONFIG=cpu_temp,gpu_temp,position=top-right,height=500,font_size=32` diff --git a/bin/MangoHud.conf b/bin/MangoHud.conf index 5e0e9a43..7f0cc8ce 100644 --- a/bin/MangoHud.conf +++ b/bin/MangoHud.conf @@ -38,6 +38,10 @@ gpu_stats # gpu_load_value # gpu_load_color +### Display FPS and frametime +fps +frametime + ### Display loaded MangoHud architecture # arch @@ -145,4 +149,4 @@ background_alpha=0.5 # permit_upload=1 ### Define a '+'-separated list of percentiles shown in the benchmark results. ### Use "AVG" to get a mean average. Default percentiles are 97+AVG+1+0.1 -# benchmark_percentiles= \ No newline at end of file +# benchmark_percentiles= diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 242f6c70..5a350850 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -233,12 +233,14 @@ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_fps]){ ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("FPS"); ImGui::PopFont(); - ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.1f", 1000 / HUDElements.sw_stats->fps); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::Text("ms"); - ImGui::PopFont(); + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_frametime]){ + ImGui::TableNextCell(); + right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.1f", 1000 / HUDElements.sw_stats->fps); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("ms"); + ImGui::PopFont(); + } } } diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 1db0f7ce..e0190ca1 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -500,6 +500,7 @@ parse_overlay_config(struct overlay_params *params, params->enabled[OVERLAY_PARAM_ENABLED_gpu_load_change] = false; params->enabled[OVERLAY_PARAM_ENABLED_cpu_load_change] = false; params->enabled[OVERLAY_PARAM_ENABLED_legacy_layout] = true; + params->enabled[OVERLAY_PARAM_ENABLED_frametime] = true; params->fps_sampling_period = 500000; /* 500ms */ params->width = 0; params->height = 140; diff --git a/src/overlay_params.h b/src/overlay_params.h index 314ad188..b9e2cc7f 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -56,6 +56,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_BOOL(graphs) \ OVERLAY_PARAM_BOOL(legacy_layout) \ OVERLAY_PARAM_BOOL(cpu_mhz) \ + OVERLAY_PARAM_BOOL(frametime) \ OVERLAY_PARAM_CUSTOM(fps_sampling_period) \ OVERLAY_PARAM_CUSTOM(output_folder) \ OVERLAY_PARAM_CUSTOM(output_file) \ From 7e93453a77e186e921b836fba74f2978471ac90f Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Tue, 17 Nov 2020 14:31:45 +0100 Subject: [PATCH 103/130] Changed fps_limit's delimiter to + --- src/overlay_params.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 1db0f7ce..214719c3 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -124,7 +124,7 @@ parse_fps_limit(const char *str) std::stringstream fps_limit_strings(str); std::string value; - while (std::getline(fps_limit_strings, value, ',')) { + while (std::getline(fps_limit_strings, value, '+')) { trim(value); uint32_t as_int; From 44d5546ba51664fd732adf0b97a772d5c80915b1 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Tue, 17 Nov 2020 15:09:15 +0100 Subject: [PATCH 104/130] Add param table_columns --- README.md | 1 + bin/MangoHud.conf | 1 + src/overlay_params.cpp | 4 +++- src/overlay_params.h | 3 ++- src/vulkan.cpp | 2 +- 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f242e171..b983248a 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `cpu_load_value` | Set the values for medium and high load e.g `cpu_load_value=50,90` | | `cellpadding_y` | Set the vertical cellpadding, default is `-0.085` | | `frametime` | Display frametime next to fps text | +| `table_columns` | Set the number of table columns for ImGui, defaults to 3 | Example: `MANGOHUD_CONFIG=cpu_temp,gpu_temp,position=top-right,height=500,font_size=32` diff --git a/bin/MangoHud.conf b/bin/MangoHud.conf index 85749fa7..390ab594 100644 --- a/bin/MangoHud.conf +++ b/bin/MangoHud.conf @@ -104,6 +104,7 @@ position=top-left ### Hud dimensions # width= # height= +# table_columns ### Hud transparency / alpha background_alpha=0.5 diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index bef2370f..e9af1d2d 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -345,6 +345,7 @@ parse_font_glyph_ranges(const char *str) #define parse_permit_upload(s) parse_unsigned(s) #define parse_no_small_font(s) parse_unsigned(s) != 0 #define parse_cellpadding_y(s) parse_float(s) +#define parse_table_columns(s) parse_unsigned(s) #define parse_cpu_color(s) parse_color(s) #define parse_gpu_color(s) parse_color(s) @@ -643,7 +644,8 @@ parse_overlay_config(struct overlay_params *params, 255); } - params->tableCols = 3; + if (!params->table_columns) + params->table_columns = 3; if (!params->font_size) { params->font_size = 24; diff --git a/src/overlay_params.h b/src/overlay_params.h index ef2ff41e..8904a434 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -116,6 +116,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(gpu_load_color) \ OVERLAY_PARAM_CUSTOM(cpu_load_color) \ OVERLAY_PARAM_CUSTOM(cellpadding_y) \ + OVERLAY_PARAM_CUSTOM(table_columns) \ enum overlay_param_position { LAYER_POSITION_TOP_LEFT, @@ -179,7 +180,7 @@ struct overlay_params { std::vector gpu_load_value; std::vector cpu_load_value; unsigned media_player_color; - unsigned tableCols; + unsigned table_columns; bool no_small_font; float font_size, font_scale; float font_size_text; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 503dda9e..11ea2966 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -953,7 +953,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if (!params.no_display){ ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); - ImGui::BeginTable("hud", params.tableCols, ImGuiTableFlags_NoClipX); + ImGui::BeginTable("hud", params.table_columns, ImGuiTableFlags_NoClipX); HUDElements.place = 0; for (auto& func : HUDElements.ordered_functions){ func.first(); From 1e8487c991501b42cb3fea296887571b2d15bfca Mon Sep 17 00:00:00 2001 From: jackun Date: Tue, 17 Nov 2020 20:23:33 +0200 Subject: [PATCH 105/130] Move color conversion to HudElements; move some overlay related functions back to overlay.cpp --- src/gl/imgui_hud.cpp | 4 +- src/hud_elements.cpp | 313 ++++++++++++++++++++++------------- src/hud_elements.h | 23 +++ src/overlay.cpp | 288 +++++++++++++++++++++++++++++++- src/overlay.h | 22 +-- src/overlay_params.cpp | 12 +- src/vulkan.cpp | 367 +---------------------------------------- 7 files changed, 528 insertions(+), 501 deletions(-) diff --git a/src/gl/imgui_hud.cpp b/src/gl/imgui_hud.cpp index 4ada82de..c6a4ac43 100644 --- a/src/gl/imgui_hud.cpp +++ b/src/gl/imgui_hud.cpp @@ -117,7 +117,7 @@ void imgui_create(void *ctx) // Setup Dear ImGui style ImGui::StyleColorsDark(); //ImGui::StyleColorsClassic(); - convert_colors(false, sw_stats, params); + HUDElements.convert_colors(false, params); glGetIntegerv (GL_VIEWPORT, last_vp.v); glGetIntegerv (GL_SCISSOR_BOX, last_sb.v); @@ -175,6 +175,8 @@ void imgui_render(unsigned int width, unsigned int height) ImGuiContext *saved_ctx = ImGui::GetCurrentContext(); ImGui::SetCurrentContext(state.imgui_ctx); ImGui::GetIO().DisplaySize = ImVec2(width, height); + if (HUDElements.colors.update) + HUDElements.convert_colors(params); ImGui_ImplOpenGL3_NewFrame(); ImGui::NewFrame(); diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 1142ea27..5f0c492a 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -1,9 +1,90 @@ #include +#include #include "hud_elements.h" #include "cpu.h" #include "memory.h" #include "mesa/util/macros.h" +// Cut from https://github.com/ocornut/imgui/pull/2943 +// Probably move to ImGui +float SRGBToLinear(float in) +{ + if (in <= 0.04045f) + return in / 12.92f; + else + return powf((in + 0.055f) / 1.055f, 2.4f); +} + +float LinearToSRGB(float in) +{ + if (in <= 0.0031308f) + return in * 12.92f; + else + return 1.055f * powf(in, 1.0f / 2.4f) - 0.055f; +} + +ImVec4 SRGBToLinear(ImVec4 col) +{ + col.x = SRGBToLinear(col.x); + col.y = SRGBToLinear(col.y); + col.z = SRGBToLinear(col.z); + // Alpha component is already linear + + return col; +} + +ImVec4 LinearToSRGB(ImVec4 col) +{ + col.x = LinearToSRGB(col.x); + col.y = LinearToSRGB(col.y); + col.z = LinearToSRGB(col.z); + // Alpha component is already linear + + return col; +} + +void HudElements::convert_colors(struct overlay_params& params) +{ + HUDElements.colors.update = false; + auto convert = [](unsigned color) -> ImVec4 { + ImVec4 fc = ImGui::ColorConvertU32ToFloat4(color); + if (HUDElements.colors.convert) + return SRGBToLinear(fc); + return fc; + }; + + HUDElements.colors.cpu = convert(params.cpu_color); + HUDElements.colors.gpu = convert(params.gpu_color); + HUDElements.colors.vram = convert(params.vram_color); + HUDElements.colors.ram = convert(params.ram_color); + HUDElements.colors.engine = convert(params.engine_color); + HUDElements.colors.io = convert(params.io_color); + HUDElements.colors.frametime = convert(params.frametime_color); + HUDElements.colors.background = convert(params.background_color); + HUDElements.colors.text = convert(params.text_color); + HUDElements.colors.media_player = convert(params.media_player_color); + HUDElements.colors.wine = convert(params.wine_color); + HUDElements.colors.gpu_load_high = convert(params.gpu_load_color[0]); + HUDElements.colors.gpu_load_med = convert(params.gpu_load_color[1]); + HUDElements.colors.gpu_load_low = convert(params.gpu_load_color[2]); + HUDElements.colors.cpu_load_high = convert(params.cpu_load_color[0]); + HUDElements.colors.cpu_load_med = convert(params.cpu_load_color[1]); + HUDElements.colors.cpu_load_low = convert(params.cpu_load_color[2]); + + ImGuiStyle& style = ImGui::GetStyle(); + style.Colors[ImGuiCol_PlotLines] = convert(params.frametime_color); + style.Colors[ImGuiCol_PlotHistogram] = convert(params.frametime_color); + style.Colors[ImGuiCol_WindowBg] = convert(params.background_color); + style.Colors[ImGuiCol_Text] = convert(params.text_color); + style.CellPadding.y = params.cellpadding_y * real_font_size.y; +} + +void HudElements::convert_colors(bool do_conv, struct overlay_params& params) +{ + HUDElements.colors.convert = do_conv; + convert_colors(params); +} + void HudElements::time(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_time]){ ImGui::TableNextRow(); @@ -23,56 +104,56 @@ void HudElements::gpu_stats(){ ImGui::TableNextRow(); const char* gpu_text; if (HUDElements.params->gpu_text.empty()) - gpu_text = "GPU"; + gpu_text = "GPU"; else - gpu_text = HUDElements.params->gpu_text.c_str(); - ImGui::TextColored(HUDElements.sw_stats->colors.gpu, "%s", gpu_text); + gpu_text = HUDElements.params->gpu_text.c_str(); + ImGui::TextColored(HUDElements.colors.gpu, "%s", gpu_text); ImGui::TableNextCell(); - auto text_color = HUDElements.sw_stats->colors.text; + auto text_color = HUDElements.colors.text; if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){ - struct LOAD_DATA gpu_data = {HUDElements.sw_stats->colors.gpu_load_high, - HUDElements.sw_stats->colors.gpu_load_med, - HUDElements.sw_stats->colors.gpu_load_low, - HUDElements.params->gpu_load_value[0], - HUDElements.params->gpu_load_value[1] - }; - - - auto load_color = change_on_load_temp(gpu_data, gpu_info.load); - right_aligned_text(load_color, HUDElements.ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(load_color,"%%"); + struct LOAD_DATA gpu_data = { + HUDElements.colors.gpu_load_high, + HUDElements.colors.gpu_load_med, + HUDElements.colors.gpu_load_low, + HUDElements.params->gpu_load_value[0], + HUDElements.params->gpu_load_value[1] + }; + + auto load_color = change_on_load_temp(gpu_data, gpu_info.load); + right_aligned_text(load_color, HUDElements.ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(load_color,"%%"); } else { - right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(text_color,"%%"); - // ImGui::SameLine(150); - // ImGui::Text("%s", "%"); + right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(text_color,"%%"); + // ImGui::SameLine(150); + // ImGui::Text("%s", "%"); } if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_temp]){ - ImGui::TableNextCell(); - right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.temp); - ImGui::SameLine(0, 1.0f); - ImGui::Text("°C"); + ImGui::TableNextCell(); + right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.temp); + ImGui::SameLine(0, 1.0f); + ImGui::Text("°C"); } if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock] || HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_power]) - ImGui::TableNextRow(); + ImGui::TableNextRow(); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock]){ - ImGui::TableNextCell(); - right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.CoreClock); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::Text("MHz"); - ImGui::PopFont(); + ImGui::TableNextCell(); + right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.CoreClock); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("MHz"); + ImGui::PopFont(); } if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_power]) { - ImGui::TableNextCell(); - right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.powerUsage); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::Text("W"); - ImGui::PopFont(); + ImGui::TableNextCell(); + right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.powerUsage); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("W"); + ImGui::PopFont(); } } } @@ -82,22 +163,23 @@ void HudElements::cpu_stats(){ ImGui::TableNextRow(); const char* cpu_text; if (HUDElements.params->cpu_text.empty()) - cpu_text = "CPU"; + cpu_text = "CPU"; else - cpu_text = HUDElements.params->cpu_text.c_str(); - ImGui::TextColored(HUDElements.sw_stats->colors.cpu, "%s", cpu_text); + cpu_text = HUDElements.params->cpu_text.c_str(); + + ImGui::TextColored(HUDElements.colors.cpu, "%s", cpu_text); ImGui::TableNextCell(); - auto text_color = HUDElements.sw_stats->colors.text; + auto text_color = HUDElements.colors.text; if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_load_change]){ int cpu_load_percent = int(cpuStats.GetCPUDataTotal().percent); - struct LOAD_DATA cpu_data = {HUDElements.sw_stats->colors.cpu_load_high, - HUDElements.sw_stats->colors.cpu_load_med, - HUDElements.sw_stats->colors.cpu_load_low, - HUDElements.params->cpu_load_value[0], - HUDElements.params->cpu_load_value[1] - }; - - + struct LOAD_DATA cpu_data = { + HUDElements.colors.cpu_load_high, + HUDElements.colors.cpu_load_med, + HUDElements.colors.cpu_load_low, + HUDElements.params->cpu_load_value[0], + HUDElements.params->cpu_load_value[1] + }; + auto load_color = change_on_load_temp(cpu_data, cpu_load_percent); right_aligned_text(load_color, HUDElements.ralign_width, "%d", cpu_load_percent); ImGui::SameLine(0, 1.0f); @@ -111,7 +193,7 @@ void HudElements::cpu_stats(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_temp]){ ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); ImGui::SameLine(0, 1.0f); ImGui::Text("°C"); } @@ -119,7 +201,7 @@ void HudElements::cpu_stats(){ ImGui::TableNextRow(); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_mhz]){ ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().cpu_mhz); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().cpu_mhz); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("MHz"); @@ -127,7 +209,7 @@ void HudElements::cpu_stats(){ } if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_power]){ ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().power); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().power); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("W"); @@ -142,17 +224,17 @@ void HudElements::core_load(){ for (const CPUData &cpuData : cpuStats.GetCPUData()) { ImGui::TableNextRow(); - ImGui::TextColored(HUDElements.sw_stats->colors.cpu, "CPU"); + ImGui::TextColored(HUDElements.colors.cpu, "CPU"); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.cpu,"%i", i); + ImGui::TextColored(HUDElements.colors.cpu,"%i", i); ImGui::PopFont(); ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", int(cpuData.percent)); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", int(cpuData.percent)); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuData.mhz); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", cpuData.mhz); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("MHz"); @@ -166,29 +248,29 @@ void HudElements::io_stats(){ auto sampling = HUDElements.params->fps_sampling_period; ImGui::TableNextRow(); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read] && !HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]) - ImGui::TextColored(HUDElements.sw_stats->colors.io, "IO RD"); + ImGui::TextColored(HUDElements.colors.io, "IO RD"); else if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read] && HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]) - ImGui::TextColored(HUDElements.sw_stats->colors.io, "IO RW"); + ImGui::TextColored(HUDElements.colors.io, "IO RW"); else if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write] && !HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read]) - ImGui::TextColored(HUDElements.sw_stats->colors.io, "IO WR"); + ImGui::TextColored(HUDElements.colors.io, "IO WR"); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read]){ - ImGui::TableNextCell(); - float val = HUDElements.sw_stats->io.diff.read * 1000000 / sampling; - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, val < 100 ? "%.1f" : "%.f", val); - ImGui::SameLine(0,1.0f); - ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::Text("MiB/s"); - ImGui::PopFont(); + ImGui::TableNextCell(); + float val = HUDElements.sw_stats->io.diff.read * 1000000 / sampling; + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, val < 100 ? "%.1f" : "%.f", val); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("MiB/s"); + ImGui::PopFont(); } if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]){ - ImGui::TableNextCell(); - float val = HUDElements.sw_stats->io.diff.write * 1000000 / sampling; - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, val < 100 ? "%.1f" : "%.f", val); - ImGui::SameLine(0,1.0f); - ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::Text("MiB/s"); - ImGui::PopFont(); + ImGui::TableNextCell(); + float val = HUDElements.sw_stats->io.diff.write * 1000000 / sampling; + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, val < 100 ? "%.1f" : "%.f", val); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("MiB/s"); + ImGui::PopFont(); } } } @@ -196,16 +278,16 @@ void HudElements::io_stats(){ void HudElements::vram(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_vram]){ ImGui::TableNextRow(); - ImGui::TextColored(HUDElements.sw_stats->colors.vram, "VRAM"); + ImGui::TextColored(HUDElements.colors.vram, "VRAM"); ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.1f", gpu_info.memoryUsed); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.1f", gpu_info.memoryUsed); ImGui::SameLine(0,1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("GiB"); ImGui::PopFont(); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_mem_clock]){ ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", gpu_info.MemClock); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", gpu_info.MemClock); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("MHz"); @@ -214,12 +296,12 @@ void HudElements::vram(){ } } void HudElements::ram(){ -#ifdef __gnu_linux__ +#ifdef __gnu_linux__ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_ram]){ ImGui::TableNextRow(); - ImGui::TextColored(HUDElements.sw_stats->colors.ram, "RAM"); + ImGui::TextColored(HUDElements.colors.ram, "RAM"); ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.1f", memused); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.1f", memused); ImGui::SameLine(0,1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("GiB"); @@ -232,18 +314,18 @@ void HudElements::fps(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_fps]){ ImGui::TableNextRow(); if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_fps] && HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_engine_version]){ - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", HUDElements.is_vulkan ? HUDElements.sw_stats->engineName.c_str() : "OpenGL"); + ImGui::TextColored(HUDElements.colors.engine, "%s", HUDElements.is_vulkan ? HUDElements.sw_stats->engineName.c_str() : "OpenGL"); } - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", HUDElements.is_vulkan ? HUDElements.sw_stats->engineName.c_str() : "OpenGL"); + ImGui::TextColored(HUDElements.colors.engine, "%s", HUDElements.is_vulkan ? HUDElements.sw_stats->engineName.c_str() : "OpenGL"); ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.0f", HUDElements.sw_stats->fps); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.0f", HUDElements.sw_stats->fps); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("FPS"); ImGui::PopFont(); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_frametime]){ ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.1f", 1000 / HUDElements.sw_stats->fps); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.1f", 1000 / HUDElements.sw_stats->fps); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("ms"); @@ -256,33 +338,34 @@ void HudElements::gpu_name(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_name] && !HUDElements.sw_stats->gpuName.empty()){ ImGui::TableNextRow(); ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, + ImGui::TextColored(HUDElements.colors.engine, "%s", HUDElements.sw_stats->gpuName.c_str()); ImGui::PopFont(); } } + void HudElements::engine_version(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_engine_version]){ ImGui::TableNextRow(); ImGui::PushFont(HUDElements.sw_stats->font1); if (HUDElements.is_vulkan) { if ((HUDElements.sw_stats->engineName == "DXVK" || HUDElements.sw_stats->engineName == "VKD3D")){ - ImGui::TextColored(HUDElements.sw_stats->colors.engine, + ImGui::TextColored(HUDElements.colors.engine, "%s/%d.%d.%d", HUDElements.sw_stats->engineVersion.c_str(), HUDElements.sw_stats->version_vk.major, HUDElements.sw_stats->version_vk.minor, HUDElements.sw_stats->version_vk.patch); } else { - ImGui::TextColored(HUDElements.sw_stats->colors.engine, + ImGui::TextColored(HUDElements.colors.engine, "%d.%d.%d", HUDElements.sw_stats->version_vk.major, HUDElements.sw_stats->version_vk.minor, HUDElements.sw_stats->version_vk.patch); } } else { - ImGui::TextColored(HUDElements.sw_stats->colors.engine, - "%d.%d%s", HUDElements.sw_stats->version_gl.major, HUDElements.sw_stats->version_gl.minor, - HUDElements.sw_stats->version_gl.is_gles ? " ES" : ""); + ImGui::TextColored(HUDElements.colors.engine, + "%d.%d%s", HUDElements.sw_stats->version_gl.major, HUDElements.sw_stats->version_gl.minor, + HUDElements.sw_stats->version_gl.is_gles ? " ES" : ""); } ImGui::PopFont(); } @@ -292,7 +375,7 @@ void HudElements::vulkan_driver(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_vulkan_driver] && !HUDElements.sw_stats->driverName.empty()){ ImGui::TableNextRow(); ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, + ImGui::TextColored(HUDElements.colors.engine, "%s", HUDElements.sw_stats->driverName.c_str()); ImGui::PopFont(); } @@ -302,7 +385,7 @@ void HudElements::arch(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_arch]){ ImGui::TableNextRow(); ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "" MANGOHUD_ARCH); + ImGui::TextColored(HUDElements.colors.engine, "%s", "" MANGOHUD_ARCH); ImGui::PopFont(); } } @@ -312,7 +395,7 @@ void HudElements::wine(){ ImGui::TableNextRow(); if (!wineVersion.empty()){ ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.wine, "%s", wineVersion.c_str()); + ImGui::TextColored(HUDElements.colors.wine, "%s", wineVersion.c_str()); ImGui::PopFont(); } } @@ -323,7 +406,7 @@ void HudElements::frame_timing(){ ImGui::TableNextRow(); ImGui::Dummy(ImVec2(0.0f, real_font_size.y)); ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "Frametime"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "Frametime"); ImGui::PopFont(); ImGui::TableNextRow(); char hash[40]; @@ -334,20 +417,20 @@ void HudElements::frame_timing(){ double min_time = 0.0f; double max_time = 50.0f; if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_histogram]){ - ImGui::PlotHistogram(hash, get_time_stat, HUDElements.sw_stats, + ImGui::PlotHistogram(hash, get_time_stat, HUDElements.sw_stats, ARRAY_SIZE(HUDElements.sw_stats->frames_stats), 0, NULL, min_time, max_time, ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); } else { - ImGui::PlotLines(hash, get_time_stat, HUDElements.sw_stats, - ARRAY_SIZE(HUDElements.sw_stats->frames_stats), 0, - NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); + ImGui::PlotLines(hash, get_time_stat, HUDElements.sw_stats, + ARRAY_SIZE(HUDElements.sw_stats->frames_stats), 0, + NULL, min_time, max_time, + ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); } ImGui::PopStyleColor(); ImGui::SameLine(0,1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::Text("%.1f ms", 1000 / HUDElements.sw_stats->fps); //frame_timing / 1000.f); + ImGui::Text("%.1f ms", 1000 / HUDElements.sw_stats->fps); ImGui::PopFont(); } } @@ -378,6 +461,7 @@ void HudElements::graphs(){ { arr.push_back(0); } + if (value == "cpu_load"){ for (auto& it : graph_data){ arr.push_back(float(it.cpu_load)); @@ -385,7 +469,7 @@ void HudElements::graphs(){ } HUDElements.max = 100; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "CPU Load"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "CPU Load"); ImGui::PopFont(); } @@ -396,7 +480,7 @@ void HudElements::graphs(){ } HUDElements.max = 100; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "GPU Load"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Load"); ImGui::PopFont(); } @@ -409,10 +493,11 @@ void HudElements::graphs(){ } if (int(arr.back()) > HUDElements.cpu_temp_max) HUDElements.cpu_temp_max = arr.back(); + HUDElements.max = HUDElements.cpu_temp_max; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "CPU Temp"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "CPU Temp"); ImGui::PopFont(); } @@ -425,13 +510,14 @@ void HudElements::graphs(){ } if (int(arr.back()) > HUDElements.gpu_temp_max) HUDElements.gpu_temp_max = arr.back(); + HUDElements.max = HUDElements.gpu_temp_max; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "GPU Temp"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Temp"); ImGui::PopFont(); } - + if (value == "gpu_core_clock"){ for (auto& it : graph_data){ arr.push_back(float(it.gpu_core_clock)); @@ -439,10 +525,11 @@ void HudElements::graphs(){ } if (int(arr.back()) > HUDElements.gpu_core_max) HUDElements.gpu_core_max = arr.back(); + HUDElements.max = HUDElements.gpu_core_max; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "GPU Core Clock"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Core Clock"); ImGui::PopFont(); } @@ -453,22 +540,24 @@ void HudElements::graphs(){ } if (int(arr.back()) > HUDElements.gpu_mem_max) HUDElements.gpu_mem_max = arr.back(); + HUDElements.max = HUDElements.gpu_mem_max; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "GPU Mem Clock"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Mem Clock"); ImGui::PopFont(); } - + if (value == "vram"){ for (auto& it : graph_data){ arr.push_back(float(it.gpu_vram_used)); arr.erase(arr.begin()); } + HUDElements.max = gpu_info.memoryTotal; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "VRAM"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "VRAM"); ImGui::PopFont(); } @@ -479,12 +568,14 @@ void HudElements::graphs(){ arr.push_back(float(it.ram_used)); arr.erase(arr.begin()); } + HUDElements.max = memmax; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "RAM"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "RAM"); ImGui::PopFont(); } + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); ImGui::TableNextRow(); if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_histogram]){ @@ -518,7 +609,7 @@ void HudElements::sort_elements(std::pair option){ if (param == "engine_version") { ordered_functions.push_back({engine_version, value}); } if (param == "gpu_name") { ordered_functions.push_back({gpu_name, value}); } if (param == "vulkan_driver") { ordered_functions.push_back({vulkan_driver, value}); } - if (param == "arch") { ordered_functions.push_back({arch, value}); } + if (param == "arch") { ordered_functions.push_back({arch, value}); } if (param == "wine") { ordered_functions.push_back({wine, value}); } if (param == "frame_timing") { ordered_functions.push_back({frame_timing, value}); } if (param == "media_player") { ordered_functions.push_back({media_player, value}); } diff --git a/src/hud_elements.h b/src/hud_elements.h index c1ebc64b..026221de 100644 --- a/src/hud_elements.h +++ b/src/hud_elements.h @@ -39,6 +39,29 @@ class HudElements{ static void frame_timing(); static void media_player(); static void graphs(); + + void convert_colors(struct overlay_params& params); + void convert_colors(bool do_conv, struct overlay_params& params); + struct hud_colors { + bool convert, update; + ImVec4 cpu, + gpu, + vram, + ram, + engine, + io, + frametime, + background, + text, + media_player, + wine, + gpu_load_high, + gpu_load_med, + gpu_load_low, + cpu_load_high, + cpu_load_med, + cpu_load_low; + } colors {}; }; extern HudElements HUDElements; diff --git a/src/overlay.cpp b/src/overlay.cpp index 08db33f0..ea449ef3 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include "overlay.h" #include "logging.h" @@ -10,7 +9,11 @@ #include "timing.hpp" #include "mesa/util/macros.h" #include "string_utils.h" +#ifdef HAVE_DBUS +float g_overflow = 50.f /* 3333ms * 0.5 / 16.6667 / 2 (to edge and back) */; +#endif +bool open = false; struct benchmark_stats benchmark; struct fps_limit fps_limit_stats {}; ImVec2 real_font_size; @@ -144,3 +147,286 @@ void calculate_benchmark_data(void *params_void){ entry.first.append(max_label_size - entry.first.length(), ' '); } } + + +float get_time_stat(void *_data, int _idx) +{ + struct swapchain_stats *data = (struct swapchain_stats *) _data; + if ((ARRAY_SIZE(data->frames_stats) - _idx) > data->n_frames) + return 0.0f; + int idx = ARRAY_SIZE(data->frames_stats) + + data->n_frames < ARRAY_SIZE(data->frames_stats) ? + _idx - data->n_frames : + _idx + data->n_frames; + idx %= ARRAY_SIZE(data->frames_stats); + /* Time stats are in us. */ + return data->frames_stats[idx].stats[data->stat_selector] / data->time_dividor; +} + +void position_layer(struct swapchain_stats& data, struct overlay_params& params, ImVec2 window_size) +{ + unsigned width = ImGui::GetIO().DisplaySize.x; + unsigned height = ImGui::GetIO().DisplaySize.y; + float margin = 10.0f; + if (params.offset_x > 0 || params.offset_y > 0) + margin = 0.0f; + + ImGui::SetNextWindowBgAlpha(params.background_alpha); + ImGui::SetNextWindowSize(window_size, ImGuiCond_Always); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8,-3)); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, params.alpha); + switch (params.position) { + case LAYER_POSITION_TOP_LEFT: + data.main_window_pos = ImVec2(margin + params.offset_x, margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + case LAYER_POSITION_TOP_RIGHT: + data.main_window_pos = ImVec2(width - window_size.x - margin + params.offset_x, margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + case LAYER_POSITION_BOTTOM_LEFT: + data.main_window_pos = ImVec2(margin + params.offset_x, height - window_size.y - margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + case LAYER_POSITION_BOTTOM_RIGHT: + data.main_window_pos = ImVec2(width - window_size.x - margin + params.offset_x, height - window_size.y - margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + case LAYER_POSITION_TOP_CENTER: + data.main_window_pos = ImVec2((width / 2) - (window_size.x / 2), margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + } +} + +void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...) +{ + ImVec2 pos = ImGui::GetCursorPos(); + char buffer[32] {}; + + va_list args; + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + + ImVec2 sz = ImGui::CalcTextSize(buffer); + ImGui::SetCursorPosX(pos.x + off_x - sz.x); + //ImGui::Text("%s", buffer); + ImGui::TextColored(col,"%s",buffer); +} + +float get_ticker_limited_pos(float pos, float tw, float& left_limit, float& right_limit) +{ + //float cw = ImGui::GetContentRegionAvailWidth() * 3; // only table cell worth of width + float cw = ImGui::GetWindowContentRegionMax().x - ImGui::GetStyle().WindowPadding.x; + float new_pos_x = ImGui::GetCursorPosX(); + left_limit = cw - tw + new_pos_x; + right_limit = new_pos_x; + + if (cw < tw) { + new_pos_x += pos; + // acts as a delay before it starts scrolling again + if (new_pos_x < left_limit) + return left_limit; + else if (new_pos_x > right_limit) + return right_limit; + else + return new_pos_x; + } + return new_pos_x; +} + +#ifdef HAVE_DBUS +void render_mpris_metadata(struct overlay_params& params, mutexed_metadata& meta, uint64_t frame_timing, bool is_main) +{ + if (meta.meta.valid) { + auto color = ImGui::ColorConvertU32ToFloat4(params.media_player_color); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8,0)); + ImGui::Dummy(ImVec2(0.0f, 20.0f)); + //ImGui::PushFont(data.font1); + + if (meta.ticker.needs_recalc) { + meta.ticker.tw0 = ImGui::CalcTextSize(meta.meta.title.c_str()).x; + meta.ticker.tw1 = ImGui::CalcTextSize(meta.meta.artists.c_str()).x; + meta.ticker.tw2 = ImGui::CalcTextSize(meta.meta.album.c_str()).x; + meta.ticker.longest = std::max(std::max( + meta.ticker.tw0, + meta.ticker.tw1), + meta.ticker.tw2); + meta.ticker.needs_recalc = false; + } + + float new_pos, left_limit = 0, right_limit = 0; + get_ticker_limited_pos(meta.ticker.pos, meta.ticker.longest, left_limit, right_limit); + + if (meta.ticker.pos < left_limit - g_overflow * .5f) { + meta.ticker.dir = -1; + meta.ticker.pos = (left_limit - g_overflow * .5f) + 1.f /* random */; + } else if (meta.ticker.pos > right_limit + g_overflow) { + meta.ticker.dir = 1; + meta.ticker.pos = (right_limit + g_overflow) - 1.f /* random */; + } + + meta.ticker.pos -= .5f * (frame_timing / 16666.7f) * meta.ticker.dir; + + for (auto order : params.media_player_order) { + switch (order) { + case MP_ORDER_TITLE: + { + new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw0, left_limit, right_limit); + ImGui::SetCursorPosX(new_pos); + ImGui::TextColored(color, "%s", meta.meta.title.c_str()); + } + break; + case MP_ORDER_ARTIST: + { + new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw1, left_limit, right_limit); + ImGui::SetCursorPosX(new_pos); + ImGui::TextColored(color, "%s", meta.meta.artists.c_str()); + } + break; + case MP_ORDER_ALBUM: + { + //ImGui::NewLine(); + if (!meta.meta.album.empty()) { + new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw2, left_limit, right_limit); + ImGui::SetCursorPosX(new_pos); + ImGui::TextColored(color, "%s", meta.meta.album.c_str()); + } + } + break; + default: break; + } + } + + if (!meta.meta.playing) { + ImGui::TextColored(color, "(paused)"); + } + + //ImGui::PopFont(); + ImGui::PopStyleVar(); + } +} +#endif + +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 = (2 + benchmark.percentile_data.size()) * real_font_size.x + 10.0f + 58; + ImGui::SetNextWindowSize(ImVec2(window_size.x, benchHeight), ImGuiCond_Always); + if (height - (window_size.y + data.main_window_pos.y + 5) < benchHeight) + ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y - benchHeight - 5), ImGuiCond_Always); + else + ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y + window_size.y + 5), ImGuiCond_Always); + + float display_time = std::chrono::duration(now - logger->last_log_end()).count(); + static float display_for = 10.0f; + float alpha; + if(params.background_alpha != 0){ + if (display_for >= display_time){ + alpha = display_time * params.background_alpha; + if (alpha >= params.background_alpha){ + ImGui::SetNextWindowBgAlpha(params.background_alpha); + }else{ + ImGui::SetNextWindowBgAlpha(alpha); + } + } else { + alpha = 6.0 - display_time * params.background_alpha; + if (alpha >= params.background_alpha){ + ImGui::SetNextWindowBgAlpha(params.background_alpha); + }else{ + ImGui::SetNextWindowBgAlpha(alpha); + } + } + } else { + if (display_for >= display_time){ + alpha = display_time * 0.0001; + ImGui::SetNextWindowBgAlpha(params.background_alpha); + } else { + alpha = 6.0 - display_time * 0.0001; + ImGui::SetNextWindowBgAlpha(params.background_alpha); + } + } + ImGui::Begin("Benchmark", &open, ImGuiWindowFlags_NoDecoration); + static const char* finished = "Logging Finished"; + ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(finished).x / 2)); + 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", std::chrono::duration(logger->last_log_end() - logger->last_log_begin()).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.percentile_data){ + char buffer[20]; + snprintf(buffer, sizeof(buffer), "%s %.1f", data_.first.c_str(), data_.second); + ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(buffer).x / 2)); + ImGui::TextColored(ImVec4(1.0, 1.0, 1.0, alpha / params.background_alpha), "%s %.1f", data_.first.c_str(), data_.second); + } + float max = *max_element(benchmark.fps_data.begin(), benchmark.fps_data.end()); + ImVec4 plotColor = HUDElements.colors.frametime; + plotColor.w = alpha / params.background_alpha; + ImGui::PushStyleColor(ImGuiCol_PlotLines, plotColor); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0, 0.0, 0.0, alpha / params.background_alpha)); + ImGui::Dummy(ImVec2(0.0f, 8.0f)); + if (params.enabled[OVERLAY_PARAM_ENABLED_histogram]) + ImGui::PlotHistogram("", benchmark.fps_data.data(), benchmark.fps_data.size(), 0, "", 0.0f, max + 10, ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); + else + ImGui::PlotLines("", benchmark.fps_data.data(), benchmark.fps_data.size(), 0, "", 0.0f, max + 10, ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); + ImGui::PopStyleColor(2); + ImGui::End(); +} + +ImVec4 change_on_load_temp(LOAD_DATA& data, int current) +{ + if (current >= data.high_load){ + return data.color_high; + } + else if (current >= data.med_load){ + float diff = float(current - data.med_load) / float(data.high_load - data.med_load); + float x = (data.color_high.x - data.color_med.x) * diff; + float y = (data.color_high.y - data.color_med.y) * diff; + float z = (data.color_high.z - data.color_med.z) * diff; + return ImVec4(data.color_med.x + x, data.color_med.y + y, data.color_med.z + z, 1.0); + } else { + float diff = float(current) / float(data.med_load); + float x = (data.color_med.x - data.color_low.x) * diff; + float y = (data.color_med.y - data.color_low.y) * diff; + float z = (data.color_med.z - data.color_low.z) * diff; + return ImVec4(data.color_low.x + x, data.color_low.y + y, data.color_low.z + z, 1.0); + } +} + +void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan) +{ + HUDElements.sw_stats = &data; HUDElements.params = ¶ms; + HUDElements.is_vulkan = is_vulkan; + ImGui::GetIO().FontGlobalScale = params.font_scale; + if(not logger) logger = std::make_unique(¶ms); + static float ralign_width = 0, old_scale = 0; + window_size = ImVec2(params.width, params.height); + unsigned height = ImGui::GetIO().DisplaySize.y; + auto now = Clock::now(); + + if (old_scale != params.font_scale) { + HUDElements.ralign_width = ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; + old_scale = params.font_scale; + } + + if (!params.no_display){ + ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); + ImGui::BeginTable("hud", params.table_columns, ImGuiTableFlags_NoClipX); + HUDElements.place = 0; + for (auto& func : HUDElements.ordered_functions){ + func.first(); + HUDElements.place += 1; + } + ImGui::EndTable(); + + if(logger->is_active()) + 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((now - logger->last_log_end()) < 12s) + render_benchmark(data, params, window_size, height, now); + } +} diff --git a/src/overlay.h b/src/overlay.h index b3b5360f..72fd0ac8 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -53,25 +53,6 @@ struct swapchain_stats { std::string deviceName; std::string gpuName; std::string driverName; - struct { - ImVec4 cpu, - gpu, - vram, - ram, - engine, - io, - frametime, - background, - text, - media_player, - wine, - gpu_load_high, - gpu_load_med, - gpu_load_low, - cpu_load_high, - cpu_load_med, - cpu_load_low; - } colors; }; struct fps_limit { @@ -116,9 +97,8 @@ void FpsLimiter(struct fps_limit& stats); void get_device_name(int32_t vendorID, int32_t deviceID, struct swapchain_stats& sw_stats); void calculate_benchmark_data(void *params_void); void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& text_font); -void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overlay_params& params); void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...); -ImVec4 change_on_load_temp (struct LOAD_DATA& data, int current); +ImVec4 change_on_load_temp(LOAD_DATA& data, int current); float get_time_stat(void *_data, int _idx); #ifdef HAVE_DBUS diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index e9af1d2d..a7d10627 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -633,16 +633,15 @@ parse_overlay_config(struct overlay_params *params, ¶ms->cpu_load_color[0], ¶ms->cpu_load_color[1], ¶ms->cpu_load_color[2], - }; for (auto color : colors){ - *color = - IM_COL32(RGBGetRValue(*color), + *color = + IM_COL32(RGBGetRValue(*color), RGBGetGValue(*color), RGBGetBValue(*color), 255); - } + } if (!params->table_columns) params->table_columns = 3; @@ -678,8 +677,10 @@ parse_overlay_config(struct overlay_params *params, main_metadata.meta.valid = false; } #endif + if(!params->output_file.empty()) printf("MANGOHUD: output_file is Deprecated, use output_folder instead\n"); + auto real_size = params->font_size * params->font_scale; real_font_size = ImVec2(real_size, real_size / 2); HUDElements.params = params; @@ -689,4 +690,7 @@ parse_overlay_config(struct overlay_params *params, for (auto& option : HUDElements.options) HUDElements.sort_elements(option); } + + // Needs ImGui context but it is null here for OpenGL so just note it and update somewhere else + HUDElements.colors.update = true; } diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 11ea2966..1358be9b 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -64,11 +63,6 @@ #include "pci_ids.h" #include "timing.hpp" -#ifdef HAVE_DBUS -float g_overflow = 50.f /* 3333ms * 0.5 / 16.6667 / 2 (to edge and back) */; -#endif - -bool open = false; string gpuString,wineVersion,wineProcess; float offset_x, offset_y, hudSpacing; int hudFirstRow, hudSecondRow; @@ -689,293 +683,15 @@ static void snapshot_swapchain_frame(struct swapchain_data *data) // } } -float get_time_stat(void *_data, int _idx) -{ - struct swapchain_stats *data = (struct swapchain_stats *) _data; - if ((ARRAY_SIZE(data->frames_stats) - _idx) > data->n_frames) - return 0.0f; - int idx = ARRAY_SIZE(data->frames_stats) + - data->n_frames < ARRAY_SIZE(data->frames_stats) ? - _idx - data->n_frames : - _idx + data->n_frames; - idx %= ARRAY_SIZE(data->frames_stats); - /* Time stats are in us. */ - return data->frames_stats[idx].stats[data->stat_selector] / data->time_dividor; -} - -void position_layer(struct swapchain_stats& data, struct overlay_params& params, ImVec2 window_size) -{ - unsigned width = ImGui::GetIO().DisplaySize.x; - unsigned height = ImGui::GetIO().DisplaySize.y; - float margin = 10.0f; - if (params.offset_x > 0 || params.offset_y > 0) - margin = 0.0f; - - ImGui::SetNextWindowBgAlpha(params.background_alpha); - ImGui::SetNextWindowSize(window_size, ImGuiCond_Always); - ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8,-3)); - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, params.alpha); - switch (params.position) { - case LAYER_POSITION_TOP_LEFT: - data.main_window_pos = ImVec2(margin + params.offset_x, margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - case LAYER_POSITION_TOP_RIGHT: - data.main_window_pos = ImVec2(width - window_size.x - margin + params.offset_x, margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - case LAYER_POSITION_BOTTOM_LEFT: - data.main_window_pos = ImVec2(margin + params.offset_x, height - window_size.y - margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - case LAYER_POSITION_BOTTOM_RIGHT: - data.main_window_pos = ImVec2(width - window_size.x - margin + params.offset_x, height - window_size.y - margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - case LAYER_POSITION_TOP_CENTER: - data.main_window_pos = ImVec2((width / 2) - (window_size.x / 2), margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - } -} - -void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...) -{ - ImVec2 pos = ImGui::GetCursorPos(); - char buffer[32] {}; - - va_list args; - va_start(args, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, args); - va_end(args); - - ImVec2 sz = ImGui::CalcTextSize(buffer); - ImGui::SetCursorPosX(pos.x + off_x - sz.x); - //ImGui::Text("%s", buffer); - ImGui::TextColored(col,"%s",buffer); -} - -float get_ticker_limited_pos(float pos, float tw, float& left_limit, float& right_limit) -{ - float cw = ImGui::GetContentRegionAvailWidth(); - float new_pos_x = ImGui::GetCursorPosX(); - left_limit = cw - tw + new_pos_x; - right_limit = new_pos_x; - - if (cw < tw) { - new_pos_x += pos; - // acts as a delay before it starts scrolling again - if (new_pos_x < left_limit) - return left_limit; - else if (new_pos_x > right_limit) - return right_limit; - else - return new_pos_x; - } - return new_pos_x; -} - -#ifdef HAVE_DBUS -void render_mpris_metadata(struct overlay_params& params, mutexed_metadata& meta, uint64_t frame_timing, bool is_main) -{ - if (meta.meta.valid) { - auto color = ImGui::ColorConvertU32ToFloat4(params.media_player_color); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8,0)); - ImGui::Dummy(ImVec2(0.0f, 20.0f)); - //ImGui::PushFont(data.font1); - - if (meta.ticker.needs_recalc) { - meta.ticker.tw0 = ImGui::CalcTextSize(meta.meta.title.c_str()).x; - meta.ticker.tw1 = ImGui::CalcTextSize(meta.meta.artists.c_str()).x; - meta.ticker.tw2 = ImGui::CalcTextSize(meta.meta.album.c_str()).x; - meta.ticker.longest = std::max(std::max( - meta.ticker.tw0, - meta.ticker.tw1), - meta.ticker.tw2); - meta.ticker.needs_recalc = false; - } - - float new_pos, left_limit = 0, right_limit = 0; - get_ticker_limited_pos(meta.ticker.pos, meta.ticker.longest, left_limit, right_limit); - - if (meta.ticker.pos < left_limit - g_overflow * .5f) { - meta.ticker.dir = -1; - meta.ticker.pos = (left_limit - g_overflow * .5f) + 1.f /* random */; - } else if (meta.ticker.pos > right_limit + g_overflow) { - meta.ticker.dir = 1; - meta.ticker.pos = (right_limit + g_overflow) - 1.f /* random */; - } - - meta.ticker.pos -= .5f * (frame_timing / 16666.7f) * meta.ticker.dir; - - for (auto order : params.media_player_order) { - switch (order) { - case MP_ORDER_TITLE: - { - new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw0, left_limit, right_limit); - ImGui::SetCursorPosX(new_pos); - ImGui::TextColored(color, "%s", meta.meta.title.c_str()); - } - break; - case MP_ORDER_ARTIST: - { - new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw1, left_limit, right_limit); - ImGui::SetCursorPosX(new_pos); - ImGui::TextColored(color, "%s", meta.meta.artists.c_str()); - } - break; - case MP_ORDER_ALBUM: - { - //ImGui::NewLine(); - if (!meta.meta.album.empty()) { - new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw2, left_limit, right_limit); - ImGui::SetCursorPosX(new_pos); - ImGui::TextColored(color, "%s", meta.meta.album.c_str()); - } - } - break; - default: break; - } - } - - if (!meta.meta.playing) { - ImGui::TextColored(color, "(paused)"); - } - - //ImGui::PopFont(); - ImGui::PopStyleVar(); - } -} -#endif - -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 = (2 + benchmark.percentile_data.size()) * real_font_size.x + 10.0f + 58; - ImGui::SetNextWindowSize(ImVec2(window_size.x, benchHeight), ImGuiCond_Always); - if (height - (window_size.y + data.main_window_pos.y + 5) < benchHeight) - ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y - benchHeight - 5), ImGuiCond_Always); - else - ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y + window_size.y + 5), ImGuiCond_Always); - - float display_time = std::chrono::duration(now - logger->last_log_end()).count(); - static float display_for = 10.0f; - float alpha; - if(params.background_alpha != 0){ - if (display_for >= display_time){ - alpha = display_time * params.background_alpha; - if (alpha >= params.background_alpha){ - ImGui::SetNextWindowBgAlpha(params.background_alpha); - }else{ - ImGui::SetNextWindowBgAlpha(alpha); - } - } else { - alpha = 6.0 - display_time * params.background_alpha; - if (alpha >= params.background_alpha){ - ImGui::SetNextWindowBgAlpha(params.background_alpha); - }else{ - ImGui::SetNextWindowBgAlpha(alpha); - } - } - } else { - if (display_for >= display_time){ - alpha = display_time * 0.0001; - ImGui::SetNextWindowBgAlpha(params.background_alpha); - } else { - alpha = 6.0 - display_time * 0.0001; - ImGui::SetNextWindowBgAlpha(params.background_alpha); - } - } - ImGui::Begin("Benchmark", &open, ImGuiWindowFlags_NoDecoration); - static const char* finished = "Logging Finished"; - ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(finished).x / 2)); - 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", std::chrono::duration(logger->last_log_end() - logger->last_log_begin()).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.percentile_data){ - char buffer[20]; - snprintf(buffer, sizeof(buffer), "%s %.1f", data_.first.c_str(), data_.second); - ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(buffer).x / 2)); - ImGui::TextColored(ImVec4(1.0, 1.0, 1.0, alpha / params.background_alpha), "%s %.1f", data_.first.c_str(), data_.second); - } - float max = *max_element(benchmark.fps_data.begin(), benchmark.fps_data.end()); - ImVec4 plotColor = data.colors.frametime; - plotColor.w = alpha / params.background_alpha; - ImGui::PushStyleColor(ImGuiCol_PlotLines, plotColor); - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0, 0.0, 0.0, alpha / params.background_alpha)); - ImGui::Dummy(ImVec2(0.0f, 8.0f)); - if (params.enabled[OVERLAY_PARAM_ENABLED_histogram]) - ImGui::PlotHistogram("", benchmark.fps_data.data(), benchmark.fps_data.size(), 0, "", 0.0f, max + 10, ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); - else - ImGui::PlotLines("", benchmark.fps_data.data(), benchmark.fps_data.size(), 0, "", 0.0f, max + 10, ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); - ImGui::PopStyleColor(2); - ImGui::End(); -} - - -ImVec4 change_on_load_temp (struct LOAD_DATA& data, int current) { - if (current >= data.high_load){ - return data.color_high; - } - else if (current >= data.med_load){ - float diff = float(current - data.med_load) / float(data.high_load - data.med_load); - float x = (data.color_high.x - data.color_med.x) * diff; - float y = (data.color_high.y - data.color_med.y) * diff; - float z = (data.color_high.z - data.color_med.z) * diff; - return ImVec4(data.color_med.x + x, data.color_med.y + y, data.color_med.z + z, 1.0); - } else { - float diff = float(current) / float(data.med_load); - float x = (data.color_med.x - data.color_low.x) * diff; - float y = (data.color_med.y - data.color_low.y) * diff; - float z = (data.color_med.z - data.color_low.z) * diff; - return ImVec4(data.color_low.x + x, data.color_low.y + y, data.color_low.z + z, 1.0); - } -} - -void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan) -{ - HUDElements.sw_stats = &data; HUDElements.params = ¶ms; - HUDElements.is_vulkan = is_vulkan; - ImGui::GetIO().FontGlobalScale = params.font_scale; - if(not logger) logger = std::make_unique(¶ms); - static float ralign_width = 0, old_scale = 0; - window_size = ImVec2(params.width, params.height); - unsigned height = ImGui::GetIO().DisplaySize.y; - auto now = Clock::now(); - - if (old_scale != params.font_scale) { - HUDElements.ralign_width = ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; - old_scale = params.font_scale; - } - - if (!params.no_display){ - ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); - ImGui::BeginTable("hud", params.table_columns, ImGuiTableFlags_NoClipX); - HUDElements.place = 0; - for (auto& func : HUDElements.ordered_functions){ - func.first(); - HUDElements.place += 1; - } - ImGui::EndTable(); - - if(logger->is_active()) - 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((now - logger->last_log_end()) < 12s) - render_benchmark(data, params, window_size, height, now); - } -} - static void compute_swapchain_display(struct swapchain_data *data) { struct device_data *device_data = data->device; struct instance_data *instance_data = device_data->instance; ImGui::SetCurrentContext(data->imgui_context); + if (HUDElements.colors.update) + HUDElements.convert_colors(instance_data->params); + ImGui::NewFrame(); { scoped_lock lk(instance_data->notifier.mutex); @@ -1712,81 +1428,6 @@ static void setup_swapchain_data_pipeline(struct swapchain_data *data) // update_image_descriptor(data, data->font_image_view[0], data->descriptor_set); } -// Cut from https://github.com/ocornut/imgui/pull/2943 -// Probably move to ImGui -float SRGBToLinear(float in) -{ - if (in <= 0.04045f) - return in / 12.92f; - else - return powf((in + 0.055f) / 1.055f, 2.4f); -} - -float LinearToSRGB(float in) -{ - if (in <= 0.0031308f) - return in * 12.92f; - else - return 1.055f * powf(in, 1.0f / 2.4f) - 0.055f; -} - -ImVec4 SRGBToLinear(ImVec4 col) -{ - col.x = SRGBToLinear(col.x); - col.y = SRGBToLinear(col.y); - col.z = SRGBToLinear(col.z); - // Alpha component is already linear - - return col; -} - -ImVec4 LinearToSRGB(ImVec4 col) -{ - col.x = LinearToSRGB(col.x); - col.y = LinearToSRGB(col.y); - col.z = LinearToSRGB(col.z); - // Alpha component is already linear - - return col; -} - -void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overlay_params& params) -{ - auto convert = [&do_conv](unsigned color) -> ImVec4 { - ImVec4 fc = ImGui::ColorConvertU32ToFloat4(color); - if (do_conv) - return SRGBToLinear(fc); - return fc; - }; - - sw_stats.colors.cpu = convert(params.cpu_color); - sw_stats.colors.gpu = convert(params.gpu_color); - sw_stats.colors.vram = convert(params.vram_color); - sw_stats.colors.ram = convert(params.ram_color); - sw_stats.colors.engine = convert(params.engine_color); - sw_stats.colors.io = convert(params.io_color); - sw_stats.colors.frametime = convert(params.frametime_color); - sw_stats.colors.background = convert(params.background_color); - sw_stats.colors.text = convert(params.text_color); - sw_stats.colors.media_player = convert(params.media_player_color); - sw_stats.colors.wine = convert(params.wine_color); - sw_stats.colors.gpu_load_high = convert(params.gpu_load_color[0]); - sw_stats.colors.gpu_load_med = convert(params.gpu_load_color[1]); - sw_stats.colors.gpu_load_low = convert(params.gpu_load_color[2]); - sw_stats.colors.cpu_load_high = convert(params.cpu_load_color[0]); - sw_stats.colors.cpu_load_med = convert(params.cpu_load_color[1]); - sw_stats.colors.cpu_load_low = convert(params.cpu_load_color[2]); - - - - ImGuiStyle& style = ImGui::GetStyle(); - style.Colors[ImGuiCol_PlotLines] = convert(params.frametime_color); - style.Colors[ImGuiCol_PlotHistogram] = convert(params.frametime_color); - style.Colors[ImGuiCol_WindowBg] = convert(params.background_color); - style.Colors[ImGuiCol_Text] = convert(params.text_color); - style.CellPadding.y = params.cellpadding_y * real_font_size.y; -} - // TODO probably needs colorspace check too static void convert_colors_vk(VkFormat format, struct swapchain_stats& sw_stats, struct overlay_params& params) { @@ -1831,7 +1472,7 @@ static void convert_colors_vk(VkFormat format, struct swapchain_stats& sw_stats, break; } - convert_colors(do_conv, sw_stats, params); + HUDElements.convert_colors(do_conv, params); } static void setup_swapchain_data(struct swapchain_data *data, From 0474c9380033349c3275516c168aae2f6ff8b6e0 Mon Sep 17 00:00:00 2001 From: jackun Date: Tue, 17 Nov 2020 20:25:20 +0200 Subject: [PATCH 106/130] Change `change_on_load_temp`'s `current` param to unsigned --- src/overlay.cpp | 2 +- src/overlay.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlay.cpp b/src/overlay.cpp index ea449ef3..8e1c6806 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -376,7 +376,7 @@ void render_benchmark(swapchain_stats& data, struct overlay_params& params, ImVe ImGui::End(); } -ImVec4 change_on_load_temp(LOAD_DATA& data, int current) +ImVec4 change_on_load_temp(LOAD_DATA& data, unsigned current) { if (current >= data.high_load){ return data.color_high; diff --git a/src/overlay.h b/src/overlay.h index 72fd0ac8..0e2c5c87 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -98,7 +98,7 @@ void get_device_name(int32_t vendorID, int32_t deviceID, struct swapchain_stats& void calculate_benchmark_data(void *params_void); void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& text_font); void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...); -ImVec4 change_on_load_temp(LOAD_DATA& data, int current); +ImVec4 change_on_load_temp(LOAD_DATA& data, unsigned current); float get_time_stat(void *_data, int _idx); #ifdef HAVE_DBUS From 7c80dc53efa95718f1cec9b41814f05af625c2d0 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Sat, 14 Nov 2020 21:58:01 -0800 Subject: [PATCH 107/130] Allow users to add a new item to the blacklist from config file --- README.md | 1 + bin/MangoHud.conf | 3 +++ src/blacklist.cpp | 47 ++++++++++++++++++++++++------------------ src/blacklist.h | 4 +++- src/overlay_params.cpp | 1 + src/overlay_params.h | 2 ++ src/vulkan.cpp | 11 +++++++++- 7 files changed, 47 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index b983248a..a9519f70 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `cellpadding_y` | Set the vertical cellpadding, default is `-0.085` | | `frametime` | Display frametime next to fps text | | `table_columns` | Set the number of table columns for ImGui, defaults to 3 | +| `blacklist` | Add a program to the blacklist. e.g `blacklist=vkcube,WatchDogs2.exe` | Example: `MANGOHUD_CONFIG=cpu_temp,gpu_temp,position=top-right,height=500,font_size=32` diff --git a/bin/MangoHud.conf b/bin/MangoHud.conf index 390ab594..6248c3d1 100644 --- a/bin/MangoHud.conf +++ b/bin/MangoHud.conf @@ -132,6 +132,9 @@ background_alpha=0.5 ### Set to 'domain:bus:slot.function' # pci_dev = 0:0a:0.0 +### Blacklist +#blacklist = + ################## INTERACTION ################# ### Change toggle keybinds for the hud & logging diff --git a/src/blacklist.cpp b/src/blacklist.cpp index 661eb4f8..378d6fcd 100644 --- a/src/blacklist.cpp +++ b/src/blacklist.cpp @@ -22,27 +22,28 @@ static std::string get_proc_name() { return proc_name; } -static bool check_blacklisted() { - static const std::vector blacklist { - "Battle.net.exe", - "BethesdaNetLauncher.exe", - "EpicGamesLauncher.exe", - "IGOProxy.exe", - "IGOProxy64.exe", - "Origin.exe", - "OriginThinSetupInternal.exe", - "steam", - "steamwebhelper", - "gldriverquery", - "vulkandriverquery", - "Steam.exe", - "ffxivlauncher.exe", - "ffxivlauncher64.exe", - "LeagueClient.exe", - "LeagueClientUxRender.exe", - "SocialClubHelper.exe", - }; +static std::vector blacklist { + "Battle.net.exe", + "BethesdaNetLauncher.exe", + "EpicGamesLauncher.exe", + "IGOProxy.exe", + "IGOProxy64.exe", + "Origin.exe", + "OriginThinSetupInternal.exe", + "steam", + "steamwebhelper", + "gldriverquery", + "vulkandriverquery", + "Steam.exe", + "ffxivlauncher.exe", + "ffxivlauncher64.exe", + "LeagueClient.exe", + "LeagueClientUxRender.exe", + "SocialClubHelper.exe", +}; + +static bool check_blacklisted() { std::string proc_name = get_proc_name(); bool blacklisted = std::find(blacklist.begin(), blacklist.end(), proc_name) != blacklist.end(); @@ -59,3 +60,9 @@ bool is_blacklisted(bool force_recheck) { blacklisted = check_blacklisted(); return blacklisted; } + +void add_blacklist(std::string new_item) { + blacklist.push_back (new_item); + is_blacklisted(true); +} + diff --git a/src/blacklist.h b/src/blacklist.h index b4105df3..5f505a2c 100644 --- a/src/blacklist.h +++ b/src/blacklist.h @@ -1,7 +1,9 @@ #pragma once #ifndef MANGOHUD_BLACKLIST_H #define MANGOHUD_BLACKLIST_H - +#include bool is_blacklisted(bool force_recheck = false); +void add_blacklist(std::string); + #endif //MANGOHUD_BLACKLIST_H diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index a7d10627..1ee204cb 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -362,6 +362,7 @@ parse_font_glyph_ranges(const char *str) #define parse_cpu_load_color(s) parse_load_color(s) #define parse_gpu_load_value(s) parse_load_value(s) #define parse_cpu_load_value(s) parse_load_value(s) +#define parse_blacklist(s) parse_str(s) static bool parse_help(const char *str) diff --git a/src/overlay_params.h b/src/overlay_params.h index 8904a434..5666b2b2 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -117,6 +117,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(cpu_load_color) \ OVERLAY_PARAM_CUSTOM(cellpadding_y) \ OVERLAY_PARAM_CUSTOM(table_columns) \ + OVERLAY_PARAM_CUSTOM(blacklist) \ enum overlay_param_position { LAYER_POSITION_TOP_LEFT, @@ -197,6 +198,7 @@ struct overlay_params { std::string pci_dev; std::string media_player_name; std::string cpu_text, gpu_text; + std::string blacklist; unsigned log_interval; std::vector media_player_order; std::vector benchmark_percentiles; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 1358be9b..3dadf2a8 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -2079,8 +2079,17 @@ static VkResult overlay_CreateInstance( &instance_data->vtable); instance_data_map_physical_devices(instance_data, true); + parse_overlay_config(&instance_data->params, getenv("MANGOHUD_CONFIG")); + + //check for blacklist item in the config file + std::stringstream ss(instance_data->params.blacklist); + std::string token; + while (std::getline(ss, token, ',')) { + trim(token); + add_blacklist(token); + } + if (!is_blacklisted()) { - parse_overlay_config(&instance_data->params, getenv("MANGOHUD_CONFIG")); #ifdef __gnu_linux__ instance_data->notifier.params = &instance_data->params; start_notifier(instance_data->notifier); From ef05ab2f2095c605d3c640e8325aa6d9a4c9cdcb Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Wed, 18 Nov 2020 16:19:00 -0800 Subject: [PATCH 108/130] Parse blacklist with parse_str_tokenize --- src/overlay_params.cpp | 16 +++++++++++++++- src/overlay_params.h | 3 ++- src/vulkan.cpp | 7 ++----- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 1ee204cb..b63355d4 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -184,6 +184,20 @@ parse_load_value(const char *str) } +static std::vector +parse_str_tokenize(const char *str) +{ + std::vector data; + std::stringstream ss(str); + std::string token; + while (std::getline(ss, token, ',')) { + trim(token); + data.push_back(token); + } + return data; +} + + static unsigned parse_unsigned(const char *str) { @@ -362,7 +376,7 @@ parse_font_glyph_ranges(const char *str) #define parse_cpu_load_color(s) parse_load_color(s) #define parse_gpu_load_value(s) parse_load_value(s) #define parse_cpu_load_value(s) parse_load_value(s) -#define parse_blacklist(s) parse_str(s) +#define parse_blacklist(s) parse_str_tokenize(s) static bool parse_help(const char *str) diff --git a/src/overlay_params.h b/src/overlay_params.h index 5666b2b2..b2e325b6 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -198,7 +198,8 @@ struct overlay_params { std::string pci_dev; std::string media_player_name; std::string cpu_text, gpu_text; - std::string blacklist; + //std::string blacklist; + std::vector blacklist; unsigned log_interval; std::vector media_player_order; std::vector benchmark_percentiles; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 3dadf2a8..0dbe195c 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -2082,11 +2082,8 @@ static VkResult overlay_CreateInstance( parse_overlay_config(&instance_data->params, getenv("MANGOHUD_CONFIG")); //check for blacklist item in the config file - std::stringstream ss(instance_data->params.blacklist); - std::string token; - while (std::getline(ss, token, ',')) { - trim(token); - add_blacklist(token); + for (auto& item : instance_data->params.blacklist) { + add_blacklist(item); } if (!is_blacklisted()) { From 221c355f15c63a0ea894f149015d81fe0c7d8905 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Wed, 18 Nov 2020 17:05:14 -0800 Subject: [PATCH 109/130] Check if item exits before adding to blacklist --- src/blacklist.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/blacklist.cpp b/src/blacklist.cpp index 378d6fcd..041d0aa3 100644 --- a/src/blacklist.cpp +++ b/src/blacklist.cpp @@ -62,7 +62,13 @@ bool is_blacklisted(bool force_recheck) { } void add_blacklist(std::string new_item) { + // check if item exits in blacklist before adding new item + if(std::find(blacklist.begin(), blacklist.end(), new_item) != blacklist.end()) { + return; + } + blacklist.push_back (new_item); is_blacklisted(true); } + From e4fe24a051745e7a04e30061b42f77cc43387e2e Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Wed, 18 Nov 2020 17:25:11 -0800 Subject: [PATCH 110/130] Use "+" as a delimiter for param blacklist --- README.md | 2 +- src/overlay_params.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a9519f70..97d94c1e 100644 --- a/README.md +++ b/README.md @@ -188,7 +188,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `cellpadding_y` | Set the vertical cellpadding, default is `-0.085` | | `frametime` | Display frametime next to fps text | | `table_columns` | Set the number of table columns for ImGui, defaults to 3 | -| `blacklist` | Add a program to the blacklist. e.g `blacklist=vkcube,WatchDogs2.exe` | +| `blacklist` | Add a program to the blacklist. e.g `blacklist=vkcube+WatchDogs2.exe` | Example: `MANGOHUD_CONFIG=cpu_temp,gpu_temp,position=top-right,height=500,font_size=32` diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index b63355d4..2daa07e0 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -190,7 +190,7 @@ parse_str_tokenize(const char *str) std::vector data; std::stringstream ss(str); std::string token; - while (std::getline(ss, token, ',')) { + while (std::getline(ss, token, '+')) { trim(token); data.push_back(token); } From 6ee6663fb6626b71c5ceaea6c5968a83798f434c Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Tue, 24 Nov 2020 19:48:38 -0800 Subject: [PATCH 111/130] Change delimiter for cpu and gpu load change and color to + --- README.md | 8 ++++---- src/overlay_params.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 97d94c1e..edb4a997 100644 --- a/README.md +++ b/README.md @@ -180,11 +180,11 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `wine_color` | Change color of the wine/proton text | | `cpu_mhz` | Shows the CPUs current MHz | | `gpu_load_change` | Changes the color of the GPU load depending on load | -| `gpu_load_color` | Set the colors for the gpu load change low,medium and high. e.g `gpu_load_color=0000FF,00FFFF,FF00FF` | -| `gpu_load_value` | Set the values for medium and high load e.g `gpu_load_value=50,90` | +| `gpu_load_color` | Set the colors for the gpu load change low,medium and high. e.g `gpu_load_color=0000FF+00FFFF+FF00FF` | +| `gpu_load_value` | Set the values for medium and high load e.g `gpu_load_value=50+90` | | `cpu_load_change` | Changes the color of the CPU load depending on load | -| `cpu_load_color` | Set the colors for the gpu load change low,medium and high. e.g `cpu_load_color=0000FF,00FFFF,FF00FF` | -| `cpu_load_value` | Set the values for medium and high load e.g `cpu_load_value=50,90` | +| `cpu_load_color` | Set the colors for the gpu load change low,medium and high. e.g `cpu_load_color=0000FF+00FFFF+FF00FF` | +| `cpu_load_value` | Set the values for medium and high load e.g `cpu_load_value=50+90` | | `cellpadding_y` | Set the vertical cellpadding, default is `-0.085` | | `frametime` | Display frametime next to fps text | | `table_columns` | Set the number of table columns for ImGui, defaults to 3 | diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 2daa07e0..3db74e9d 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -159,7 +159,7 @@ parse_load_color(const char *str) std::vector load_colors; std::stringstream ss(str); std::string token; - while (std::getline(ss, token, ',')) { + while (std::getline(ss, token, '+')) { trim(token); load_colors.push_back(std::stoi(token, NULL, 16)); } @@ -176,7 +176,7 @@ parse_load_value(const char *str) std::vector load_value; std::stringstream ss(str); std::string token; - while (std::getline(ss, token, ',')) { + while (std::getline(ss, token, '+')) { trim(token); load_value.push_back(std::stoi(token)); } From d855dc6691d9bf0be9d0a455a5187af39299cc76 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Tue, 24 Nov 2020 19:55:47 -0800 Subject: [PATCH 112/130] Also change delimiter for media_player_order to + --- README.md | 2 +- src/overlay_params.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index edb4a997..3f01eb7e 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `vsync`
`gl_vsync` | Set vsync for OpenGL or Vulkan | | `media_player` | Show media player metadata | | `media_player_name` | Force media player DBus service name without the `org.mpris.MediaPlayer2` part, like `spotify`, `vlc`, `audacious` or `cantata`. If none is set, MangoHud tries to switch between currently playing players. | -| `media_player_order` | Media player metadata field order. Defaults to `title,artist,album`. | +| `media_player_order` | Media player metadata field order. Defaults to `title+artist+album`. | | `font_scale_media_player` | Change size of media player text relative to font_size | | `io_read`
`io_write` | Show non-cached IO read/write, in MiB/s | | `pci_dev` | Select GPU device in multi-gpu setups | diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 3db74e9d..269d02a7 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -243,7 +243,7 @@ parse_media_player_order(const char *str) std::vector order; std::stringstream ss(str); std::string token; - while (std::getline(ss, token, ',')) { + while (std::getline(ss, token, '+')) { trim(token); std::transform(token.begin(), token.end(), token.begin(), ::tolower); if (token == "title") From 9124f0f26a0e6b87f6e168ecf31f7f06d08412b2 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Wed, 25 Nov 2020 21:55:17 +0100 Subject: [PATCH 113/130] Let graphs take up full content region --- src/hud_elements.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 5f0c492a..efdf1d37 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -420,12 +420,12 @@ void HudElements::frame_timing(){ ImGui::PlotHistogram(hash, get_time_stat, HUDElements.sw_stats, ARRAY_SIZE(HUDElements.sw_stats->frames_stats), 0, NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); + ImVec2(ImGui::GetContentRegionAvailWidth() * HUDElements.params->table_columns, 50)); } else { ImGui::PlotLines(hash, get_time_stat, HUDElements.sw_stats, ARRAY_SIZE(HUDElements.sw_stats->frames_stats), 0, NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); + ImVec2(ImGui::GetContentRegionAvailWidth() * HUDElements.params->table_columns, 50)); } ImGui::PopStyleColor(); ImGui::SameLine(0,1.0f); @@ -582,12 +582,12 @@ void HudElements::graphs(){ ImGui::PlotLines("", arr.data(), arr.size(), 0, NULL, HUDElements.min, HUDElements.max, - ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); + ImVec2(ImGui::GetContentRegionAvailWidth() * HUDElements.params->table_columns, 50)); } else { ImGui::PlotHistogram("", arr.data(), arr.size(), 0, NULL, HUDElements.min, HUDElements.max, - ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); + ImVec2(ImGui::GetContentRegionAvailWidth() * HUDElements.params->table_columns, 50)); } ImGui::PopStyleColor(1); From f3987ec65c3542047c8581c4456f5a6d3f042471 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Wed, 25 Nov 2020 21:55:30 +0100 Subject: [PATCH 114/130] Move frame_timings ms text to above --- src/hud_elements.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index efdf1d37..b045fcde 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -407,6 +407,10 @@ void HudElements::frame_timing(){ ImGui::Dummy(ImVec2(0.0f, real_font_size.y)); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::TextColored(HUDElements.colors.engine, "%s", "Frametime"); + for (size_t i = 0; i < HUDElements.params->table_columns - 1; i++) + ImGui::TableNextCell(); + ImGui::Dummy(ImVec2(0.0f, real_font_size.y)); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width * 1.3, "%.1f ms", 1000 / HUDElements.sw_stats->fps); ImGui::PopFont(); ImGui::TableNextRow(); char hash[40]; @@ -428,10 +432,7 @@ void HudElements::frame_timing(){ ImVec2(ImGui::GetContentRegionAvailWidth() * HUDElements.params->table_columns, 50)); } ImGui::PopStyleColor(); - ImGui::SameLine(0,1.0f); - ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::Text("%.1f ms", 1000 / HUDElements.sw_stats->fps); - ImGui::PopFont(); + } } From 8cad40cfac84f235748d07f8989a5ebfd98cb869 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Wed, 25 Nov 2020 17:39:02 -0800 Subject: [PATCH 115/130] Change order of cpu/gpu load colors and data --- src/hud_elements.cpp | 16 ++++++++-------- src/hud_elements.h | 8 ++++---- src/overlay.h | 6 +++--- src/overlay_params.cpp | 8 ++++---- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index b045fcde..5b22f5a9 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -64,12 +64,12 @@ void HudElements::convert_colors(struct overlay_params& params) HUDElements.colors.text = convert(params.text_color); HUDElements.colors.media_player = convert(params.media_player_color); HUDElements.colors.wine = convert(params.wine_color); - HUDElements.colors.gpu_load_high = convert(params.gpu_load_color[0]); + HUDElements.colors.gpu_load_low = convert(params.gpu_load_color[0]); HUDElements.colors.gpu_load_med = convert(params.gpu_load_color[1]); - HUDElements.colors.gpu_load_low = convert(params.gpu_load_color[2]); - HUDElements.colors.cpu_load_high = convert(params.cpu_load_color[0]); + HUDElements.colors.gpu_load_high = convert(params.gpu_load_color[2]); + HUDElements.colors.cpu_load_low = convert(params.cpu_load_color[0]); HUDElements.colors.cpu_load_med = convert(params.cpu_load_color[1]); - HUDElements.colors.cpu_load_low = convert(params.cpu_load_color[2]); + HUDElements.colors.cpu_load_high = convert(params.cpu_load_color[2]); ImGuiStyle& style = ImGui::GetStyle(); style.Colors[ImGuiCol_PlotLines] = convert(params.frametime_color); @@ -112,9 +112,9 @@ void HudElements::gpu_stats(){ auto text_color = HUDElements.colors.text; if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){ struct LOAD_DATA gpu_data = { - HUDElements.colors.gpu_load_high, - HUDElements.colors.gpu_load_med, HUDElements.colors.gpu_load_low, + HUDElements.colors.gpu_load_med, + HUDElements.colors.gpu_load_high, HUDElements.params->gpu_load_value[0], HUDElements.params->gpu_load_value[1] }; @@ -173,9 +173,9 @@ void HudElements::cpu_stats(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_load_change]){ int cpu_load_percent = int(cpuStats.GetCPUDataTotal().percent); struct LOAD_DATA cpu_data = { - HUDElements.colors.cpu_load_high, - HUDElements.colors.cpu_load_med, HUDElements.colors.cpu_load_low, + HUDElements.colors.cpu_load_med, + HUDElements.colors.cpu_load_high, HUDElements.params->cpu_load_value[0], HUDElements.params->cpu_load_value[1] }; diff --git a/src/hud_elements.h b/src/hud_elements.h index 026221de..925eafcb 100644 --- a/src/hud_elements.h +++ b/src/hud_elements.h @@ -55,12 +55,12 @@ class HudElements{ text, media_player, wine, - gpu_load_high, - gpu_load_med, gpu_load_low, - cpu_load_high, + gpu_load_med, + gpu_load_high, + cpu_load_low, cpu_load_med, - cpu_load_low; + cpu_load_high; } colors {}; }; diff --git a/src/overlay.h b/src/overlay.h index 0e2c5c87..f927f933 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -70,11 +70,11 @@ struct benchmark_stats { }; struct LOAD_DATA { - ImVec4 color_high; - ImVec4 color_med; ImVec4 color_low; - unsigned high_load; + ImVec4 color_med; + ImVec4 color_high; unsigned med_load; + unsigned high_load; }; extern struct fps_limit fps_limit_stats; diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 269d02a7..b339a49a 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -543,15 +543,15 @@ parse_overlay_config(struct overlay_params *params, params->media_player_name = ""; params->font_scale = 1.0f; params->wine_color = 0xeb5b5b; - params->gpu_load_color = { 0xb22222, 0xfdfd09, 0x39f900 }; - params->cpu_load_color = { 0xb22222, 0xfdfd09, 0x39f900 }; + params->gpu_load_color = { 0x39f900, 0xfdfd09, 0xb22222 }; + params->cpu_load_color = { 0x39f900, 0xfdfd09, 0xb22222 }; params->font_scale_media_player = 0.55f; params->log_interval = 100; params->media_player_order = { MP_ORDER_TITLE, MP_ORDER_ARTIST, MP_ORDER_ALBUM }; params->permit_upload = 0; params->benchmark_percentiles = { "97", "AVG", "1", "0.1" }; - params->gpu_load_value = { 90, 60 }; - params->cpu_load_value = { 90, 60 }; + params->gpu_load_value = { 60, 90 }; + params->cpu_load_value = { 60, 90 }; params->cellpadding_y = -0.085; From ee2933bff5b263b7037cb17137df9bd8c8270f63 Mon Sep 17 00:00:00 2001 From: jackun Date: Mon, 16 Nov 2020 15:51:37 +0200 Subject: [PATCH 116/130] Resize fonts --- src/font.cpp | 8 +-- src/gl/imgui_hud.cpp | 8 +++ src/gl/imgui_impl_opengl3.cpp | 2 +- src/gl/imgui_impl_opengl3.h | 1 + src/overlay.h | 1 + src/overlay_params.cpp | 28 +++++++++ src/overlay_params.h | 2 + src/vulkan.cpp | 108 +++++++++++++++++++++++++--------- 8 files changed, 125 insertions(+), 33 deletions(-) diff --git a/src/font.cpp b/src/font.cpp index ff51de87..e8866659 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -5,6 +5,7 @@ void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& text_font) { auto& io = ImGui::GetIO(); + io.Fonts->Clear(); ImGui::GetIO().FontGlobalScale = params.font_scale; // set here too so ImGui::CalcTextSize is correct float font_size = params.font_size; if (font_size < FLT_EPSILON) @@ -40,16 +41,15 @@ void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& te if (params.font_glyph_ranges & FG_VIETNAMESE) builder.AddRanges(io.Fonts->GetGlyphRangesVietnamese()); if (params.font_glyph_ranges & FG_LATIN_EXT_A) { - static const ImWchar latin_ext_a[] { 0x0100, 0x017F, 0 }; + constexpr ImWchar latin_ext_a[] { 0x0100, 0x017F, 0 }; builder.AddRanges(latin_ext_a); } if (params.font_glyph_ranges & FG_LATIN_EXT_B) { - static const ImWchar latin_ext_b[] { 0x0180, 0x024F, 0 }; + constexpr ImWchar latin_ext_b[] { 0x0180, 0x024F, 0 }; builder.AddRanges(latin_ext_b); } builder.BuildRanges(&glyph_ranges); - // If both font_file and text_font_file are the same then just use "default" font bool same_font = (params.font_file == params.font_file_text || params.font_file_text.empty()); bool same_size = (font_size == font_size_text); @@ -79,4 +79,4 @@ void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& te text_font = io.Fonts->Fonts[0]; io.Fonts->Build(); -} \ No newline at end of file +} diff --git a/src/gl/imgui_hud.cpp b/src/gl/imgui_hud.cpp index c6a4ac43..a62396d0 100644 --- a/src/gl/imgui_hud.cpp +++ b/src/gl/imgui_hud.cpp @@ -133,6 +133,7 @@ void imgui_create(void *ctx) glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); create_fonts(params, sw_stats.font1, sw_stats.font_text); + sw_stats.font_params_hash = params.font_params_hash; // Restore global context or ours might clash with apps that use Dear ImGui ImGui::SetCurrentContext(saved_ctx); @@ -178,6 +179,13 @@ void imgui_render(unsigned int width, unsigned int height) if (HUDElements.colors.update) HUDElements.convert_colors(params); + if (sw_stats.font_params_hash != params.font_params_hash) + { + sw_stats.font_params_hash = params.font_params_hash; + create_fonts(params, sw_stats.font1, sw_stats.font_text); + ImGui_ImplOpenGL3_CreateFontsTexture(); + } + ImGui_ImplOpenGL3_NewFrame(); ImGui::NewFrame(); { diff --git a/src/gl/imgui_impl_opengl3.cpp b/src/gl/imgui_impl_opengl3.cpp index e44ba290..9375e608 100644 --- a/src/gl/imgui_impl_opengl3.cpp +++ b/src/gl/imgui_impl_opengl3.cpp @@ -105,7 +105,7 @@ static void ImGui_ImplOpenGL3_DestroyFontsTexture() } } -static bool ImGui_ImplOpenGL3_CreateFontsTexture() +bool ImGui_ImplOpenGL3_CreateFontsTexture() { ImGui_ImplOpenGL3_DestroyFontsTexture(); // Build texture atlas diff --git a/src/gl/imgui_impl_opengl3.h b/src/gl/imgui_impl_opengl3.h index 4d9d373a..01609368 100644 --- a/src/gl/imgui_impl_opengl3.h +++ b/src/gl/imgui_impl_opengl3.h @@ -34,6 +34,7 @@ IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullpt IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); +IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); // (Optional) Called by Init/NewFrame/Shutdown //IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); diff --git a/src/overlay.h b/src/overlay.h index f927f933..09299f83 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -30,6 +30,7 @@ struct swapchain_stats { ImFont* font1 = nullptr; ImFont* font_text = nullptr; + size_t font_params_hash = 0; std::string time; double fps; struct iostats io; diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index b339a49a..1eff9cc7 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include "overlay_params.h" #include "overlay.h" @@ -33,6 +34,25 @@ #include "dbus_info.h" #endif +// C++17 has `if constexpr` so this won't be needed then +template +size_t get_hash() +{ + return 0; +} + +template +size_t get_hash(T const& first, Ts const&... rest) +{ + size_t hash = std::hash{}(first); +#if __cplusplus >= 201703L + if constexpr (sizeof...(rest) > 0) +#endif + hash ^= get_hash(rest...) << 1; + + return hash; +} + static enum overlay_param_position parse_position(const char *str) { @@ -677,6 +697,14 @@ parse_overlay_config(struct overlay_params *params, params->width += 7 * params->font_size * params->font_scale; } + params->font_params_hash = get_hash(params->font_size, + params->font_size_text, + params->no_small_font, + params->font_file, + params->font_file_text, + params->font_glyph_ranges + ); + // set frametime limit using namespace std::chrono; if (params->fps_limit.size() > 0 && params->fps_limit[0] > 0) diff --git a/src/overlay_params.h b/src/overlay_params.h index b2e325b6..b3f34d22 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -209,6 +209,8 @@ struct overlay_params { std::string config_file_path; std::unordered_map options; int permit_upload; + + size_t font_params_hash; }; const extern char *overlay_param_names[]; diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 0dbe195c..a7d78652 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -220,6 +220,8 @@ static void unmap_object(uint64_t obj) #define CHAR_CELSIUS "\xe2\x84\x83" #define CHAR_FAHRENHEIT "\xe2\x84\x89" +static void shutdown_swapchain_font(struct swapchain_data*); + static VkLayerInstanceCreateInfo *get_instance_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func) { @@ -835,13 +837,14 @@ static void upload_image_data(struct device_data *device_data, 1, use_barrier); } -static VkDescriptorSet create_image_with_desc(struct swapchain_data *data, - uint32_t width, - uint32_t height, - VkFormat format, - VkImage& image, - VkDeviceMemory& image_mem, - VkImageView& image_view) +static void create_image(struct swapchain_data *data, + VkDescriptorSet descriptor_set, + uint32_t width, + uint32_t height, + VkFormat format, + VkImage& image, + VkDeviceMemory& image_mem, + VkImageView& image_view) { struct device_data *device_data = data->device; @@ -888,9 +891,22 @@ static VkDescriptorSet create_image_with_desc(struct swapchain_data *data, VK_CHECK(device_data->vtable.CreateImageView(device_data->device, &view_info, NULL, &image_view)); - VkDescriptorSet descriptor_set; + update_image_descriptor(data, image_view, descriptor_set); +} - VkDescriptorSetAllocateInfo alloc_info = {}; +static VkDescriptorSet create_image_with_desc(struct swapchain_data *data, + uint32_t width, + uint32_t height, + VkFormat format, + VkImage& image, + VkDeviceMemory& image_mem, + VkImageView& image_view) +{ + struct device_data *device_data = data->device; + + VkDescriptorSet descriptor_set {}; + + VkDescriptorSetAllocateInfo alloc_info {}; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; alloc_info.descriptorPool = data->descriptor_pool; alloc_info.descriptorSetCount = 1; @@ -899,14 +915,54 @@ static VkDescriptorSet create_image_with_desc(struct swapchain_data *data, &alloc_info, &descriptor_set)); - update_image_descriptor(data, image_view, descriptor_set); + create_image(data, descriptor_set, width, height, format, image, image_mem, image_view); return descriptor_set; } +static void check_fonts(struct swapchain_data* data) +{ + struct device_data *device_data = data->device; + struct instance_data *instance_data = device_data->instance; + auto& params = instance_data->params; + ImGuiIO& io = ImGui::GetIO(); + + if (params.font_params_hash != data->sw_stats.font_params_hash) + { + std::cerr << "MANGOHUD: recreating font image\n"; + VkDescriptorSet desc_set = (VkDescriptorSet)io.Fonts->TexID; + create_fonts(instance_data->params, data->sw_stats.font1, data->sw_stats.font_text); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); + + // wait for rendering to complete, if any + device_data->vtable.DeviceWaitIdle(device_data->device); + shutdown_swapchain_font(data); + + if (desc_set) + create_image(data, desc_set, width, height, VK_FORMAT_R8_UNORM, data->font_image, data->font_mem, data->font_image_view); + else + desc_set = create_image_with_desc(data, width, height, VK_FORMAT_R8_UNORM, data->font_image, data->font_mem, data->font_image_view); + + io.Fonts->TexID = (ImTextureID) desc_set; + + data->font_uploaded = false; + data->sw_stats.font_params_hash = params.font_params_hash; + +#ifndef NDEBUG + std::cerr << "MANGOHUD: Default font tex size: " << width << "x" << height << "px (" << (width*height*1) << " bytes)" << "\n"; +#endif + + } +} + static void ensure_swapchain_fonts(struct swapchain_data *data, VkCommandBuffer command_buffer) { struct device_data *device_data = data->device; + + check_fonts(data); + if (data->font_uploaded) return; @@ -1411,18 +1467,7 @@ static void setup_swapchain_data_pipeline(struct swapchain_data *data) device_data->vtable.DestroyShaderModule(device_data->device, vert_module, NULL); device_data->vtable.DestroyShaderModule(device_data->device, frag_module, NULL); - create_fonts(device_data->instance->params, data->sw_stats.font1, data->sw_stats.font_text); - - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - - // upload default font to VkImage - io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); - io.Fonts->TexID = (ImTextureID)create_image_with_desc(data, width, height, VK_FORMAT_R8_UNORM, data->font_image, data->font_mem, data->font_image_view); -#ifndef NDEBUG - std::cerr << "MANGOHUD: Default font tex size: " << width << "x" << height << "px (" << (width*height*1) << " bytes)" << "\n"; -#endif + check_fonts(data); // if (data->descriptor_set) // update_image_descriptor(data, data->font_image_view[0], data->descriptor_set); @@ -1593,6 +1638,18 @@ static void setup_swapchain_data(struct swapchain_data *data, NULL, &data->command_pool)); } +static void shutdown_swapchain_font(struct swapchain_data *data) +{ + struct device_data *device_data = data->device; + + device_data->vtable.DestroyImageView(device_data->device, data->font_image_view, NULL); + device_data->vtable.DestroyImage(device_data->device, data->font_image, NULL); + device_data->vtable.FreeMemory(device_data->device, data->font_mem, NULL); + + device_data->vtable.DestroyBuffer(device_data->device, data->upload_font_buffer, NULL); + device_data->vtable.FreeMemory(device_data->device, data->upload_font_buffer_mem, NULL); +} + static void shutdown_swapchain_data(struct swapchain_data *data) { struct device_data *device_data = data->device; @@ -1626,12 +1683,7 @@ static void shutdown_swapchain_data(struct swapchain_data *data) data->descriptor_layout, NULL); device_data->vtable.DestroySampler(device_data->device, data->font_sampler, NULL); - device_data->vtable.DestroyImageView(device_data->device, data->font_image_view, NULL); - device_data->vtable.DestroyImage(device_data->device, data->font_image, NULL); - device_data->vtable.FreeMemory(device_data->device, data->font_mem, NULL); - - device_data->vtable.DestroyBuffer(device_data->device, data->upload_font_buffer, NULL); - device_data->vtable.FreeMemory(device_data->device, data->upload_font_buffer_mem, NULL); + shutdown_swapchain_font(data); ImGui::DestroyContext(data->imgui_context); } From 3827fe96d4d9353187d26e2d4e3dd6ee5955f67a Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Fri, 27 Nov 2020 14:17:43 +0100 Subject: [PATCH 117/130] Add autostart_log param --- bin/MangoHud.conf | 3 ++- src/logging.cpp | 5 +++++ src/logging.h | 1 + src/overlay.cpp | 1 - src/overlay_params.cpp | 6 +++++- src/overlay_params.h | 3 ++- 6 files changed, 15 insertions(+), 4 deletions(-) diff --git a/bin/MangoHud.conf b/bin/MangoHud.conf index 6248c3d1..c6cc0fdf 100644 --- a/bin/MangoHud.conf +++ b/bin/MangoHud.conf @@ -145,7 +145,8 @@ background_alpha=0.5 #upload_log=Shift+F3 ################## LOG ################# - +### Automatically start the log after X seconds +# autostart_log = 1 ### Set amount of time in second that the logging will run for # log_duration ### Define name and location of the output file (Required for logging) diff --git a/src/logging.cpp b/src/logging.cpp index 4a2a56ac..f2c4271c 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -165,4 +165,9 @@ void Logger::upload_last_log() { void Logger::upload_last_logs() { if(m_log_files.empty()) return; std::thread(upload_files, m_log_files).detach(); +} + +void autostart_log(int sleep) { + os_time_sleep(sleep * 1000000); + logger->start_logging(); } \ No newline at end of file diff --git a/src/logging.h b/src/logging.h index a7397b94..ae16603f 100644 --- a/src/logging.h +++ b/src/logging.h @@ -74,5 +74,6 @@ extern uint64_t frametime; extern logData currentLogData; string exec(string command); +void autostart_log(int sleep); #endif //MANGOHUD_LOGGING_H diff --git a/src/overlay.cpp b/src/overlay.cpp index 8e1c6806..cea2daa2 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -70,7 +70,6 @@ void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& par } void update_hud_info(struct swapchain_stats& sw_stats, struct overlay_params& params, uint32_t vendorID){ - if(not logger) logger = std::make_unique(¶ms); uint32_t f_idx = sw_stats.n_frames % ARRAY_SIZE(sw_stats.frames_stats); uint64_t now = os_time_get(); /* us */ double elapsed = (double)(now - sw_stats.last_fps_update); /* us */ diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 1eff9cc7..b390556f 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -22,7 +22,6 @@ #include "config.h" #include "string_utils.h" #include "hud_elements.h" - #include "mesa/util/os_socket.h" #ifdef HAVE_X11 @@ -380,6 +379,7 @@ parse_font_glyph_ranges(const char *str) #define parse_no_small_font(s) parse_unsigned(s) != 0 #define parse_cellpadding_y(s) parse_float(s) #define parse_table_columns(s) parse_unsigned(s) +#define parse_autostart_log(s) parse_unsigned(s) #define parse_cpu_color(s) parse_color(s) #define parse_gpu_color(s) parse_color(s) @@ -736,4 +736,8 @@ parse_overlay_config(struct overlay_params *params, // Needs ImGui context but it is null here for OpenGL so just note it and update somewhere else HUDElements.colors.update = true; + + if(not logger) logger = std::make_unique(params); + if(params->autostart_log) + std::thread(autostart_log, params->autostart_log).detach(); } diff --git a/src/overlay_params.h b/src/overlay_params.h index b3f34d22..521d30bf 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -118,6 +118,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(cellpadding_y) \ OVERLAY_PARAM_CUSTOM(table_columns) \ OVERLAY_PARAM_CUSTOM(blacklist) \ + OVERLAY_PARAM_CUSTOM(autostart_log) \ enum overlay_param_position { LAYER_POSITION_TOP_LEFT, @@ -200,7 +201,7 @@ struct overlay_params { std::string cpu_text, gpu_text; //std::string blacklist; std::vector blacklist; - unsigned log_interval; + unsigned log_interval, autostart_log; std::vector media_player_order; std::vector benchmark_percentiles; std::string font_file, font_file_text; From 4505bba6bd33ead8bb0f256f86e98933dc713c5f Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Fri, 27 Nov 2020 14:49:02 +0100 Subject: [PATCH 118/130] Check if logger is active before autostarting --- src/overlay_params.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index b390556f..46837874 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -738,6 +738,6 @@ parse_overlay_config(struct overlay_params *params, HUDElements.colors.update = true; if(not logger) logger = std::make_unique(params); - if(params->autostart_log) + if(params->autostart_log && !logger->is_active()) std::thread(autostart_log, params->autostart_log).detach(); } From 9af4ac546fb1cce6d4cb200aa14b2f368b24bec9 Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Fri, 27 Nov 2020 15:53:49 +0100 Subject: [PATCH 119/130] No need to convert cpu_load --- src/logging.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging.h b/src/logging.h index ae16603f..b0134e89 100644 --- a/src/logging.h +++ b/src/logging.h @@ -17,7 +17,7 @@ using namespace std; struct logData{ double fps; uint64_t frametime; - int cpu_load; + float cpu_load; int gpu_load; int cpu_temp; int gpu_temp; From 6a5cd38127ae330c79bc61d2a433bdb84061bc5b Mon Sep 17 00:00:00 2001 From: jackun Date: Fri, 27 Nov 2020 17:43:44 +0200 Subject: [PATCH 120/130] Meson option to have absolute paths in LD_PRELOAD --- bin/mangohud.in | 4 ++-- build.sh | 4 ++-- meson_options.txt | 1 + src/meson.build | 8 +++++++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/bin/mangohud.in b/bin/mangohud.in index e9fec054..eadce2d2 100755 --- a/bin/mangohud.in +++ b/bin/mangohud.in @@ -13,10 +13,10 @@ if [ "$1" = "--dlsym" ]; then shift fi -MANGOHUD_LIB_NAME="libMangoHud.so" +MANGOHUD_LIB_NAME="@ld_libdir_mangohud_abs@libMangoHud.so" if [ "$MANGOHUD_DLSYM" = "1" ]; then - MANGOHUD_LIB_NAME="libMangoHud_dlsym.so:${MANGOHUD_LIB_NAME}" + MANGOHUD_LIB_NAME="@ld_libdir_mangohud_abs@libMangoHud_dlsym.so:${MANGOHUD_LIB_NAME}" fi # Preload using the plain filesnames of the libs, the dynamic linker will diff --git a/build.sh b/build.sh index 81fc8bf5..5bca4d7c 100755 --- a/build.sh +++ b/build.sh @@ -142,14 +142,14 @@ configure() { dependencies git submodule update --init --depth 50 if [[ ! -f "build/meson64/build.ninja" ]]; then - meson build/meson64 --libdir lib/mangohud/lib --prefix /usr -Dappend_libdir_mangohud=false -Dld_libdir_prefix=true $@ ${CONFIGURE_OPTS} + meson build/meson64 --libdir lib/mangohud/lib --prefix /usr -Dappend_libdir_mangohud=false -Dld_libdir_prefix=true -Dld_libdir_abs=true $@ ${CONFIGURE_OPTS} fi if [[ ! -f "build/meson32/build.ninja" ]]; then export CC="gcc -m32" export CXX="g++ -m32" export PKG_CONFIG_PATH="/usr/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig:/usr/lib/pkgconfig:${PKG_CONFIG_PATH_32}" export LLVM_CONFIG="/usr/bin/llvm-config32" - meson build/meson32 --libdir lib/mangohud/lib32 --prefix /usr -Dappend_libdir_mangohud=false -Dld_libdir_prefix=true $@ ${CONFIGURE_OPTS} + meson build/meson32 --libdir lib/mangohud/lib32 --prefix /usr -Dappend_libdir_mangohud=false -Dld_libdir_prefix=true -Dld_libdir_abs=true $@ ${CONFIGURE_OPTS} fi } diff --git a/meson_options.txt b/meson_options.txt index 87338e5e..9bac7910 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -2,6 +2,7 @@ option('glibcxx_asserts', type : 'boolean', value : false) option('use_system_vulkan', type : 'feature', value : 'disabled', description: 'Use system vulkan headers instead of the provided ones') option('append_libdir_mangohud', type : 'boolean', value : true, description: 'Append "mangohud" to libdir path or not.') option('ld_libdir_prefix', type : 'boolean', value : false, description: 'Set ld libdir to "$prefix/lib/mangohud/\$LIB"') +option('ld_libdir_abs', type : 'boolean', value : false, description: 'Use absolute path in LD_PRELOAD') option('include_doc', type : 'boolean', value : true, description: 'Include the example config') option('with_nvml', type : 'combo', value : 'enabled', choices: ['enabled', 'system', 'disabled'], description: 'Enable NVML support') option('with_xnvctrl', type : 'feature', value : 'enabled', description: 'Enable XNVCtrl support') diff --git a/src/meson.build b/src/meson.build index da4847e2..63935265 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,5 +1,6 @@ glslang = find_program('glslangValidator') +ld_libdir_mangohud_abs = '' # Needs prefix for configure_file() if get_option('append_libdir_mangohud') libdir_mangohud = join_paths(get_option('libdir'), 'mangohud') @@ -15,6 +16,10 @@ if get_option('ld_libdir_prefix') ld_libdir_mangohud = get_option('prefix') + '/lib/mangohud/\$LIB/' endif +if get_option('ld_libdir_abs') + ld_libdir_mangohud_abs = ld_libdir_mangohud +endif + overlay_shaders = [ 'overlay.frag', 'overlay.vert', @@ -205,7 +210,8 @@ configure_file(input : 'mangohud.json.in', configure_file(input : '../bin/mangohud.in', output : 'mangohud', - configuration : {'ld_libdir_mangohud' : ld_libdir_mangohud}, + configuration : {'ld_libdir_mangohud' : ld_libdir_mangohud, + 'ld_libdir_mangohud_abs': ld_libdir_mangohud_abs}, install_dir : get_option('bindir'), ) From 27fee4f151c80b61e93be7e6b9d93331ed0a1ddb Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Fri, 27 Nov 2020 18:49:13 +0100 Subject: [PATCH 121/130] Prettying up hudelements::graphs --- src/hud_elements.cpp | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 5b22f5a9..bb528b30 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -453,25 +453,19 @@ void HudElements::media_player(){ } void HudElements::graphs(){ - + ImGui::TableNextRow(); ImGui::Dummy(ImVec2(0.0f, real_font_size.y)); std::string value = HUDElements.ordered_functions[HUDElements.place].second; - std::vector arr; - - for (size_t i = 0; i < 50; i++) - { - arr.push_back(0); - } + std::vector arr(50, 0); + ImGui::PushFont(HUDElements.sw_stats->font1); if (value == "cpu_load"){ for (auto& it : graph_data){ arr.push_back(float(it.cpu_load)); arr.erase(arr.begin()); } HUDElements.max = 100; HUDElements.min = 0; - ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::TextColored(HUDElements.colors.engine, "%s", "CPU Load"); - ImGui::PopFont(); } if (value == "gpu_load"){ @@ -480,9 +474,7 @@ void HudElements::graphs(){ arr.erase(arr.begin()); } HUDElements.max = 100; HUDElements.min = 0; - ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Load"); - ImGui::PopFont(); } if (value == "cpu_temp"){ @@ -497,9 +489,7 @@ void HudElements::graphs(){ HUDElements.max = HUDElements.cpu_temp_max; HUDElements.min = 0; - ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::TextColored(HUDElements.colors.engine, "%s", "CPU Temp"); - ImGui::PopFont(); } if (value == "gpu_temp"){ @@ -514,9 +504,7 @@ void HudElements::graphs(){ HUDElements.max = HUDElements.gpu_temp_max; HUDElements.min = 0; - ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Temp"); - ImGui::PopFont(); } if (value == "gpu_core_clock"){ @@ -529,9 +517,7 @@ void HudElements::graphs(){ HUDElements.max = HUDElements.gpu_core_max; HUDElements.min = 0; - ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Core Clock"); - ImGui::PopFont(); } if (value == "gpu_mem_clock"){ @@ -544,9 +530,7 @@ void HudElements::graphs(){ HUDElements.max = HUDElements.gpu_mem_max; HUDElements.min = 0; - ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Mem Clock"); - ImGui::PopFont(); } if (value == "vram"){ @@ -557,9 +541,7 @@ void HudElements::graphs(){ HUDElements.max = gpu_info.memoryTotal; HUDElements.min = 0; - ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::TextColored(HUDElements.colors.engine, "%s", "VRAM"); - ImGui::PopFont(); } if (value == "ram"){ @@ -572,11 +554,10 @@ void HudElements::graphs(){ HUDElements.max = memmax; HUDElements.min = 0; - ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::TextColored(HUDElements.colors.engine, "%s", "RAM"); - ImGui::PopFont(); } - + ImGui::PopFont(); + ImGui::Dummy(ImVec2(0.0f,5.0f)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); ImGui::TableNextRow(); if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_histogram]){ @@ -590,7 +571,7 @@ void HudElements::graphs(){ NULL, HUDElements.min, HUDElements.max, ImVec2(ImGui::GetContentRegionAvailWidth() * HUDElements.params->table_columns, 50)); } - + ImGui::Dummy(ImVec2(0.0f,5.0f)); ImGui::PopStyleColor(1); } From fda43f57272c2c0f9bca497631bc2a26ff50604b Mon Sep 17 00:00:00 2001 From: jackun Date: Fri, 27 Nov 2020 19:59:11 +0200 Subject: [PATCH 122/130] Use str_tokenize for multiple delimiters --- src/hud_elements.cpp | 5 +++-- src/overlay_params.cpp | 38 ++++++++++++++++---------------------- src/string_utils.h | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index bb528b30..adb29850 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -4,6 +4,7 @@ #include "cpu.h" #include "memory.h" #include "mesa/util/macros.h" +#include "string_utils.h" // Cut from https://github.com/ocornut/imgui/pull/2943 // Probably move to ImGui @@ -596,8 +597,8 @@ void HudElements::sort_elements(std::pair option){ if (param == "frame_timing") { ordered_functions.push_back({frame_timing, value}); } if (param == "media_player") { ordered_functions.push_back({media_player, value}); } if (param == "graphs"){ - stringstream ss; ss << value; - while (getline(ss, value, '+')) { + auto values = str_tokenize(value); + for (auto& value : values) { if (find(permitted_params.begin(), permitted_params.end(), value) != permitted_params.end()) ordered_functions.push_back({graphs, value}); else diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 46837874..d3360e2e 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -100,9 +100,8 @@ parse_string_to_keysym_vec(const char *str) std::vector keys; if(g_x11->IsLoaded()) { - std::stringstream keyStrings(str); - std::string ks; - while (std::getline(keyStrings, ks, '+')) { + auto keyStrings = str_tokenize(str); + for (auto& ks : keyStrings) { trim(ks); KeySym xk = g_x11->XStringToKeysym(ks.c_str()); if (xk) @@ -140,10 +139,9 @@ static std::vector parse_fps_limit(const char *str) { std::vector fps_limit; - std::stringstream fps_limit_strings(str); - std::string value; + auto fps_limit_strings = str_tokenize(str); - while (std::getline(fps_limit_strings, value, '+')) { + for (auto& value : fps_limit_strings) { trim(value); uint32_t as_int; @@ -176,9 +174,9 @@ static std::vector parse_load_color(const char *str) { std::vector load_colors; - std::stringstream ss(str); + auto tokens = str_tokenize(str); std::string token; - while (std::getline(ss, token, '+')) { + for (auto& token : tokens) { trim(token); load_colors.push_back(std::stoi(token, NULL, 16)); } @@ -193,9 +191,9 @@ static std::vector parse_load_value(const char *str) { std::vector load_value; - std::stringstream ss(str); + auto tokens = str_tokenize(str); std::string token; - while (std::getline(ss, token, '+')) { + for (auto& token : tokens) { trim(token); load_value.push_back(std::stoi(token)); } @@ -207,9 +205,9 @@ static std::vector parse_str_tokenize(const char *str) { std::vector data; - std::stringstream ss(str); + auto tokens = str_tokenize(str); std::string token; - while (std::getline(ss, token, '+')) { + for (auto& token : tokens) { trim(token); data.push_back(token); } @@ -260,9 +258,8 @@ static std::vector parse_media_player_order(const char *str) { std::vector order; - std::stringstream ss(str); - std::string token; - while (std::getline(ss, token, '+')) { + auto tokens = str_tokenize(str); + for (auto& token : tokens) { trim(token); std::transform(token.begin(), token.end(), token.begin(), ::tolower); if (token == "title") @@ -280,10 +277,8 @@ static std::vector parse_benchmark_percentiles(const char *str) { std::vector percentiles; - std::stringstream percent_strings(str); - std::string value; - - while (std::getline(percent_strings, value, '+')) { + auto tokens = str_tokenize(str); + for (auto& value : tokens) { trim(value); if (value == "AVG") { @@ -321,9 +316,8 @@ static uint32_t parse_font_glyph_ranges(const char *str) { uint32_t fg = 0; - std::stringstream ss(str); - std::string token; - while (std::getline(ss, token, ',')) { + auto tokens = str_tokenize(str); + for (auto& token : tokens) { trim(token); std::transform(token.begin(), token.end(), token.begin(), ::tolower); diff --git a/src/string_utils.h b/src/string_utils.h index 3c9664e6..e7062add 100644 --- a/src/string_utils.h +++ b/src/string_utils.h @@ -3,6 +3,7 @@ #define MANGOHUD_STRING_UTILS_H #include +#include #include #include #include @@ -109,6 +110,23 @@ static float parse_float(const std::string& s, std::size_t* float_len = nullptr) return ret; } +static std::vector str_tokenize(const std::string& s, const std::string&& delims = ",:+") +{ + std::vector v; + size_t old_n = 0, new_n = 0; + + while (old_n < s.size()){ + new_n = s.find_first_of(delims, old_n); + auto c = s.substr(old_n, new_n - old_n); + if (old_n != new_n) + v.push_back(c); + if (new_n == std::string::npos) + break; + old_n = new_n + 1; + } + return v; +} + #pragma GCC diagnostic pop #endif //MANGOHUD_STRING_UTILS_H From 0309b6bbb94693f9dd3f2c641baf199c1ba68bff Mon Sep 17 00:00:00 2001 From: jackun Date: Fri, 27 Nov 2020 19:59:57 +0200 Subject: [PATCH 123/130] Escape spaces in file names for `wordexp` --- src/overlay_params.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index d3360e2e..d78ea2e8 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -239,11 +239,17 @@ parse_path(const char *str) #ifdef _XOPEN_SOURCE // Expand ~/ to home dir if (str[0] == '~') { - std::string s; + std::string s = str; + size_t n = 0; wordexp_t e; int ret; - if (!(ret = wordexp(str, &e, 0))) + while ((n = s.find_first_of(" ", n)) != std::string::npos) { + s = s.replace(n, 1, "\\ "); + n += 2; + } + + if (!(ret = wordexp(s.c_str(), &e, 0))) s = e.we_wordv[0]; wordfree(&e); From a4a5950ddf3f1800113bc360aff078583ee245ce Mon Sep 17 00:00:00 2001 From: FlightlessMango Date: Fri, 27 Nov 2020 19:15:51 +0100 Subject: [PATCH 124/130] Make sure graphs have data without enabling elems --- src/hud_elements.cpp | 6 ++---- src/overlay.cpp | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index adb29850..658b5b16 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -479,8 +479,6 @@ void HudElements::graphs(){ } if (value == "cpu_temp"){ - if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_temp]) - HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_temp] = true; for (auto& it : graph_data){ arr.push_back(float(it.cpu_temp)); arr.erase(arr.begin()); @@ -494,8 +492,6 @@ void HudElements::graphs(){ } if (value == "gpu_temp"){ - if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_temp]) - HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_temp] = true; for (auto& it : graph_data){ arr.push_back(float(it.gpu_temp)); arr.erase(arr.begin()); @@ -597,6 +593,8 @@ void HudElements::sort_elements(std::pair option){ if (param == "frame_timing") { ordered_functions.push_back({frame_timing, value}); } if (param == "media_player") { ordered_functions.push_back({media_player, value}); } if (param == "graphs"){ + if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_graphs]) + HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_graphs] = true; auto values = str_tokenize(value); for (auto& value : values) { if (find(permitted_params.begin(), permitted_params.end(), value) != permitted_params.end()) diff --git a/src/overlay.cpp b/src/overlay.cpp index cea2daa2..04697491 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -27,7 +27,7 @@ void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& par if (params.enabled[OVERLAY_PARAM_ENABLED_core_load] || params.enabled[OVERLAY_PARAM_ENABLED_cpu_mhz]) cpuStats.UpdateCoreMhz(); - if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_temp] || logger->is_active()) + if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_temp] || logger->is_active() || params.enabled[OVERLAY_PARAM_ENABLED_graphs]) cpuStats.UpdateCpuTemp(); if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_power]) cpuStats.UpdateCpuPower(); From e0f79d9435277c01d43b56806b2c5697a93359c2 Mon Sep 17 00:00:00 2001 From: jackun Date: Fri, 27 Nov 2020 23:47:38 +0200 Subject: [PATCH 125/130] Escape spaces in file names for `wordexp` v2 but just append to stringstream --- src/overlay_params.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index d78ea2e8..e1435229 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -239,22 +239,22 @@ parse_path(const char *str) #ifdef _XOPEN_SOURCE // Expand ~/ to home dir if (str[0] == '~') { - std::string s = str; - size_t n = 0; + std::stringstream s; wordexp_t e; int ret; - while ((n = s.find_first_of(" ", n)) != std::string::npos) { - s = s.replace(n, 1, "\\ "); - n += 2; + if (!(ret = wordexp(str, &e, 0))) { + for(size_t i = 0; i < e.we_wordc; i++) + { + if (i > 0) + s << " "; + s << e.we_wordv[i]; + } } - - if (!(ret = wordexp(s.c_str(), &e, 0))) - s = e.we_wordv[0]; wordfree(&e); if (!ret) - return s; + return s.str(); } #endif return str; From 4d09cebe3ad9910a8c1e9ac2b1f707bde25c7a9d Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Fri, 27 Nov 2020 13:58:09 -0800 Subject: [PATCH 126/130] Change delimiter from '+' to ',' in README --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3f01eb7e..cdba5d6b 100644 --- a/README.md +++ b/README.md @@ -175,20 +175,20 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `engine_version` | Display OpenGL or vulkan and vulkan-based render engine's version | | `permit_upload` | Allow uploading of logs to Flightlessmango.com | | `upload_log` | Change keybind for uploading log | -| `benchmark_percentiles` | Configure which framerate percentiles are shown in the logging summary. Default is `97+AVG+1+0.1` | +| `benchmark_percentiles` | Configure which framerate percentiles are shown in the logging summary. Default is `97,AVG,1,0.1` | | `wine` | Shows current Wine or Proton version in use | | `wine_color` | Change color of the wine/proton text | | `cpu_mhz` | Shows the CPUs current MHz | | `gpu_load_change` | Changes the color of the GPU load depending on load | -| `gpu_load_color` | Set the colors for the gpu load change low,medium and high. e.g `gpu_load_color=0000FF+00FFFF+FF00FF` | -| `gpu_load_value` | Set the values for medium and high load e.g `gpu_load_value=50+90` | +| `gpu_load_color` | Set the colors for the gpu load change low,medium and high. e.g `gpu_load_color=0000FF,00FFFF,FF00FF` | +| `gpu_load_value` | Set the values for medium and high load e.g `gpu_load_value=50,90` | | `cpu_load_change` | Changes the color of the CPU load depending on load | -| `cpu_load_color` | Set the colors for the gpu load change low,medium and high. e.g `cpu_load_color=0000FF+00FFFF+FF00FF` | -| `cpu_load_value` | Set the values for medium and high load e.g `cpu_load_value=50+90` | +| `cpu_load_color` | Set the colors for the gpu load change low,medium and high. e.g `cpu_load_color=0000FF,00FFFF,FF00FF` | +| `cpu_load_value` | Set the values for medium and high load e.g `cpu_load_value=50,90` | | `cellpadding_y` | Set the vertical cellpadding, default is `-0.085` | | `frametime` | Display frametime next to fps text | | `table_columns` | Set the number of table columns for ImGui, defaults to 3 | -| `blacklist` | Add a program to the blacklist. e.g `blacklist=vkcube+WatchDogs2.exe` | +| `blacklist` | Add a program to the blacklist. e.g `blacklist=vkcube,WatchDogs2.exe` | Example: `MANGOHUD_CONFIG=cpu_temp,gpu_temp,position=top-right,height=500,font_size=32` From 56a5cae2f7c6932686b8ab481de15be0e42b2e59 Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Fri, 27 Nov 2020 14:12:11 -0800 Subject: [PATCH 127/130] Added new params to config file --- bin/MangoHud.conf | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bin/MangoHud.conf b/bin/MangoHud.conf index c6cc0fdf..bf693ca0 100644 --- a/bin/MangoHud.conf +++ b/bin/MangoHud.conf @@ -16,6 +16,9 @@ ################### VISUAL ################### +### Legacy Layout +legacy_layout + ### Display the current CPU information cpu_stats # cpu_temp @@ -86,6 +89,7 @@ position=top-left ### IO read and write for the app (not system) # io_read # io_write +# io_stats ### Display system ram / vram usage # ram @@ -104,7 +108,8 @@ position=top-left ### Hud dimensions # width= # height= -# table_columns +# table_columns= +# cellpadding_y= ### Hud transparency / alpha background_alpha=0.5 From 5af93c7dc5bb6cfff08935ed0f3829566a2a86bd Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Fri, 27 Nov 2020 14:13:30 -0800 Subject: [PATCH 128/130] Change delimiter from '+' to ',' in README for media_player_order --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cdba5d6b..d6ad3f91 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `vsync`
`gl_vsync` | Set vsync for OpenGL or Vulkan | | `media_player` | Show media player metadata | | `media_player_name` | Force media player DBus service name without the `org.mpris.MediaPlayer2` part, like `spotify`, `vlc`, `audacious` or `cantata`. If none is set, MangoHud tries to switch between currently playing players. | -| `media_player_order` | Media player metadata field order. Defaults to `title+artist+album`. | +| `media_player_order` | Media player metadata field order. Defaults to `title,artist,album`. | | `font_scale_media_player` | Change size of media player text relative to font_size | | `io_read`
`io_write` | Show non-cached IO read/write, in MiB/s | | `pci_dev` | Select GPU device in multi-gpu setups | From ef34bcd52fb5ffd583b7ea9c5ec458ed9f51da5f Mon Sep 17 00:00:00 2001 From: jackun Date: Sat, 28 Nov 2020 00:14:32 +0200 Subject: [PATCH 129/130] README.md: about using `+` --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d6ad3f91..af821cc3 100644 --- a/README.md +++ b/README.md @@ -191,6 +191,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `blacklist` | Add a program to the blacklist. e.g `blacklist=vkcube,WatchDogs2.exe` | Example: `MANGOHUD_CONFIG=cpu_temp,gpu_temp,position=top-right,height=500,font_size=32` +Because comma is also used as option delimiter and needs to be escaped for values with a backslash, you can use `+` like `MANGOHUD_CONFIG=fps_limit=60+30+0` instead. Note: Width and Height are set automatically based on the font_size, but can be overridden. ## Vsync From 03bd71d1456daff1407299ca3464a655758e7abf Mon Sep 17 00:00:00 2001 From: Alessandro Toia Date: Fri, 27 Nov 2020 16:14:38 -0800 Subject: [PATCH 130/130] Add missing add_blacklist for OpenGl apps --- src/gl/imgui_hud.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/gl/imgui_hud.cpp b/src/gl/imgui_hud.cpp index a62396d0..feb8278e 100644 --- a/src/gl/imgui_hud.cpp +++ b/src/gl/imgui_hud.cpp @@ -67,8 +67,15 @@ void imgui_init() { if (cfg_inited) return; - is_blacklisted(true); + parse_overlay_config(¶ms, getenv("MANGOHUD_CONFIG")); + + //check for blacklist item in the config file + for (auto& item : params.blacklist) { + add_blacklist(item); + } + + is_blacklisted(true); notifier.params = ¶ms; start_notifier(notifier); window_size = ImVec2(params.width, params.height);