Video mirror: frametime + FPS graphs with min/max/avg stats
The mirror renders into the host window, so the host's render frame timing is the mirror's performance. FrameStats now retains a ~2 s ring of frame-time samples; the Video mirror panel plots them as a frametime graph (0-33 ms scale) and an FPS graph (0-144 scale), each with an avg overlay, and prints avg/min/max for both frametime and FPS underneath. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
// stay focused on their own pipeline while presenting a consistent shell.
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace coop
|
||||
{
|
||||
|
||||
@@ -24,6 +26,9 @@ struct UiState
|
||||
class FrameStats
|
||||
{
|
||||
public:
|
||||
// Number of frame samples kept for the graphs (~2 s at 120 FPS).
|
||||
static constexpr int kHistory = 240;
|
||||
|
||||
void tick(float dt_ms)
|
||||
{
|
||||
if (dt_ms < cur_min_)
|
||||
@@ -46,8 +51,16 @@ public:
|
||||
accum_ms_ = 0.0f;
|
||||
frames_ = 0;
|
||||
}
|
||||
|
||||
history_[hist_pos_] = dt_ms;
|
||||
hist_pos_ = (hist_pos_ + 1) % kHistory;
|
||||
if (hist_count_ < kHistory)
|
||||
{
|
||||
++hist_count_;
|
||||
}
|
||||
}
|
||||
|
||||
// --- 1 s windowed aggregates (stable readout for the menu bar) ---------
|
||||
[[nodiscard]] float avg_ms() const
|
||||
{
|
||||
return avg_ms_;
|
||||
@@ -65,6 +78,45 @@ public:
|
||||
return avg_ms_ > 0.0f ? 1000.0f / avg_ms_ : 0.0f;
|
||||
}
|
||||
|
||||
// --- Sample history (for graphs) ---------------------------------------
|
||||
[[nodiscard]] int history_size() const
|
||||
{
|
||||
return hist_count_;
|
||||
}
|
||||
|
||||
// Copy the frame-time samples (ms) into `out` oldest-to-newest; `out` must
|
||||
// hold at least kHistory floats. Returns the number written.
|
||||
int copy_frame_ms(float* out) const
|
||||
{
|
||||
const int start = (hist_pos_ - hist_count_ + kHistory * 2) % kHistory;
|
||||
for (int i = 0; i < hist_count_; ++i)
|
||||
{
|
||||
out[i] = history_[(start + i) % kHistory];
|
||||
}
|
||||
return hist_count_;
|
||||
}
|
||||
|
||||
// min / max / mean over the whole retained history (order-independent).
|
||||
void history_stats(float& min_ms, float& max_ms, float& avg_ms) const
|
||||
{
|
||||
if (hist_count_ == 0)
|
||||
{
|
||||
min_ms = max_ms = avg_ms = 0.0f;
|
||||
return;
|
||||
}
|
||||
float mn = 1.0e9f, mx = 0.0f, sum = 0.0f;
|
||||
for (int i = 0; i < hist_count_; ++i)
|
||||
{
|
||||
const float v = history_[i];
|
||||
mn = std::min(mn, v);
|
||||
mx = std::max(mx, v);
|
||||
sum += v;
|
||||
}
|
||||
min_ms = mn;
|
||||
max_ms = mx;
|
||||
avg_ms = sum / static_cast<float>(hist_count_);
|
||||
}
|
||||
|
||||
private:
|
||||
float accum_ms_ = 0.0f;
|
||||
int frames_ = 0;
|
||||
@@ -73,6 +125,10 @@ private:
|
||||
float avg_ms_ = 0.0f;
|
||||
float min_ms_ = 0.0f;
|
||||
float max_ms_ = 0.0f;
|
||||
|
||||
float history_[kHistory] = {};
|
||||
int hist_pos_ = 0;
|
||||
int hist_count_ = 0;
|
||||
};
|
||||
|
||||
// Draw the main menu bar (app name, View menu of panel toggles + debug switch,
|
||||
|
||||
Reference in New Issue
Block a user