From 4a2ca9115bf71e926c554f21874de678fa49a005 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Sat, 3 Oct 2026 23:59:22 -0400 Subject: [PATCH] M13.23: Shatter wireframe views and Foam's texture / map extras fall back via gpu_supported (no readback attempt) Co-Authored-By: Claude Opus 5.5 --- crates/effects/src/catalog.rs | 13 +++++++++++++ crates/effects/src/sim2.rs | 8 +------- crates/gpu/src/tests_fx_sim.rs | 8 ++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/crates/effects/src/catalog.rs b/crates/effects/src/catalog.rs index ca580b9d..1e1b4bc2 100644 --- a/crates/effects/src/catalog.rs +++ b/crates/effects/src/catalog.rs @@ -97,6 +97,19 @@ pub fn gpu_supported(id: &str, ctx: &crate::EffectCtx) -> bool { match id { "ec.generate.cellpattern" if (6..=10).contains(&ctx.params.e("cellPattern")) => return false, "ec.distort.turbulentdisplace" if ctx.params.e("pinning") >= 8 => return false, + // Shatter's wireframe views; Foam's User Defined texture, Environment Map and flow-map + // preview (the GPU draws the rendered pieces and the sprite bubbles only). + "ec.sim.shatter" if ctx.params.e("view") != 0 => return false, + "ec.sim.foam" => { + let set = |id: &str| matches!(ctx.params.get(id), Some(effectcraft_keyframe::Value::Layer(Some(_)))); + let view = ctx.params.e("view"); + if (view == 2 && ctx.params.e("rendering/bubbleTexture") == 5) + || (view == 2 && ctx.params.f("rendering/reflectionStrength") > 0.0 && set("rendering/environmentMap")) + || (view == 1 && set("flowMap/flowMap")) + { + return false; + } + } // Fisheye / Twist (a crease at the unit circle) bent past 50 % or with Horizontal / // Vertical Distortion: Newton's inverse wanders chaotically before converging near the // fold, so f32 lands on other pixels than the CPU's f64. diff --git a/crates/effects/src/sim2.rs b/crates/effects/src/sim2.rs index d682a310..98634b0f 100644 --- a/crates/effects/src/sim2.rs +++ b/crates/effects/src/sim2.rs @@ -1525,13 +1525,7 @@ fn foam(ctx: &EffectCtx, b: Buf) -> Buf { /// Foam's bubbles as sprites, `None` when it draws more than sprites (a User Defined bubble /// texture, an Environment Map reflection or the Draft + Flow Map view's flow map). pub(crate) fn foam_plan(ctx: &EffectCtx, b: &Buf) -> Option { - let pr = ctx.params; - let set = |id: &str| matches!(pr.get(id), Some(Value::Layer(Some(_)))); - let view = pr.e("view"); - if (view == 2 && pr.e("rendering/bubbleTexture") == 5) - || (view == 2 && pr.f("rendering/reflectionStrength") > 0.0 && set("rendering/environmentMap")) - || (view == 1 && set("flowMap/flowMap")) - { + if !crate::catalog::gpu_supported("ec.sim.foam", ctx) { return None; } foam_impl(ctx, b, true).err() diff --git a/crates/gpu/src/tests_fx_sim.rs b/crates/gpu/src/tests_fx_sim.rs index 55dc62c4..d6977779 100644 --- a/crates/gpu/src/tests_fx_sim.rs +++ b/crates/gpu/src/tests_fx_sim.rs @@ -152,3 +152,11 @@ fn caustics() { ); let _ = (c(0.0, 0.0, 0.0), on()); } + +#[test] +fn cpu_only_views_fall_back() { + // Shatter's wireframe views and Foam's User Defined texture render on the CPU; composited + // frames still match. + composited("ec.sim.shatter", &[], 1.0, 0.0); + composited("ec.sim.foam", &[("view", e(2)), ("rendering/bubbleTexture", e(5)), ("rendering/bubbleTextureLayer", Value::Layer(Some(0)))], 1.0, 0.0); +}