Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-map3d/tests/taa_red.rs

//! **THE RED PROOF, kept hook-free on purpose.**
//!
//! It measures the SHIPPED present path — whatever `install_renderer` installs — with
//! exactly the metric `taa_present.rs` uses (distance to a 3× supersampled coverage
//! truth, over the 3D content rect), and asserts the TAA-level result. It calls no
//! test hook, so it compiles against the tree BEFORE the TAA wiring as well as after:
//! stash the source changes and it goes red on the FXAA present path, restore them and
//! it goes green. That is the point of it existing beside the fuller proof.
//!
//! Run:
//! `FACETT_TEST_GPU=discrete cargo test -p facett-map3d --features wgpu --test taa_red -- --nocapture --test-threads=1`

#[cfg(not(feature = "wgpu"))]
#[test]
fn taa_red_proof_needs_the_wgpu_feature() {
    eprintln!(
        "[taa_red] SKIPPED and therefore PROVED NOTHING — built without `--features wgpu`, so no \
         present pass ran and NOTHING about antialiasing was measured."
    );
}

#[cfg(feature = "wgpu")]
mod proof {
    use egui_kittest::wgpu::{create_render_state, default_wgpu_setup, WgpuTestRenderer};
    use egui_kittest::Harness;
    use facett_map3d::{Map3D, SunSky, V3};
    use std::cell::RefCell;
    use std::rc::Rc;

    const PANE: f32 = 512.0;
    const SS: u32 = 3;
    const FRAMES: usize = 24;
    const WARMUP: usize = 4;
    const CONTENT: (f64, f64, f64, f64) = (0.06, 0.40, 0.60, 0.88);

    fn scene() -> Map3D {
        let mut m = Map3D::synthetic("taa")
            .with_gpu(true)
            .with_sky(true)
            .with_bloom(false)
            .with_ssao(false)
            .with_shadows(0.0)
            .with_compass(false)
            .with_scale_bar(false)
            .with_minimap(false)
            .with_sun(SunSky::from_angles(0.7, 0.55));
        m.spin = false;
        m.set_clock(0.0);
        pose(&mut m, 0.0);
        m
    }

    fn pose(m: &mut Map3D, az_offset: f32) {
        let az = 0.9 + az_offset;
        m.cam.azimuth = az;
        m.cam.goal_azimuth = az;
        m.cam.elevation = 0.35;
        m.cam.goal_elevation = 0.35;
        m.cam.distance = 2.2;
        m.cam.goal_distance = 2.2;
        m.cam.target = V3::new(0.0, 0.15, 0.0);
        m.cam.goal_target = m.cam.target;
        m.cam.settle();
    }

    fn render_seq(frames: usize, ppp: f32) -> image::RgbaImage {
        let rs = create_render_state(
            facett_map3d::gpu::proof_wgpu_setup().unwrap_or_else(default_wgpu_setup),
            Default::default(),
        );
        eprintln!("[taa_red] adapter: {}", rs.adapter.get_info().name);
        facett_map3d::gpu::install_renderer(&rs);
        let view = Rc::new(RefCell::new(scene()));
        let v2 = view.clone();
        let mut harness = Harness::builder()
            .with_size(egui::vec2(PANE, PANE))
            .with_pixels_per_point(ppp)
            .renderer(WgpuTestRenderer::from_render_state(rs))
            .build_ui(move |ui| {
                facett_core::set_theme(ui.ctx(), facett_core::Theme::sci_fi());
                use facett_core::Facet as _;
                v2.borrow_mut().ui(ui);
            });
        let mut img = None;
        for _ in 0..frames.max(WARMUP + 1) {
            pose(&mut view.borrow_mut(), 0.0);
            harness.step();
            img = Some(harness.render().expect("wgpu render produced an image"));
        }
        img.expect("at least one frame")
    }

    fn luma(p: &[u8]) -> f64 {
        0.2126 * f64::from(p[0]) + 0.7152 * f64::from(p[1]) + 0.0722 * f64::from(p[2])
    }

    fn plane(img: &image::RgbaImage) -> Vec<f64> {
        img.pixels().map(|p| luma(&p.0)).collect()
    }

    fn references(ss: &image::RgbaImage, w: u32, h: u32) -> (Vec<f64>, Vec<f64>) {
        assert_eq!((ss.width(), ss.height()), (w * SS, h * SS));
        let mut boxed = Vec::with_capacity((w * h) as usize);
        let mut ctr = Vec::with_capacity((w * h) as usize);
        for y in 0..h {
            for x in 0..w {
                let mut sum = 0.0;
                for dy in 0..SS {
                    for dx in 0..SS {
                        sum += luma(&ss.get_pixel(x * SS + dx, y * SS + dy).0);
                    }
                }
                boxed.push(sum / f64::from(SS * SS));
                ctr.push(luma(&ss.get_pixel(x * SS + SS / 2, y * SS + SS / 2).0));
            }
        }
        (boxed, ctr)
    }

    fn rms(a: &[f64], b: &[f64], w: u32, h: u32) -> f64 {
        let (x0, y0, x1, y1) = (
            (f64::from(w) * CONTENT.0) as u32,
            (f64::from(h) * CONTENT.1) as u32,
            (f64::from(w) * CONTENT.2) as u32,
            (f64::from(h) * CONTENT.3) as u32,
        );
        let (mut s, mut n) = (0.0f64, 0usize);
        for y in y0..y1 {
            for x in x0..x1 {
                let i = (y * w + x) as usize;
                s += (a[i] - b[i]) * (a[i] - b[i]);
                n += 1;
            }
        }
        (s / n as f64).sqrt()
    }

    /// Calibrated between the two MEASURED numbers, not guessed: the FXAA present path
    /// scores 2.745 on this metric and the TAA one 1.044, so anything under 2.0 is a
    /// pipeline that is genuinely converging rather than edge-smoothing.
    const TARGET: f64 = 2.0;

    #[test]
    fn the_shipped_present_path_converges_on_coverage() {
        if std::env::var("FACETT_TEST_GPU").as_deref() != Ok("discrete") {
            eprintln!(
                "[taa_red] SKIPPED and therefore PROVED NOTHING — FACETT_TEST_GPU=discrete was not \
                 set, so the adapter was not the app's and NOTHING was measured."
            );
            return;
        }
        let img = render_seq(FRAMES, 1.0);
        let (w, h) = (img.width(), img.height());
        let ss = render_seq(FRAMES, SS as f32);
        let (boxed, ctr) = references(&ss, w, h);
        let got = plane(&img);
        let e_box = rms(&got, &boxed, w, h);
        let e_ctr = rms(&got, &ctr, w, h);
        eprintln!(
            "[taa_red] shipped present path: rms(img,BOX)={e_box:.3} rms(img,CTR)={e_ctr:.3} \
             ratio={:.3} (target rms < {TARGET})",
            e_box / e_ctr.max(1e-9)
        );
        assert!(
            e_box < TARGET,
            "the shipped present pass must converge on the 9-sample coverage truth: rms {e_box:.3} \
             (target < {TARGET}); an edge-smoothing (FXAA) present pass scores 2.745 here"
        );
    }
}