add fps_metrics param

fps_metrics takes a list of decimal value between 0.001-0.9 or avg
winesync
flightlessmango 6 months ago
parent f351515265
commit 48f8db420b

@ -352,7 +352,8 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu
| `fps_limit` | Limit the apps framerate. Comma-separated list of one or more FPS values. `0` means unlimited |
| `fps_only` | Show FPS only. ***Not meant to be used with other display params*** |
| `fps_sampling_period=` | Time interval between two sampling points for gathering the FPS in milliseconds. Default is `500` |
| `fps_value=` | Choose the break points where `fps_color_change` changes colors between. E.g `60,144`, default is `30,60` |
| `fps_value` | Choose the break points where `fps_color_change` changes colors between. E.g `60,144`, default is `30,60` |
| `fps_metrics` | Takes a list of decimal values or the value avg, e.g `avg,0.001` |
| `frame_count` | Display frame count |
| `frametime` | Display frametime next to FPS text |
| `fsr` | Display the status of FSR (only works in gamescope) |

@ -135,6 +135,8 @@ fps
# fps_color=B22222,FDFD09,39F900
frametime
# frame_count
## fps_metrics takes a list of decimal values or the value avg
# fps_metrics=avg,0.01
### Display GPU throttling status based on Power, current, temp or "other"
## Only shows if throttling is currently happening

@ -0,0 +1,134 @@
#pragma once
#include <vector>
#include <string>
#include <memory>
#include <thread>
#include <mesa/util/os_time.h>
#include <numeric>
#include <mutex>
#include <algorithm>
#include <condition_variable>
#include <stdexcept>
struct metric_t {
std::string name;
float value;
std::string display_name;
};
class fpsMetrics {
private:
std::vector<std::pair<uint64_t, float>> fps_stats;
std::thread thread;
std::mutex mtx;
std::condition_variable cv;
bool run = false;
bool thread_init = false;
bool terminate = false;
void calculate(){
thread_init = true;
while (!terminate){
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [this] { return run; });
std::vector<float> sorted_values;
for (const auto& p : fps_stats)
sorted_values.push_back(p.second);
std::sort(sorted_values.begin(), sorted_values.end());
auto it = metrics.begin();
while (it != metrics.end()) {
if (it->name == "AVG") {
it->display_name = it->name;
if (!fps_stats.empty()) {
float sum = std::accumulate(fps_stats.begin(), fps_stats.end(), 0.0f,
[](float acc, const std::pair<uint64_t, float>& p) {
return acc + p.second;
});
it->value = sum / fps_stats.size();
++it;
}
} else {
try {
float val = std::stof(it->name);
if (val <= 0 || val >= 1 ) {
SPDLOG_DEBUG("Failed to use fps metric, it's out of range {}", it->name);
it = metrics.erase(it);
break;
}
float multiplied_val = val * 100;
std::ostringstream stream;
if (multiplied_val == static_cast<int>(multiplied_val)) {
stream << std::fixed << std::setprecision(0) << multiplied_val << "%";
} else {
stream << std::fixed << std::setprecision(1) << multiplied_val << "%";
}
it->display_name = stream.str();
uint64_t idx = val * sorted_values.size() - 1;
it->value = sorted_values[idx];
++it;
} catch (const std::invalid_argument& e) {
SPDLOG_DEBUG("Failed to use fps metric value {}", it->name);
it = metrics.erase(it);
}
}
}
run = false;
}
}
public:
std::vector<metric_t> metrics;
fpsMetrics(std::vector<std::string> values){
// capitalize string
for (auto& val : values){
for(char& c : val) {
c = std::toupper(static_cast<unsigned char>(c));
}
metrics.push_back({val, 0.0f});
}
if (!thread_init){
thread = std::thread(&fpsMetrics::calculate, this);
}
};
void update(uint64_t now, double fps){
fps_stats.push_back({now, fps});
// Calculate the cut-off nanotime (10 minutes ago)
uint64_t ten_minutes_ns = 600000000000ULL; // 10 minutes in nanoseconds
uint64_t cutoff_time_ns = os_time_get_nano() - ten_minutes_ns;
// Removing elements older than 10 minutes
fps_stats.erase(std::remove_if(fps_stats.begin(), fps_stats.end(),
[cutoff_time_ns](const std::pair<uint64_t, float>& p) {
return p.first < cutoff_time_ns;
}),
fps_stats.end());
};
void update_thread(){
{
std::lock_guard<std::mutex> lock(mtx);
run = true;
}
cv.notify_one();
}
~fpsMetrics(){
terminate = true;
{
std::lock_guard<std::mutex> lock(mtx);
run = true;
}
cv.notify_one();
thread.join();
}
};
extern std::unique_ptr<fpsMetrics> fpsmetrics;

@ -84,6 +84,7 @@ class HudElements{
static void throttling_status();
static void exec_name();
static void duration();
static void fps_metrics();
void convert_colors(const struct overlay_params& params);
void convert_colors(bool do_conv, const struct overlay_params& params);

@ -23,7 +23,7 @@
#include "pci_ids.h"
#include "iostats.h"
#include "amdgpu.h"
#include "fps_metrics.h"
#ifdef __linux__
#include <libgen.h>
@ -256,12 +256,15 @@ void update_hud_info_with_frametime(struct swapchain_stats& sw_stats, const stru
#endif
frametime = frametime_ms;
fps = double(1000 / frametime_ms);
if (fpsmetrics) fpsmetrics->update(now, fps);
if (elapsed >= params.fps_sampling_period) {
if (!hw_update_thread)
hw_update_thread = std::make_unique<hw_info_updater>();
hw_update_thread->update(&params, vendorID);
if (fpsmetrics) fpsmetrics->update_thread();
sw_stats.fps = 1000000000.0 * sw_stats.n_frames_since_update / elapsed;
if (params.enabled[OVERLAY_PARAM_ENABLED_time]) {

@ -38,6 +38,9 @@
#include "dbus_info.h"
#include "app/mangoapp.h"
#include "fps_metrics.h"
std::unique_ptr<fpsMetrics> fpsmetrics;
#if __cplusplus >= 201703L
@ -414,6 +417,20 @@ parse_gl_size_query(const char *str)
return GL_SIZE_DRAWABLE;
}
static std::vector<std::string>
parse_fps_metrics(const char *str){
std::vector<std::string> metrics;
auto tokens = str_tokenize(str);
for (auto& token : tokens) {
metrics.push_back(token);
}
fpsmetrics.release();
fpsmetrics = std::make_unique<fpsMetrics>(metrics);
return metrics;
}
#define parse_width(s) parse_unsigned(s)
#define parse_height(s) parse_unsigned(s)
#define parse_vsync(s) parse_unsigned(s)

@ -186,6 +186,7 @@ typedef unsigned long KeySym;
OVERLAY_PARAM_CUSTOM(text_outline_thickness) \
OVERLAY_PARAM_CUSTOM(fps_text) \
OVERLAY_PARAM_CUSTOM(device_battery) \
OVERLAY_PARAM_CUSTOM(fps_metrics) \
enum overlay_param_position {
LAYER_POSITION_TOP_LEFT,
@ -306,6 +307,7 @@ struct overlay_params {
unsigned text_outline_color;
float text_outline_thickness;
std::vector<std::string> device_battery;
std::vector<std::string> fps_metrics;
};
const extern char *overlay_param_names[];

Loading…
Cancel
Save