perf_overlays: add avg and 1p high/low

This commit is contained in:
Megamouse 2021-05-19 21:14:49 +02:00
parent f103004aa0
commit 98b668b3a8
9 changed files with 129 additions and 20 deletions

View File

@ -1131,9 +1131,15 @@ namespace rsx
color4f m_color;
f32 m_min{};
f32 m_max{};
f32 m_avg{};
f32 m_1p{};
f32 m_guide_interval{};
label m_label{};
bool m_show_min_max{false};
bool m_show_1p_avg{false};
bool m_1p_sort_high{false};
public:
graph();
void set_pos(u16 _x, u16 _y) override;
@ -1144,6 +1150,8 @@ namespace rsx
void set_count(u32 datapoint_count);
void set_color(color4f color);
void set_guide_interval(f32 guide_interval);
void set_labels_visible(bool show_min_max, bool show_1p_avg);
void set_one_percent_sort_high(bool sort_1p_high);
u16 get_height() const;
u32 get_datapoint_count() const;
void record_datapoint(f32 datapoint);

View File

@ -244,6 +244,9 @@ namespace rsx
void perf_metrics_overlay::init()
{
m_fps_graph.set_one_percent_sort_high(false);
m_frametime_graph.set_one_percent_sort_high(true);
reset_transforms();
force_next_update();
@ -271,7 +274,7 @@ namespace rsx
if (enabled)
{
m_fps_graph.set_title(" Framerate");
m_fps_graph.set_title("Framerate: 00.0");
m_fps_graph.set_font_size(static_cast<u16>(m_font_size * 0.8));
m_fps_graph.set_color(convert_color_code(m_color_body, m_opacity));
m_fps_graph.set_guide_interval(10);
@ -289,7 +292,7 @@ namespace rsx
if (enabled)
{
m_frametime_graph.set_title(" Frametime");
m_frametime_graph.set_title("Frametime: 0.0");
m_frametime_graph.set_font_size(static_cast<u16>(m_font_size * 0.8));
m_frametime_graph.set_color(convert_color_code(m_color_body, m_opacity));
m_frametime_graph.set_guide_interval(8);
@ -316,6 +319,18 @@ namespace rsx
m_force_repaint = true;
}
void perf_metrics_overlay::set_graph_detail_levels(perf_graph_detail_level framerate_level, perf_graph_detail_level frametime_level)
{
m_fps_graph.set_labels_visible(
framerate_level == perf_graph_detail_level::show_all || framerate_level == perf_graph_detail_level::show_min_max,
framerate_level == perf_graph_detail_level::show_all || framerate_level == perf_graph_detail_level::show_one_percent_avg);
m_frametime_graph.set_labels_visible(
frametime_level == perf_graph_detail_level::show_all || frametime_level == perf_graph_detail_level::show_min_max,
frametime_level == perf_graph_detail_level::show_all || frametime_level == perf_graph_detail_level::show_one_percent_avg);
m_force_repaint = true;
}
void perf_metrics_overlay::set_detail_level(detail_level level)
{
if (m_detail == level)
@ -420,9 +435,10 @@ namespace rsx
{
if (m_frametime_graph_enabled && !m_force_update)
{
const auto elapsed_frame = m_frametime_timer.GetElapsedTimeInMilliSec();
const float elapsed_frame = static_cast<float>(m_frametime_timer.GetElapsedTimeInMilliSec());
m_frametime_timer.Start();
m_frametime_graph.record_datapoint(static_cast<float>(elapsed_frame));
m_frametime_graph.record_datapoint(elapsed_frame);
m_frametime_graph.set_title(fmt::format("Frametime: %4.1f", elapsed_frame).c_str());
}
if (m_force_repaint)
@ -495,7 +511,10 @@ namespace rsx
{
m_fps = std::max(0.f, static_cast<f32>(m_frames / (elapsed_update / 1000)));
if (m_is_initialised && m_framerate_graph_enabled)
{
m_fps_graph.record_datapoint(m_fps);
m_fps_graph.set_title(fmt::format("Framerate: %04.1f", m_fps).c_str());
}
break;
}
}
@ -680,6 +699,17 @@ namespace rsx
m_guide_interval = guide_interval;
}
void graph::set_labels_visible(bool show_min_max, bool show_1p_avg)
{
m_show_min_max = show_min_max;
m_show_1p_avg = show_1p_avg;
}
void graph::set_one_percent_sort_high(bool sort_1p_high)
{
m_1p_sort_high = sort_1p_high;
}
u16 graph::get_height() const
{
return h + m_label.h + m_label.padding_top + m_label.padding_bottom;
@ -699,23 +729,53 @@ namespace rsx
// Record datapoint
m_datapoints.push_back(datapoint);
// Calculate new min/max
m_min = max_v<f32>;
m_max = 0.0f;
m_avg = 0.0f;
m_1p = 0.0f;
// Make sure min/max reflects the data being displayed, not the entire datapoints vector
for (usz i = m_datapoints.size() - m_datapoint_count; i < m_datapoints.size(); i++)
if (m_show_min_max || m_show_1p_avg)
{
const f32& dp = m_datapoints[i];
m_min = max_v<f32>;
if (dp < 0) continue; // Skip initial negative values. They don't count.
std::vector<f32> valid_datapoints;
m_min = std::min(m_min, dp);
m_max = std::max(m_max, dp);
// Make sure min/max reflects the data being displayed, not the entire datapoints vector
for (usz i = m_datapoints.size() - m_datapoint_count; i < m_datapoints.size(); i++)
{
const f32& dp = m_datapoints[i];
if (dp < 0) continue; // Skip initial negative values. They don't count.
m_min = std::min(m_min, dp);
m_max = std::max(m_max, dp);
m_avg += dp;
valid_datapoints.push_back(dp);
}
// Sanitize min value
m_min = std::min(m_min, m_max);
if (m_show_1p_avg && valid_datapoints.size())
{
// Sort datapoints (we are only interested in the lowest/highest 1%)
const usz i_1p = valid_datapoints.size() / 100;
const usz n_1p = i_1p + 1;
if (m_1p_sort_high)
std::nth_element(valid_datapoints.begin(), valid_datapoints.begin() + i_1p, valid_datapoints.end(), std::greater<f32>());
else
std::nth_element(valid_datapoints.begin(), valid_datapoints.begin() + i_1p, valid_datapoints.end());
// Calculate statistics
m_avg /= valid_datapoints.size();
m_1p = std::accumulate(valid_datapoints.begin(), valid_datapoints.begin() + n_1p, 0.0f) / static_cast<float>(n_1p);
}
}
else
{
m_min = 0.0f;
}
// Sanitize min value
m_min = std::min(m_min, m_max);
// Cull vector when it gets large
if (m_datapoints.size() > m_datapoint_count * 16ull)
@ -727,7 +787,19 @@ namespace rsx
void graph::update()
{
m_label.set_text(fmt::format("%s\nmn:%4.1f mx:%4.1f", m_title.c_str(), m_min, m_max));
std::string fps_info = m_title;
if (m_show_1p_avg)
{
fmt::append(fps_info, "\n1%%:%4.1f av:%4.1f", m_1p, m_avg);
}
if (m_show_min_max)
{
fmt::append(fps_info, "\nmn:%4.1f mx:%4.1f", m_min, m_max);
}
m_label.set_text(fps_info);
m_label.set_padding(4, 4, 0, 4);
m_label.auto_resize();
@ -827,6 +899,7 @@ namespace rsx
perf_overlay->set_frametime_datapoint_count(perf_settings.frametime_datapoint_count);
perf_overlay->set_framerate_graph_enabled(perf_settings.framerate_graph_enabled.get());
perf_overlay->set_frametime_graph_enabled(perf_settings.frametime_graph_enabled.get());
perf_overlay->set_graph_detail_levels(perf_settings.framerate_graph_detail_level.get(), perf_settings.frametime_graph_detail_level.get());
perf_overlay->init();
}
else if (perf_overlay)

View File

@ -89,6 +89,7 @@ namespace rsx
void set_frametime_graph_enabled(bool enabled);
void set_framerate_datapoint_count(u32 datapoint_count);
void set_frametime_datapoint_count(u32 datapoint_count);
void set_graph_detail_levels(perf_graph_detail_level framerate_level, perf_graph_detail_level frametime_level);
void set_detail_level(detail_level level);
void set_position(screen_quadrant quadrant);
void set_update_interval(u32 update_interval);

View File

@ -190,6 +190,8 @@ struct cfg_root : cfg::node
cfg::uint<2, 6000> framerate_datapoint_count{ this, "Framerate datapoints", 50, true };
cfg::uint<2, 6000> frametime_datapoint_count{ this, "Frametime datapoints", 170, true };
cfg::_enum<detail_level> level{ this, "Detail level", detail_level::medium, true };
cfg::_enum<perf_graph_detail_level> framerate_graph_detail_level{ this, "Framerate graph detail level", perf_graph_detail_level::show_all, true };
cfg::_enum<perf_graph_detail_level> frametime_graph_detail_level{ this, "Frametime graph detail level", perf_graph_detail_level::show_all, true };
cfg::uint<1, 1000> update_interval{ this, "Metrics update interval (ms)", 350, true };
cfg::uint<4, 36> font_size{ this, "Font size (px)", 10, true };
cfg::_enum<screen_quadrant> position{ this, "Position", screen_quadrant::top_left, true };

View File

@ -143,6 +143,23 @@ void fmt_class_string<detail_level>::format(std::string& out, u64 arg)
});
}
template <>
void fmt_class_string<perf_graph_detail_level>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](perf_graph_detail_level value)
{
switch (value)
{
case perf_graph_detail_level::minimal: return "Minimal";
case perf_graph_detail_level::show_min_max: return "Show min and max";
case perf_graph_detail_level::show_one_percent_avg: return "Show 1% and average";
case perf_graph_detail_level::show_all: return "All";
}
return unknown;
});
}
template <>
void fmt_class_string<screen_quadrant>::format(std::string& out, u64 arg)
{

View File

@ -208,3 +208,11 @@ enum class thread_scheduler_mode
old,
alt
};
enum class perf_graph_detail_level
{
minimal,
show_min_max,
show_one_percent_avg,
show_all
};

View File

@ -53,7 +53,7 @@ bool hid_pad_handler<Device>::Init()
if (res != 0)
fmt::throw_exception("%s hidapi-init error.threadproc", m_type);
for (size_t i = 1; i <= MAX_GAMEPADS; i++) // Controllers 1-n in GUI
for (usz i = 1; i <= MAX_GAMEPADS; i++) // Controllers 1-n in GUI
{
m_controllers.emplace(m_name_string + std::to_string(i), std::make_shared<Device>());
}
@ -167,7 +167,7 @@ void hid_pad_handler<Device>::enumerate_devices()
}
else
{
const size_t count = std::count_if(m_controllers.cbegin(), m_controllers.cend(), [](const auto& c) { return c.second && c.second->hidDevice; });
const usz count = std::count_if(m_controllers.cbegin(), m_controllers.cend(), [](const auto& c) { return c.second && c.second->hidDevice; });
if (count > 0)
{
hid_log.success("%s Controllers found: %d", m_type, count);

View File

@ -499,7 +499,7 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
default: break;
}
if (const size_t pos = std::basic_string_view<u32>(res.data(), 2).find_last_not_of(umax); pos != umax)
if (const usz pos = std::basic_string_view<u32>(res.data(), 2).find_last_not_of(umax); pos != umax)
m_debugger_list->ShowAddress(res[pos] - std::max(row, 0) * 4, true, true);
return;

View File

@ -686,7 +686,7 @@ void main_window::HandlePackageInstallation(QStringList file_paths)
bool cancelled = false;
for (size_t i = 0, count = packages.size(); i < count; i++)
for (usz i = 0, count = packages.size(); i < count; i++)
{
progress = 0.;