tawasuyu

tawasuyu/llimphi

Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.

Rust 660Markdown 302TOML 157RON 312382 Definitions

⎇ 168cd187519c0ad575d3ce63baee2f164c38d9d1 llimphi-test/tests/gpu_golden.rs Rust · 68 lines · 3.3 KB History Who touched what raw

chore: refresco desde el monorepo — vello 0.9 / wgpu 29, 120 miembros d251eb32b · Sergio ·

1//! Golden del backend **GPU-directo** vía `Harness::render_gpu`. Cierra el hueco
2//! "el path GPU-directo no tenía cobertura de regresión visual" (antes sólo el
3//! smoke test "no panic" de llimphi-raster). Un starfield determinista de discos
4//! con AA por SDF — el caso canónico denso del SDD §"GPU directo". Si el
5//! rasterizado de discos/AA/color regresiona, el golden falla con DiffStats.
6//!
7//! Regenerar: `LLIMPHI_GOLDEN_UPDATE=1 cargo test -p llimphi-test`.
8
9use std::path::Path;
10
11use llimphi_hal::wgpu;
12use llimphi_raster::gpu::{GpuBatch, GpuPipelines};
13use llimphi_raster::peniko::Color;
14use llimphi_test::{compare_golden, with_harness, GoldenConfig};
15
16#[test]
17fn golden_starfield_gpu_directo() {
18    // **Este test, y sólo éste, no vale contra la GPU real.** Un golden es una
19    // imagen bendecida contra un rasterizador concreto: el de software. Medido
20    // el 2026-08-05 con `LLIMPHI_TEST_GPU=1` en una Iris Xe: **2,74 % de los
21    // píxeles difieren, Δ máximo 44**. No es un bug — es lo que significa
22    // comparar contra una foto en vez de contra un oráculo.
23    //
24    // El contraste vale la pena mirarlo: en esa misma corrida los **112** tests
25    // restantes pasaron en las dos, y todos ellos comparan contra *otra manera
26    // de calcular lo mismo* (caché contra fresco, troceado contra entero, atlas
27    // contra vello, hybrid contra CPU). Ésa es la diferencia entre un oráculo y
28    // una foto, y acá quedó medida, no argumentada.
29    //
30    // Se saltea en vez de fallar para que `LLIMPHI_TEST_GPU=1 cargo test` sea
31    // una pregunta limpia —«¿el motor se porta igual en hardware?»— y no una
32    // corrida con un fallo conocido de ruido de fondo.
33    if std::env::var("LLIMPHI_TEST_GPU").ok().as_deref() == Some("1") {
34        eprintln!(
35            "salteado: un golden se compara contra el adapter de SOFTWARE con el \
36             que se bendijo. Contra la GPU real difiere por definición (medido: \
37             2,74 % de píxeles, Δ máx 44)."
38        );
39        return;
40    }
41    let rendered = with_harness(|h| {
42        h.render_gpu(320, 200, Color::from_rgba8(6, 8, 16, 255), |device, queue, enc, view, vp| {
43            let pipelines = GpuPipelines::new(device, wgpu::TextureFormat::Rgba8Unorm);
44            let mut batch = GpuBatch::new(&pipelines);
45            // Starfield determinista (LCG con seed fijo → golden reproducible).
46            let mut s: u32 = 0x1234_5678;
47            let lcg = |s: &mut u32| -> f32 {
48                *s = s.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
49                (*s >> 8) as f32 / 16_777_216.0
50            };
51            for _ in 0..300 {
52                let x = lcg(&mut s) * vp.0;
53                let y = lcg(&mut s) * vp.1;
54                let bright = 0.3 + lcg(&mut s) * 0.7;
55                let t = lcg(&mut s);
56                // Blanco-azulado a amarillo suave, alpha ∝ brillo.
57                let col = Color::new([0.85 + 0.15 * t, 0.88 + 0.10 * (1.0 - t), 0.95, bright]);
58                let r = 0.8 + bright * 1.6;
59                batch.add_disc(x, y, r, col);
60            }
61            batch.flush(device, queue, enc, view, vp, wgpu::LoadOp::Load);
62        })
63    });
64    let path = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/goldens/starfield_gpu.png");
65    if let Err(e) = compare_golden(&path, &rendered, &GoldenConfig::default()) {
66        panic!("{e}");
67    }
68}