effectcraft/crates/ui-egui/tests/ui_gpu.rs

55 lines
2.3 KiB
Rust

//! The viewer on the GPU compositor (egui_kittest with wgpu): frames composited on the GPU match
//! the CPU viewer. Skips without a GPU adapter (CI). Set `EC_SNAPSHOT_DIR` to keep PNGs.
use effectcraft_engine::Session;
use effectcraft_ui_egui::EffectcraftApp;
use egui_kittest::Harness;
use serde_json::json;
fn settle(h: &mut Harness<'_, EffectcraftApp>) {
for _ in 0..600 {
h.step();
if h.state().frames.inflight() == 0 && h.state().frames.last_ms.lock().map(|v| *v > 0.0).unwrap_or(false) {
break;
}
std::thread::sleep(std::time::Duration::from_millis(20));
}
for _ in 0..4 {
h.step();
}
}
#[test]
fn viewer_draws_gpu_frames_that_match_the_cpu() {
if effectcraft_gpu::Gpu::headless().is_none() {
eprintln!("no GPU adapter: skipping");
return;
}
let mut s = Session::default();
s.execute("file.openDemoProject", json!({})).unwrap();
s.execute("time.set", json!({"time": 2.0})).unwrap();
let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).with_pixels_per_point(1.0).wgpu().build_eframe(|_| EffectcraftApp::new(s));
settle(&mut h);
assert!(h.state().gpu_adapter().is_some(), "GPU compositor on egui-wgpu's device");
let gpu_px = h.state_mut().viewer_pixels().expect("read back the GPU frame");
let gpu_shot = h.render().expect("render");
// Mercury Software Only: the same frame from the CPU.
h.state_mut().session.execute("render.backend", json!({"backend": "cpu"})).unwrap();
settle(&mut h);
let cpu_px = h.state_mut().viewer_pixels().expect("CPU frame");
let cpu_shot = h.render().expect("render");
assert_eq!(gpu_px.size, cpu_px.size);
let mut worst = 0i32;
let mut over = 0usize;
for (a, b) in gpu_px.pixels.iter().zip(&cpu_px.pixels) {
let d = a.to_array().iter().zip(b.to_array()).map(|(x, y)| (*x as i32 - y as i32).abs()).max().unwrap_or(0);
worst = worst.max(d);
over += usize::from(d > 1);
}
assert!(over * 1000 <= gpu_px.pixels.len() * 3 && worst <= 4, "viewer GPU vs CPU: {over} pixels > 1/255, worst {worst}/255");
if let Ok(d) = std::env::var("EC_SNAPSHOT_DIR") {
gpu_shot.save(format!("{d}/ui_gpu_viewer.png")).unwrap();
cpu_shot.save(format!("{d}/ui_cpu_viewer.png")).unwrap();
}
}