- render: CSM cascades and spot/point shadow faces draw inside a per-draw scissor, with a depth shader that has no discard for solid and rigid casters (downtown city shadow pass 3.3 ms → 0.4 ms, spot shadows 2.7 → 0.1 ms); cascade selection by caster bounds on Apple; per-frame model draw order built once; clustered light terms per pixel; foliage wind, impostors, grass and LOD model sets; city glass and interior light; the viewmodel eye-space fix for narrow panes; joint-following parts use the skin's exact joint matrix. - model / csg / mesh_edit / remesh / gltf: makepad_csg_math::portable (sin/cos/atan/exp/ln/pow/hypot/cbrt from exactly rounded operations), used at 320 call sites, so a model hashes and builds byte-identically on macOS and Linux (MODEL_GENERATOR_VERSION 2, CHARACTER_GENERATOR_VERSION 42; tests/portable_identity.rs); lathes always face outward; sculpted-shell booleans with a tolerant surface map; decal and badge lettering; LOD model sets; grip poses for first-person arms. - platform: DrawCall scissor rectangles (Metal and Vulkan; other backends keep the old clip); draw_shader_ready for a fallback while a pipeline compiles; Metal clock reads once per frame; Linux render-texture readback. - audio_synth: score.rs and its Sequencer are removed; game music now runs on Stage's Score engine; drum_note moves into instruments.rs. Includes Stage SF1's SoundFontInstrument change: programs share one loaded font instead of ~300 MB each. - ai: the sfx model generates at whole seconds and trims to the requested length (fractional lengths came back as noise); fleet roles let node 165 serve audio as a fallback. - widgets/core: screen recordings of any app inside a Makepad checkout land in <makepad>/local/screencap. - fab: FabDragNumber read_only, for the sandbox time dial. Checked on node 165: cargo check --release --workspace; makepad crate suites 1442 passed; sandbox 3095 passed; portable model hashes identical on the Mac mini. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
55 lines
2.7 KiB
Rust
55 lines
2.7 KiB
Rust
//! One program, one product, on every machine. Models built on a Mac and on
|
|
//! Linux must be byte-identical: the store addresses built products by
|
|
//! content, so a product that differs per platform splits the store and
|
|
//! misses every cache the other machine filled. These goldens were recorded
|
|
//! on Linux (node 165) and pass unchanged on macOS (the Mac mini); a
|
|
//! transcendental routed back through the platform libm breaks them there.
|
|
|
|
use makepad_model::json::{self, Value};
|
|
use makepad_model::build_program;
|
|
use makepad_model::Limits;
|
|
|
|
fn fnv(bytes: &[u8]) -> u64 {
|
|
bytes.iter().fold(0xcbf2_9ce4_8422_2325u64, |h, b| (h ^ *b as u64).wrapping_mul(0x100_0000_01b3))
|
|
}
|
|
|
|
fn product(program: &str) -> u64 {
|
|
let ops = match json::parse(program.as_bytes()).unwrap() {
|
|
Value::Arr(ops) => ops,
|
|
_ => unreachable!(),
|
|
};
|
|
let built = build_program(&ops, Limits::default(), &mut |alias| Err(format!("no import {alias}")), None).unwrap();
|
|
fnv(&built.compiled.glb)
|
|
}
|
|
|
|
const PROGRAMS: &[(&str, &str)] = &[
|
|
("sphere+cylinder", r#"[{"op":"sphere","object":"ball","radius":0.5,"segments":24,"rings":12,"smooth":true},
|
|
{"op":"cylinder","object":"post","radius":0.2,"height":2,"segments":17,"smooth":true}]"#),
|
|
("lathe+sweep", r#"[{"op":"lathe","object":"vase","profile":[[0,0],[0.7,0.1],[0.8,0.8],[0.3,1.7],[0,1.8]],"axis":1,"segments":23,"caps":true,"material":0,"outward":true},
|
|
{"op":"sweep","object":"rail","profile":[[-0.1,-0.1],[0.1,-0.1],[0.1,0.1],[-0.1,0.1]],"path":[[0,0,0],[0,0.4,1],[0.5,0.9,2],[1.4,1.1,2.6]],"caps":true,"material":0}]"#),
|
|
("shapes", r#"[{"op":"capsule","object":"pill","radius":0.3,"height":1.2,"segments":19,"rings":7,"material":0},
|
|
{"op":"cone","object":"cone","radius":0.6,"top_radius":0.2,"height":1.1,"segments":21,"smooth":true,"material":0},
|
|
{"op":"torus","object":"ring","radius":0.8,"tube":0.15,"segments":29,"sides":11,"material":0}]"#),
|
|
("character", r#"[{"op":"character","preset":"halcyon_warden"}]"#),
|
|
];
|
|
|
|
/// Recorded on Linux. A mismatch on another platform means some geometry
|
|
/// still goes through the platform libm (see `makepad_csg_math::portable`).
|
|
const GOLDEN: &[(&str, u64)] = &[
|
|
("sphere+cylinder", 0x73f3_858b_4f3d_f1cd),
|
|
("lathe+sweep", 0x0dc2_4fc8_8b97_c245),
|
|
("shapes", 0x4e83_3371_811a_a309),
|
|
("character", 0x95fb_81d9_a066_ffc0),
|
|
];
|
|
|
|
#[test]
|
|
fn every_platform_builds_the_same_bytes() {
|
|
let mut got = Vec::new();
|
|
for (name, program) in PROGRAMS {
|
|
got.push((*name, product(program)));
|
|
}
|
|
for (name, hash) in &got {
|
|
eprintln!("portable identity: {name} {hash:#018x}");
|
|
}
|
|
assert_eq!(got, GOLDEN, "a built product changed on this platform");
|
|
}
|