diff --git a/bin/MangoHud.conf b/bin/MangoHud.conf index 24943c95..afd3b2f3 100644 --- a/bin/MangoHud.conf +++ b/bin/MangoHud.conf @@ -166,6 +166,17 @@ frame_timing # background_alpha=0.5 # alpha= +### FCAT overlay +### This enables an FCAT overlay to perform frametime analysis on the final image stream. +### Enable the overlay +# fcat +### Set the width of the FCAT overlay. +### 24 is a performance optimization on AMD GPUs that should not have adverse effects on nVidia GPUs. +### A minimum of 20 pixels is recommended by nVidia. +# fcat_overlay_width=24 +### Set the screen edge, this can be useful for special displays that don't update from top edge to bottom. This goes from 0 (left side) to 3 (top edge), counter-clockwise. +# fcat_screen_edge=0 + ### Color customization # text_color=FFFFFF # gpu_color=2E9762 diff --git a/src/fcat.h b/src/fcat.h new file mode 100644 index 00000000..a79045ff --- /dev/null +++ b/src/fcat.h @@ -0,0 +1,63 @@ +#pragma once +#ifndef MANGOHUD_FCAT_H +#define MANGOHUD_FCAT_H + +#include +#include +#include +#include +#include +#include +#include + +#include "timing.hpp" + +#include "overlay_params.h" +#include "overlay.h" + +struct fcatoverlay{ + const struct overlay_params* params = nullptr; + const std::array sequence={{{255, 255, 255},{0, 255, 0},{0, 0, 255},{255, 0, 0},{0, 128, 128},{0, 0, 128},{0, 128, 0},{0, 255, 255},{128, 0, 0},{192, 192, 192},{128, 0, 128},{128, 128, 0},{128, 128, 128},{255, 0, 255},{255, 255, 0},{255, 128, 0}}}; + void update(const struct overlay_params* params_){ + params=params_; + }; + ImColor get_next_color (const swapchain_stats& sw_stats){ + size_t currentColor = sw_stats.n_frames % 16;// should probably be sequence.size(); but this doesn't matter as all FCAT analysis tools use this exact 16 colour sequence. + ImColor output = sequence[currentColor]; + return output; + }; + std::array get_overlay_corners() + { + unsigned short screen_edge=params->fcat_screen_edge; + auto window_size = ImVec2(params->fcat_overlay_width,ImGui::GetIO().DisplaySize.y); + auto p_min = ImVec2(0.,0.); + auto p_max = ImVec2(window_size.x,ImGui::GetIO().DisplaySize.y); + //Switch the used screen edge, this enables capture from devices with any screen orientation. + //This goes counter-clockwise from the left edge (0) + switch (screen_edge) + { + default: + case 0: + break; + case 1: + window_size = ImVec2(ImGui::GetIO().DisplaySize.x,window_size.x); + p_min = ImVec2(0,ImGui::GetIO().DisplaySize.y - window_size.y); + p_max = ImVec2(ImGui::GetIO().DisplaySize.x,ImGui::GetIO().DisplaySize.y); + break; + case 2: + window_size = ImVec2(window_size.x,ImGui::GetIO().DisplaySize.y); + p_min = ImVec2(ImGui::GetIO().DisplaySize.x-window_size.x,0); + p_max = ImVec2(ImGui::GetIO().DisplaySize.x,ImGui::GetIO().DisplaySize.y); + break; + case 3: + window_size = ImVec2(ImGui::GetIO().DisplaySize.x,window_size.x); + p_min = ImVec2(0,0); + p_max = ImVec2(ImGui::GetIO().DisplaySize.x,window_size.y); + break; + } + std::array output={{p_min,p_max,window_size}}; + return output; + }; +}; + +#endif diff --git a/src/overlay.cpp b/src/overlay.cpp index 9e1e8e09..05d91a1d 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -14,6 +14,7 @@ #include "gpu.h" #include "memory.h" #include "timing.hpp" +#include "fcat.h" #include "mesa/util/macros.h" #include "battery.h" #include "gamepad.h" @@ -38,6 +39,7 @@ float g_overflow = 50.f /* 3333ms * 0.5 / 16.6667 / 2 (to edge and back) */; string gpuString,wineVersion,wineProcess; uint32_t deviceID; bool gui_open = false; +bool fcat_open = false; struct benchmark_stats benchmark; struct fps_limit fps_limit_stats {}; ImVec2 real_font_size; @@ -49,6 +51,7 @@ bool gpu_metrics_exists = false; bool steam_focused = false; vector frametime_data(200,0.f); int fan_speed; +fcatoverlay fcatstatus; void init_spdlog() { @@ -568,6 +571,22 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if((now - logger->last_log_end()) < 12s && !logger->is_active()) render_benchmark(data, params, window_size, height, now); } + + if(params.enabled[OVERLAY_PARAM_ENABLED_fcat]) + { + fcatstatus.update(¶ms); + auto window_corners = fcatstatus.get_overlay_corners(); + auto p_min=window_corners[0]; + auto p_max=window_corners[1]; + auto window_size= window_corners[2]; + ImGui::SetNextWindowPos(p_min, ImGuiCond_Always); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0,0)); + ImGui::SetNextWindowSize(window_size); + ImGui::Begin("FCAT", &fcat_open, ImGuiWindowFlags_NoDecoration| ImGuiWindowFlags_NoBackground); + ImGui::GetWindowDrawList()->AddRectFilled(p_min,p_max,fcatstatus.get_next_color(data),0.0); + ImGui::End(); + ImGui::PopStyleVar(); + } } void init_cpu_stats(overlay_params& params) diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 0e8e93ec..fdaa8741 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -402,6 +402,8 @@ parse_gl_size_query(const char *str) #define parse_gl_bind_framebuffer(s) parse_unsigned(s) #define parse_gl_dont_flip(s) parse_unsigned(s) != 0 #define parse_round_corners(s) parse_unsigned(s) +#define parse_fcat_overlay_width(s) parse_unsigned(s) +#define parse_fcat_screen_edge(s) parse_unsigned(s) #define parse_cpu_color(s) parse_color(s) #define parse_gpu_color(s) parse_color(s) @@ -578,6 +580,7 @@ parse_overlay_config(struct overlay_params *params, params->enabled[OVERLAY_PARAM_ENABLED_gamepad_battery] = false; params->enabled[OVERLAY_PARAM_ENABLED_gamepad_battery_icon] = true; params->enabled[OVERLAY_PARAM_ENABLED_throttling_status] = false; + params->enabled[OVERLAY_PARAM_ENABLED_fcat] = false; params->fps_sampling_period = 500000000; /* 500ms */ params->width = 0; params->height = 140; @@ -589,6 +592,8 @@ parse_overlay_config(struct overlay_params *params, params->offset_y = 0; params->background_alpha = 0.5; params->alpha = 1.0; + params->fcat_screen_edge = 0; + params->fcat_overlay_width = 24; params->time_format = "%T"; params->gpu_color = 0x2e9762; params->cpu_color = 0x2e97cb; diff --git a/src/overlay_params.h b/src/overlay_params.h index c070e277..7977edfe 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -83,6 +83,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_BOOL(hide_fsr_sharpness) \ OVERLAY_PARAM_BOOL(fan) \ OVERLAY_PARAM_BOOL(throttling_status) \ + OVERLAY_PARAM_BOOL(fcat) \ OVERLAY_PARAM_CUSTOM(fps_sampling_period) \ OVERLAY_PARAM_CUSTOM(output_folder) \ OVERLAY_PARAM_CUSTOM(output_file) \ @@ -152,6 +153,8 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(autostart_log) \ OVERLAY_PARAM_CUSTOM(round_corners) \ OVERLAY_PARAM_CUSTOM(fsr_steam_sharpness) \ + OVERLAY_PARAM_CUSTOM(fcat_screen_edge) \ + OVERLAY_PARAM_CUSTOM(fcat_overlay_width) \ enum overlay_param_position { LAYER_POSITION_TOP_LEFT, @@ -252,6 +255,8 @@ struct overlay_params { std::unordered_map options; int permit_upload; int fsr_steam_sharpness; + unsigned short fcat_screen_edge; + unsigned short fcat_overlay_width; size_t font_params_hash; };