vor 0.2.1

Cross-platform performance instrumentation with an in-app egui panel and live system and GPU metrics.
Documentation
use std::collections::VecDeque;

use web_time::Instant;

use crate::system::SYSTEM_COLUMNS;
use crate::viz::bars::bars_row;
use crate::viz::flame::flame_chart;
use crate::viz::metric::{LABEL_COL_W, Metric, RowView, STAT_COL_W, metric_row};
use crate::viz::state::PanelState;

/// Render the profiler panel.
///
/// Layout:
/// 1. Header — pinned / live indicator + resume button, and a
///    corner chip toggling the frame_ms profiler-cost annotation.
/// 2. Frame bars driven by vor's own `frame_ms` system metric
///    (green / yellow / red against `state.config.bar_*_threshold`).
///    Click any bar to pin & freeze.
/// 3. Puffin flame chart for the pinned (or latest) frame.
/// 4. System line plots (frame_ms / memory_mb / io_ms / io_MB, plus
///    gpu_* where supported) — vor-owned, automatic.
/// 5. One line plot per caller-defined [`Metric`] in `metrics`.
///
/// Caller's `history` ring is expected to advance in lockstep with
/// [`PanelState::tick`] — push one `R` per `tick`.
pub fn show<R>(
    ui: &mut egui::Ui,
    state: &mut PanelState,
    history: &VecDeque<R>,
    metrics: &[Metric<R>],
) {
    let started = Instant::now();
    header_row(ui, state);
    bars_row(ui, state);
    ui.separator();

    let frame_view = state.view.lock();
    flame_chart::<R>(
        ui,
        &frame_view,
        state.system.len(),
        state.pinned,
        state.selection,
        &mut state.flame_view,
    );
    drop(frame_view);
    ui.separator();

    let plot_w = (ui.available_width() - LABEL_COL_W - STAT_COL_W - 16.0).max(120.0);
    let view = RowView {
        pinned: state.pinned,
        selection: state.selection,
        plot_w,
        history_capacity: state.config.history_capacity,
    };
    // Profiler's own main-thread cost is a frame-time quantity, so it
    // only annotates the frame_ms row.
    let load_ms = state.profiler_load_ns / 1e6;
    for c in SYSTEM_COLUMNS {
        let m = Metric::new(c.name, c.get, c.unit).describe(c.description);
        let show_load = state.show_profiler_load && c.name == "frame_ms";
        metric_row(ui, &m, &state.system, view, show_load.then_some(load_ms));
    }
    for m in metrics {
        metric_row(ui, m, history, view, None);
    }

    state.record_render_ns(started.elapsed().as_nanos() as u64);
}

fn header_row(ui: &mut egui::Ui, state: &mut PanelState) {
    ui.horizontal(|ui| {
        let paused = state.is_paused();
        let label = if paused { "▶ resume" } else { "⏸ pause" };
        if ui.small_button(label).clicked() {
            state.toggle_pause();
        }
        ui.label(if paused {
            "paused · click a bar to inspect · shift-drag to zoom a range · resume to follow"
        } else {
            "live · click a bar to pause & inspect · shift-drag to zoom a range"
        });
        ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
            if ui
                .selectable_label(state.show_profiler_load, "⚙ profiler")
                .on_hover_text("annotate frame_ms with vor's own per-frame cost (tick + render)")
                .clicked()
            {
                state.toggle_profiler_load();
            }
        });
    });
}