System: Add frame time graph

This commit is contained in:
Connor McLaughlin 2023-01-07 13:09:20 +10:00
parent fa2fd8f84f
commit 19b4f4e921
8 changed files with 203 additions and 22 deletions

View file

@ -264,6 +264,7 @@ void Settings::Load(SettingsInterface& si)
display_show_resolution = si.GetBoolValue("Display", "ShowResolution", false); display_show_resolution = si.GetBoolValue("Display", "ShowResolution", false);
display_show_cpu = si.GetBoolValue("Display", "ShowCPU", false); display_show_cpu = si.GetBoolValue("Display", "ShowCPU", false);
display_show_gpu = si.GetBoolValue("Display", "ShowGPU", false); display_show_gpu = si.GetBoolValue("Display", "ShowGPU", false);
display_show_frame_times = si.GetBoolValue("Display", "ShowFrameTimes", false);
display_show_status_indicators = si.GetBoolValue("Display", "ShowStatusIndicators", true); display_show_status_indicators = si.GetBoolValue("Display", "ShowStatusIndicators", true);
display_show_inputs = si.GetBoolValue("Display", "ShowInputs", false); display_show_inputs = si.GetBoolValue("Display", "ShowInputs", false);
display_show_enhancements = si.GetBoolValue("Display", "ShowEnhancements", false); display_show_enhancements = si.GetBoolValue("Display", "ShowEnhancements", false);
@ -478,6 +479,7 @@ void Settings::Save(SettingsInterface& si) const
si.SetBoolValue("Display", "ShowResolution", display_show_resolution); si.SetBoolValue("Display", "ShowResolution", display_show_resolution);
si.SetBoolValue("Display", "ShowCPU", display_show_cpu); si.SetBoolValue("Display", "ShowCPU", display_show_cpu);
si.SetBoolValue("Display", "ShowGPU", display_show_gpu); si.SetBoolValue("Display", "ShowGPU", display_show_gpu);
si.SetBoolValue("Display", "ShowFrameTimes", display_show_frame_times);
si.SetBoolValue("Display", "ShowStatusIndicators", display_show_status_indicators); si.SetBoolValue("Display", "ShowStatusIndicators", display_show_status_indicators);
si.SetBoolValue("Display", "ShowInputs", display_show_inputs); si.SetBoolValue("Display", "ShowInputs", display_show_inputs);
si.SetBoolValue("Display", "ShowEnhancements", display_show_enhancements); si.SetBoolValue("Display", "ShowEnhancements", display_show_enhancements);

View file

@ -137,6 +137,7 @@ struct Settings
bool display_show_resolution = false; bool display_show_resolution = false;
bool display_show_cpu = false; bool display_show_cpu = false;
bool display_show_gpu = false; bool display_show_gpu = false;
bool display_show_frame_times = false;
bool display_show_status_indicators = true; bool display_show_status_indicators = true;
bool display_show_inputs = false; bool display_show_inputs = false;
bool display_show_enhancements = false; bool display_show_enhancements = false;

View file

@ -155,12 +155,14 @@ static bool s_display_all_frames = true;
static bool s_syncing_to_host = false; static bool s_syncing_to_host = false;
static float s_average_frame_time_accumulator = 0.0f; static float s_average_frame_time_accumulator = 0.0f;
static float s_worst_frame_time_accumulator = 0.0f; static float s_minimum_frame_time_accumulator = 0.0f;
static float s_maximum_frame_time_accumulator = 0.0f;
static float s_vps = 0.0f; static float s_vps = 0.0f;
static float s_fps = 0.0f; static float s_fps = 0.0f;
static float s_speed = 0.0f; static float s_speed = 0.0f;
static float s_worst_frame_time = 0.0f; static float s_minimum_frame_time = 0.0f;
static float s_maximum_frame_time = 0.0f;
static float s_average_frame_time = 0.0f; static float s_average_frame_time = 0.0f;
static float s_cpu_thread_usage = 0.0f; static float s_cpu_thread_usage = 0.0f;
static float s_cpu_thread_time = 0.0f; static float s_cpu_thread_time = 0.0f;
@ -169,6 +171,8 @@ static float s_sw_thread_time = 0.0f;
static float s_average_gpu_time = 0.0f; static float s_average_gpu_time = 0.0f;
static float s_accumulated_gpu_time = 0.0f; static float s_accumulated_gpu_time = 0.0f;
static float s_gpu_usage = 0.0f; static float s_gpu_usage = 0.0f;
static System::FrameTimeHistory s_frame_time_history;
static u32 s_frame_time_history_pos = 0;
static u32 s_last_frame_number = 0; static u32 s_last_frame_number = 0;
static u32 s_last_internal_frame_number = 0; static u32 s_last_internal_frame_number = 0;
static u32 s_last_global_tick_counter = 0; static u32 s_last_global_tick_counter = 0;
@ -339,9 +343,13 @@ float System::GetAverageFrameTime()
{ {
return s_average_frame_time; return s_average_frame_time;
} }
float System::GetWorstFrameTime() float System::GetMinimumFrameTime()
{ {
return s_worst_frame_time; return s_minimum_frame_time;
}
float System::GetMaximumFrameTime()
{
return s_maximum_frame_time;
} }
float System::GetThrottleFrequency() float System::GetThrottleFrequency()
{ {
@ -371,6 +379,14 @@ float System::GetGPUAverageTime()
{ {
return s_average_gpu_time; return s_average_gpu_time;
} }
const System::FrameTimeHistory& System::GetFrameTimeHistory()
{
return s_frame_time_history;
}
u32 System::GetFrameTimeHistoryPos()
{
return s_frame_time_history_pos;
}
bool System::IsExeFileName(const std::string_view& path) bool System::IsExeFileName(const std::string_view& path)
{ {
@ -802,6 +818,7 @@ void System::SetDefaultSettings(SettingsInterface& si)
temp.display_show_resolution = g_settings.display_show_resolution; temp.display_show_resolution = g_settings.display_show_resolution;
temp.display_show_cpu = g_settings.display_show_cpu; temp.display_show_cpu = g_settings.display_show_cpu;
temp.display_show_gpu = g_settings.display_show_gpu; temp.display_show_gpu = g_settings.display_show_gpu;
temp.display_show_frame_times = g_settings.display_show_frame_times;
// keep controller, we reset it elsewhere // keep controller, we reset it elsewhere
for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++) for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++)
@ -1305,12 +1322,14 @@ bool System::Initialize(bool force_software_renderer)
s_fast_forward_enabled = false; s_fast_forward_enabled = false;
s_average_frame_time_accumulator = 0.0f; s_average_frame_time_accumulator = 0.0f;
s_worst_frame_time_accumulator = 0.0f; s_minimum_frame_time_accumulator = 0.0f;
s_maximum_frame_time_accumulator = 0.0f;
s_vps = 0.0f; s_vps = 0.0f;
s_fps = 0.0f; s_fps = 0.0f;
s_speed = 0.0f; s_speed = 0.0f;
s_worst_frame_time = 0.0f; s_minimum_frame_time = 0.0f;
s_maximum_frame_time = 0.0f;
s_average_frame_time = 0.0f; s_average_frame_time = 0.0f;
s_cpu_thread_usage = 0.0f; s_cpu_thread_usage = 0.0f;
s_cpu_thread_time = 0.0f; s_cpu_thread_time = 0.0f;
@ -1326,6 +1345,8 @@ bool System::Initialize(bool force_software_renderer)
s_last_cpu_time = 0; s_last_cpu_time = 0;
s_fps_timer.Reset(); s_fps_timer.Reset();
s_frame_timer.Reset(); s_frame_timer.Reset();
s_frame_time_history.fill(0.0f);
s_frame_time_history_pos = 0;
TimingEvents::Initialize(); TimingEvents::Initialize();
@ -2092,8 +2113,6 @@ void System::DoRunFrame()
void System::RunFrame() void System::RunFrame()
{ {
s_frame_timer.Reset();
if (s_rewind_load_counter >= 0) if (s_rewind_load_counter >= 0)
{ {
DoRewind(); DoRewind();
@ -2183,9 +2202,12 @@ void System::RunFrames()
void System::UpdatePerformanceCounters() void System::UpdatePerformanceCounters()
{ {
const float frame_time = static_cast<float>(s_frame_timer.GetTimeMilliseconds()); const float frame_time = static_cast<float>(s_frame_timer.GetTimeMillisecondsAndReset());
s_minimum_frame_time_accumulator = (s_minimum_frame_time_accumulator == 0.0f) ? frame_time : std::min(s_minimum_frame_time_accumulator, frame_time);
s_average_frame_time_accumulator += frame_time; s_average_frame_time_accumulator += frame_time;
s_worst_frame_time_accumulator = std::max(s_worst_frame_time_accumulator, frame_time); s_maximum_frame_time_accumulator = std::max(s_maximum_frame_time_accumulator, frame_time);
s_frame_time_history[s_frame_time_history_pos] = frame_time;
s_frame_time_history_pos = (s_frame_time_history_pos + 1) % NUM_FRAME_TIME_SAMPLES;
// update fps counter // update fps counter
const Common::Timer::Value now_ticks = Common::Timer::GetCurrentValue(); const Common::Timer::Value now_ticks = Common::Timer::GetCurrentValue();
@ -2204,10 +2226,10 @@ void System::UpdatePerformanceCounters()
const double time_divider = 1000.0 * (1.0 / static_cast<double>(Threading::GetThreadTicksPerSecond())) * const double time_divider = 1000.0 * (1.0 / static_cast<double>(Threading::GetThreadTicksPerSecond())) *
(1.0 / static_cast<double>(frames_run)); (1.0 / static_cast<double>(frames_run));
s_worst_frame_time = s_worst_frame_time_accumulator; s_minimum_frame_time = std::exchange(s_minimum_frame_time_accumulator, 0.0f);
s_worst_frame_time_accumulator = 0.0f; s_average_frame_time = std::exchange(s_average_frame_time_accumulator, 0.0f) / frames_run;
s_average_frame_time = s_average_frame_time_accumulator / frames_run; s_maximum_frame_time = std::exchange(s_maximum_frame_time_accumulator, 0.0f);
s_average_frame_time_accumulator = 0.0f;
s_vps = static_cast<float>(frames_run / time); s_vps = static_cast<float>(frames_run / time);
s_last_frame_number = s_frame_number; s_last_frame_number = s_frame_number;
s_fps = static_cast<float>(s_internal_frame_number - s_last_internal_frame_number) / time; s_fps = static_cast<float>(s_internal_frame_number - s_last_internal_frame_number) / time;
@ -2240,8 +2262,8 @@ void System::UpdatePerformanceCounters()
s_accumulated_gpu_time = 0.0f; s_accumulated_gpu_time = 0.0f;
s_presents_since_last_update = 0; s_presents_since_last_update = 0;
Log_VerbosePrintf("FPS: %.2f VPS: %.2f CPU: %.2f GPU: %.2f Average: %.2fms Worst: %.2fms", s_fps, s_vps, Log_VerbosePrintf("FPS: %.2f VPS: %.2f CPU: %.2f GPU: %.2f Average: %.2fms Min: %.2fms Max: %.2f ms", s_fps, s_vps,
s_cpu_thread_usage, s_gpu_usage, s_average_frame_time, s_worst_frame_time); s_cpu_thread_usage, s_gpu_usage, s_average_frame_time, s_minimum_frame_time, s_maximum_frame_time);
Host::OnPerformanceCountersUpdated(); Host::OnPerformanceCountersUpdated();
} }
@ -2258,7 +2280,9 @@ void System::ResetPerformanceCounters()
s_last_sw_time = 0; s_last_sw_time = 0;
s_average_frame_time_accumulator = 0.0f; s_average_frame_time_accumulator = 0.0f;
s_worst_frame_time_accumulator = 0.0f; s_minimum_frame_time_accumulator = 0.0f;
s_maximum_frame_time_accumulator = 0.0f;
s_frame_timer.Reset();
s_fps_timer.Reset(); s_fps_timer.Reset();
ResetThrottler(); ResetThrottler();
} }
@ -3491,8 +3515,6 @@ void System::SetRewinding(bool enabled)
void System::DoRewind() void System::DoRewind()
{ {
s_frame_timer.Reset();
if (s_rewind_load_counter == 0) if (s_rewind_load_counter == 0)
{ {
const u32 skip_saves = BoolToUInt32(!s_rewinding_first_save); const u32 skip_saves = BoolToUInt32(!s_rewinding_first_save);

View file

@ -176,11 +176,15 @@ const std::string& GetRunningTitle();
bool IsRunningBIOS(); bool IsRunningBIOS();
// TODO: Move to PerformanceMetrics // TODO: Move to PerformanceMetrics
static constexpr u32 NUM_FRAME_TIME_SAMPLES = 150;
using FrameTimeHistory = std::array<float, NUM_FRAME_TIME_SAMPLES>;
float GetFPS(); float GetFPS();
float GetVPS(); float GetVPS();
float GetEmulationSpeed(); float GetEmulationSpeed();
float GetAverageFrameTime(); float GetAverageFrameTime();
float GetWorstFrameTime(); float GetMinimumFrameTime();
float GetMaximumFrameTime();
float GetThrottleFrequency(); float GetThrottleFrequency();
float GetCPUThreadUsage(); float GetCPUThreadUsage();
float GetCPUThreadAverageTime(); float GetCPUThreadAverageTime();
@ -188,6 +192,8 @@ float GetSWThreadUsage();
float GetSWThreadAverageTime(); float GetSWThreadAverageTime();
float GetGPUUsage(); float GetGPUUsage();
float GetGPUAverageTime(); float GetGPUAverageTime();
const FrameTimeHistory& GetFrameTimeHistory();
u32 GetFrameTimeHistoryPos();
/// Loads global settings (i.e. EmuConfig). /// Loads global settings (i.e. EmuConfig).
void LoadSettings(bool display_osd_messages); void LoadSettings(bool display_osd_messages);

View file

@ -226,6 +226,8 @@ void AdvancedSettingsWidget::addTweakOptions()
"DisableAllEnhancements", false); "DisableAllEnhancements", false);
addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Show Status Indicators"), "Display", addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Show Status Indicators"), "Display",
"ShowStatusIndicators", true); "ShowStatusIndicators", true);
addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Show Frame Times"), "Display",
"ShowFrameTimes", false);
addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Apply Compatibility Settings"), "Main", addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Apply Compatibility Settings"), "Main",
"ApplyCompatibilitySettings", true); "ApplyCompatibilitySettings", true);
addIntRangeTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Display FPS Limit"), "Display", "MaxFPS", 0, 1000, 0); addIntRangeTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Display FPS Limit"), "Display", "MaxFPS", 0, 1000, 0);
@ -303,6 +305,7 @@ void AdvancedSettingsWidget::onResetToDefaultClicked()
setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // Disable all enhancements setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // Disable all enhancements
setBooleanTweakOption(m_ui.tweakOptionTable, i++, true); // Show status indicators setBooleanTweakOption(m_ui.tweakOptionTable, i++, true); // Show status indicators
setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // Show frame times
setBooleanTweakOption(m_ui.tweakOptionTable, i++, true); // Apply compatibility settings setBooleanTweakOption(m_ui.tweakOptionTable, i++, true); // Apply compatibility settings
setIntRangeTweakOption(m_ui.tweakOptionTable, i++, 0); // Display FPS limit setIntRangeTweakOption(m_ui.tweakOptionTable, i++, 0); // Display FPS limit
setChoiceTweakOption(m_ui.tweakOptionTable, i++, 0); // Multisample antialiasing setChoiceTweakOption(m_ui.tweakOptionTable, i++, 0); // Multisample antialiasing

View file

@ -2661,6 +2661,9 @@ void FullscreenUI::DrawInterfaceSettingsPage()
"ShowCPU", false); "ShowCPU", false);
DrawToggleSetting(bsi, ICON_FA_SPINNER " Show GPU Usage", DrawToggleSetting(bsi, ICON_FA_SPINNER " Show GPU Usage",
"Shows the host's GPU usage in the top-right corner of the display.", "Display", "ShowGPU", false); "Shows the host's GPU usage in the top-right corner of the display.", "Display", "ShowGPU", false);
DrawToggleSetting(bsi, ICON_FA_RULER_HORIZONTAL " Show Frame Times",
"Shows a visual history of frame times in the upper-left corner of the display.", "EmuCore/GS",
"ShowFrameTimes", false);
DrawToggleSetting(bsi, ICON_FA_RULER_VERTICAL " Show Resolution", DrawToggleSetting(bsi, ICON_FA_RULER_VERTICAL " Show Resolution",
"Shows the current rendering resolution of the system in the top-right corner of the display.", "Shows the current rendering resolution of the system in the top-right corner of the display.",
"Display", "ShowResolution", false); "Display", "ShowResolution", false);

View file

@ -472,7 +472,7 @@ bool ImGuiManager::AddIconFonts(float size)
0xf15d, 0xf15d, 0xf188, 0xf188, 0xf191, 0xf192, 0xf1dd, 0xf1de, 0xf1e6, 0xf1e6, 0xf1eb, 0xf1eb, 0xf1f8, 0xf1f8, 0xf15d, 0xf15d, 0xf188, 0xf188, 0xf191, 0xf192, 0xf1dd, 0xf1de, 0xf1e6, 0xf1e6, 0xf1eb, 0xf1eb, 0xf1f8, 0xf1f8,
0xf1fc, 0xf1fc, 0xf242, 0xf242, 0xf245, 0xf245, 0xf26c, 0xf26c, 0xf279, 0xf279, 0xf2d0, 0xf2d0, 0xf2db, 0xf2db, 0xf1fc, 0xf1fc, 0xf242, 0xf242, 0xf245, 0xf245, 0xf26c, 0xf26c, 0xf279, 0xf279, 0xf2d0, 0xf2d0, 0xf2db, 0xf2db,
0xf2f2, 0xf2f2, 0xf2f5, 0xf2f5, 0xf3c1, 0xf3c1, 0xf410, 0xf410, 0xf466, 0xf466, 0xf500, 0xf500, 0xf51f, 0xf51f, 0xf2f2, 0xf2f2, 0xf2f5, 0xf2f5, 0xf3c1, 0xf3c1, 0xf410, 0xf410, 0xf466, 0xf466, 0xf500, 0xf500, 0xf51f, 0xf51f,
0xf545, 0xf545, 0xf548, 0xf548, 0xf552, 0xf552, 0xf57a, 0xf57a, 0xf5a2, 0xf5a2, 0xf5aa, 0xf5aa, 0xf5e7, 0xf5e7, 0xf545, 0xf545, 0xf547, 0xf548, 0xf552, 0xf552, 0xf57a, 0xf57a, 0xf5a2, 0xf5a2, 0xf5aa, 0xf5aa, 0xf5e7, 0xf5e7,
0xf65d, 0xf65e, 0xf6a9, 0xf6a9, 0xf7c2, 0xf7c2, 0xf807, 0xf807, 0xf815, 0xf815, 0xf818, 0xf818, 0xf84c, 0xf84c, 0xf65d, 0xf65e, 0xf6a9, 0xf6a9, 0xf7c2, 0xf7c2, 0xf807, 0xf807, 0xf815, 0xf815, 0xf818, 0xf818, 0xf84c, 0xf84c,
0xf8cc, 0xf8cc, 0x0, 0x0}; 0xf8cc, 0xf8cc, 0x0, 0x0};

View file

@ -4,6 +4,7 @@
#include "imgui_overlays.h" #include "imgui_overlays.h"
#include "IconsFontAwesome5.h" #include "IconsFontAwesome5.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/align.h"
#include "common/file_system.h" #include "common/file_system.h"
#include "common/log.h" #include "common/log.h"
#include "common/string_util.h" #include "common/string_util.h"
@ -27,6 +28,7 @@
#include "imgui_manager.h" #include "imgui_manager.h"
#include "input_manager.h" #include "input_manager.h"
#include "util/audio_stream.h" #include "util/audio_stream.h"
#include "gsl/span"
#include <atomic> #include <atomic>
#include <chrono> #include <chrono>
#include <cmath> #include <cmath>
@ -34,6 +36,16 @@
#include <mutex> #include <mutex>
#include <unordered_map> #include <unordered_map>
#if defined(CPU_X64)
#include <emmintrin.h>
#elif defined(CPU_AARCH64)
#ifdef _MSC_VER
#include <arm64_neon.h>
#else
#include <arm_neon.h>
#endif
#endif
Log_SetChannel(ImGuiManager); Log_SetChannel(ImGuiManager);
namespace ImGuiManager { namespace ImGuiManager {
@ -47,6 +59,74 @@ namespace SaveStateSelectorUI {
static void Draw(); static void Draw();
} }
static std::tuple<float, float> GetMinMax(gsl::span<const float> values)
{
#if defined(CPU_X64)
__m128 vmin(_mm_loadu_ps(values.data()));
__m128 vmax(vmin);
const u32 count = static_cast<u32>(values.size());
const u32 aligned_count = Common::AlignDownPow2(count, 4);
u32 i = 4;
for (; i < aligned_count; i += 4)
{
const __m128 v(_mm_loadu_ps(&values[i]));
vmin = _mm_min_ps(v);
vmax = _mm_max_ps(v);
}
#ifdef _MSC_VER
float min = std::min(vmin.m128_f32[0], std::min(vmin.m128_f32[1], std::min(vmin.m128_f32[2], vmin.m128_f32[3])));
float max = std::max(vmax.m128_f32[0], std::max(vmax.m128_f32[1], std::max(vmax.m128_f32[2], vmax.m128_f32[3])));
#else
float min = std::min(vmin[0], std::min(vmin[1], std::min(vmin[2], vmin[3])));
float max = std::max(vmax[0], std::max(vmax[1], std::max(vmax[2], vmax[3])));
#endif
for (; i < count; i++)
{
min = std::min(min, values[i]);
max = std::max(max, values[i]);
}
return std::tie(min, max);
#elif defined(CPU_AARCH64)
float32x4_t vmin(vld1q_f32(values.data()));
float32x4_t vmax(vmin);
const u32 count = static_cast<u32>(values.size());
const u32 aligned_count = Common::AlignDownPow2(count, 4);
u32 i = 4;
for (; i < aligned_count; i += 4)
{
const float32x4_t v(vld1q_f32(&values[i]));
vmin = vminq_f32(v);
vmax = vmaxq_f32(v);
}
float min = vminvq_f32(vmin);
float max = vmaxvq_f32(vmax);
for (; i < count; i++)
{
min = std::min(min, values[i]);
max = std::max(max, values[i]);
}
return std::tie(min, max);
#else
float min = values[0];
float max = values[0];
const u32 count = static_cast<u32>(values.size());
for (u32 i = 1; i < count; i++)
{
min = std::min(min, values[i]);
max = std::max(max, values[i]);
}
return std::tie(min, max);
#endif
}
static bool s_save_state_selector_ui_open = false; static bool s_save_state_selector_ui_open = false;
void ImGuiManager::RenderOverlays() void ImGuiManager::RenderOverlays()
@ -160,7 +240,7 @@ void ImGuiManager::DrawPerformanceOverlay()
if (g_settings.display_show_cpu) if (g_settings.display_show_cpu)
{ {
text.Clear(); text.Clear();
text.AppendFmtString("{:.2f}ms ({:.2f}ms worst)", System::GetAverageFrameTime(), System::GetWorstFrameTime()); text.AppendFmtString("{:.2f}ms | {:.2f}ms | {:.2f}ms", System::GetMinimumFrameTime(), System::GetMaximumFrameTime(), System::GetAverageFrameTime());
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255)); DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
text.Clear(); text.Clear();
@ -241,6 +321,70 @@ void ImGuiManager::DrawPerformanceOverlay()
DRAW_LINE(standard_font, text, IM_COL32(255, 255, 255, 255)); DRAW_LINE(standard_font, text, IM_COL32(255, 255, 255, 255));
} }
} }
if (g_settings.display_show_frame_times)
{
const ImVec2 history_size(200.0f * scale, 50.0f * scale);
ImGui::SetNextWindowSize(ImVec2(history_size.x, history_size.y));
ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x - margin - history_size.x, position_y));
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.25f));
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_PlotLines, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
ImGui::PushFont(fixed_font);
if (ImGui::Begin("##frame_times", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoInputs))
{
auto [min, max] = GetMinMax(System::GetFrameTimeHistory());
// add a little bit of space either side, so we're not constantly resizing
if ((max - min) < 4.0f)
{
min = min - std::fmod(min, 1.0f);
max = max - std::fmod(max, 1.0f) + 1.0f;
min = std::max(min - 2.0f, 0.0f);
max += 2.0f;
}
ImGui::PlotEx(
ImGuiPlotType_Lines, "##frame_times",
[](void*, int idx) -> float {
return System::GetFrameTimeHistory()[((System::GetFrameTimeHistoryPos() + idx) %
System::NUM_FRAME_TIME_SAMPLES)];
},
nullptr, System::NUM_FRAME_TIME_SAMPLES, 0, nullptr, min, max, history_size);
ImDrawList* win_dl = ImGui::GetCurrentWindow()->DrawList;
const ImVec2 wpos(ImGui::GetCurrentWindow()->Pos);
text.Clear();
text.AppendFmtString("{:.1f} ms", max);
text_size = fixed_font->CalcTextSizeA(fixed_font->FontSize, FLT_MAX, 0.0f, text.GetCharArray(),
text.GetCharArray() + text.GetLength());
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing + shadow_offset, wpos.y + shadow_offset),
IM_COL32(0, 0, 0, 100), text.GetCharArray(), text.GetCharArray() + text.GetLength());
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing, wpos.y), IM_COL32(255, 255, 255, 255),
text.GetCharArray(), text.GetCharArray() + text.GetLength());
text.Clear();
text.AppendFmtString("{:.1f} ms", min);
text_size = fixed_font->CalcTextSizeA(fixed_font->FontSize, FLT_MAX, 0.0f, text.GetCharArray(),
text.GetCharArray() + text.GetLength());
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing + shadow_offset,
wpos.y + history_size.y - fixed_font->FontSize + shadow_offset),
IM_COL32(0, 0, 0, 100), text.GetCharArray(), text.GetCharArray() + text.GetLength());
win_dl->AddText(
ImVec2(wpos.x + history_size.x - text_size.x - spacing, wpos.y + history_size.y - fixed_font->FontSize),
IM_COL32(255, 255, 255, 255), text.GetCharArray(), text.GetCharArray() + text.GetLength());
}
ImGui::End();
ImGui::PopFont();
ImGui::PopStyleVar(5);
ImGui::PopStyleColor(3);
}
} }
else if (g_settings.display_show_status_indicators && state == System::State::Paused && else if (g_settings.display_show_status_indicators && state == System::State::Paused &&
!FullscreenUI::HasActiveWindow()) !FullscreenUI::HasActiveWindow())