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:
@@ -1,5 +1,7 @@
|
||||
#include "capture_panel.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "imgui.h"
|
||||
|
||||
namespace coop
|
||||
@@ -11,9 +13,9 @@ bool CapturePanel::init(ID3D11Device* device)
|
||||
return renderer_.init(device);
|
||||
}
|
||||
|
||||
void CapturePanel::draw_ui()
|
||||
void CapturePanel::draw_ui(const FrameStats& stats)
|
||||
{
|
||||
ImGui::SetNextWindowPos(ImVec2(460, 24), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowPos(ImVec2(460, 40), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(ImVec2(360, 0), ImGuiCond_FirstUseEver);
|
||||
ImGui::Begin("Video mirror");
|
||||
|
||||
@@ -48,9 +50,49 @@ void CapturePanel::draw_ui()
|
||||
capture_.frame_height());
|
||||
}
|
||||
|
||||
draw_perf_graphs(stats);
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void CapturePanel::draw_perf_graphs(const FrameStats& stats)
|
||||
{
|
||||
// The mirror renders into this window, so the host's render frame timing is
|
||||
// the mirror's performance. Plot the recent history and summarise it.
|
||||
ImGui::SeparatorText("Render performance");
|
||||
|
||||
float ms[FrameStats::kHistory] = {};
|
||||
const int n = stats.copy_frame_ms(ms);
|
||||
if (n == 0)
|
||||
{
|
||||
ImGui::TextDisabled("Gathering samples...");
|
||||
return;
|
||||
}
|
||||
|
||||
float fps[FrameStats::kHistory] = {};
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
fps[i] = ms[i] > 0.0f ? 1000.0f / ms[i] : 0.0f;
|
||||
}
|
||||
|
||||
float min_ms = 0.0f, max_ms = 0.0f, avg_ms = 0.0f;
|
||||
stats.history_stats(min_ms, max_ms, avg_ms);
|
||||
const float avg_fps = avg_ms > 0.0f ? 1000.0f / avg_ms : 0.0f;
|
||||
const float min_fps = max_ms > 0.0f ? 1000.0f / max_ms : 0.0f; // slowest frame -> lowest FPS
|
||||
const float max_fps = min_ms > 0.0f ? 1000.0f / min_ms : 0.0f;
|
||||
|
||||
char overlay[64];
|
||||
std::snprintf(overlay, sizeof(overlay), "avg %.2f ms", avg_ms);
|
||||
// Fixed 0..33 ms scale (30 FPS floor) so the line height is meaningful frame
|
||||
// to frame rather than auto-rescaling.
|
||||
ImGui::PlotLines("##frametime", ms, n, 0, overlay, 0.0f, 33.0f, ImVec2(-1.0f, 60.0f));
|
||||
ImGui::Text("Frametime avg %.2f min %.2f max %.2f ms", avg_ms, min_ms, max_ms);
|
||||
|
||||
std::snprintf(overlay, sizeof(overlay), "avg %.0f FPS", avg_fps);
|
||||
ImGui::PlotLines("##fps", fps, n, 0, overlay, 0.0f, 144.0f, ImVec2(-1.0f, 60.0f));
|
||||
ImGui::Text("FPS avg %.0f min %.0f max %.0f", avg_fps, min_fps, max_fps);
|
||||
}
|
||||
|
||||
void CapturePanel::render(ID3D11DeviceContext* ctx, std::uint32_t dst_w, std::uint32_t dst_h)
|
||||
{
|
||||
if (capture_.running())
|
||||
|
||||
Reference in New Issue
Block a user