facett-brokkrview/tests/flow_gpu.rs
//! Real Falsett callbacks, live run-status uploads and the results-DAG golden.
//! Initial reference: Apple M2 Pro / Metal; see snapshots/README.md.
//! Compare: FACETT_TEST_GPU=integrated cargo test -p facett-brokkrview --features wgpu --test flow_gpu
//! UPDATE_SNAPSHOTS=1 is only for intended, reviewed reference changes.
//! Other hardware comparisons are separate evidence; missing references fail.
#![cfg(feature = "wgpu")]
use egui_kittest::{Harness, wgpu::WgpuTestRenderer};
use facett_brokkrview::{BrokkrView, BrokkrViewMsg, FinishedRun, ViewMode};
use facett_core::{Elm, Facet, render::lane};
use facett_flow::gpu;
fn enabled() -> bool {
let enabled = matches!(
std::env::var("FACETT_TEST_GPU").as_deref(),
Ok("integrated" | "discrete" | "software")
);
if !enabled {
eprintln!("SKIPPED: no GPU proof; set FACETT_TEST_GPU=integrated|discrete|software");
}
enabled
}
fn harness() -> (Harness<'static, BrokkrView>, egui_wgpu::RenderState) {
let setup = facett_core::render::gpu::adapter_wgpu::facett_wgpu_options().wgpu_setup;
let rs = egui_kittest::wgpu::create_render_state(setup, Default::default());
assert!(gpu::install_renderer(&rs));
let mut view = BrokkrView::demo("Build results");
view.update(BrokkrViewMsg::SetView(ViewMode::Dag));
let h = Harness::builder()
.with_size(egui::vec2(900.0, 600.0))
.with_pixels_per_point(1.0)
.renderer(WgpuTestRenderer::from_render_state(rs.clone()))
.build_ui_state(
|ui, v: &mut BrokkrView| {
facett_core::set_theme(ui.ctx(), facett_core::Theme::sci_fi());
Facet::ui(v, ui);
},
view,
);
(h, rs)
}
fn frame(h: &mut Harness<'_, BrokkrView>) -> image::RgbaImage {
let before = lane::frames_of(gpu::lane_name());
h.step();
let image = h.render().expect("real GPU framebuffer");
assert!(
lane::frames_of(gpu::lane_name()) > before,
"CPU paint cannot satisfy this proof"
);
image
}
fn bytes() -> u64 {
lane::clock_stats_of(gpu::lane_name()).upload_bytes_total
}
fn diff(a: &image::RgbaImage, b: &image::RgbaImage) -> usize {
assert_eq!(a.dimensions(), b.dimensions());
a.pixels().zip(b.pixels()).filter(|(a, b)| a != b).count()
}
#[test]
fn live_status_and_camera_keep_resident_geometry() {
if !enabled() {
return;
}
let _turn = facett_core::render::gputurn::hold();
let (mut h, rs) = harness();
frame(&mut h);
frame(&mut h);
let initial = frame(&mut h);
let generation = h.state().scene_generation();
let targets = gpu::residency(&rs);
assert_eq!(targets.0, 1);
let initial_bytes = bytes();
assert_eq!(diff(&initial, &frame(&mut h)), 0);
assert_eq!(bytes(), initial_bytes, "idle frame reuses geometry");
let attr_bytes =
(h.state().model().dag.nodes.len() * 16 + h.state().model().dag.edges.len() * 8) as u64;
let failed: FinishedRun = serde_json::from_value(serde_json::json!({
"run_id":"failed-run", "pipeline":"nornir-ci", "status":"failed",
"steps":{"compile":"failed", "unit":"skipped", "lint":"skipped", "release":"skipped"}
}))
.unwrap();
h.state_mut().update(BrokkrViewMsg::RunFinished(failed));
let failure = frame(&mut h);
assert!(
diff(&initial, &failure) > 100,
"new run status must visibly reach the DAG"
);
assert_eq!(h.state().scene_generation(), generation);
assert_eq!(
bytes() - initial_bytes,
attr_bytes,
"status uploads attributes only"
);
assert_eq!(gpu::residency(&rs), targets);
let before_pan = bytes();
h.state_mut()
.update(BrokkrViewMsg::Pan(egui::vec2(23.0, 11.0)));
assert!(diff(&failure, &frame(&mut h)) > 100);
assert_eq!(
bytes(),
before_pan,
"camera must not rebuild resident buffers"
);
assert_eq!(h.state().scene_generation(), generation);
gpu::evict_idle(&rs, u64::MAX);
assert_eq!(gpu::residency(&rs).0, 0);
}
#[test]
fn canonical_brokkrview_golden() {
if !enabled() {
return;
}
let _turn = facett_core::render::gputurn::hold();
let (mut h, _) = harness();
frame(&mut h);
frame(&mut h);
let actual = frame(&mut h);
let path =
std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/snapshots/flow_gpu.png");
facett_core::golden::assert_golden_within(&actual, &path, "brokkrview_flow_gpu", 2);
}