frust-engine 0.6.2

Sparse-strip GPU render pipeline for Frust: compiles a scene display list into strips and records the draw passes on wgpu.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
use std::sync::OnceLock;

/// Parse an environment flag as enabled/disabled, checking compile-time or runtime value.
///
/// Mirrors the pattern in `frust-render::context`, supporting both compile-time
/// (`option_env!`) and runtime (`std::env::var`) checks. Runtime overrides
/// compile-time.
fn env_flag_enabled(compile_time: Option<&str>, runtime: Option<String>) -> bool {
    if let Some(val) = runtime {
        val.eq_ignore_ascii_case("1") || val.eq_ignore_ascii_case("true")
    } else if let Some(val) = compile_time {
        val.eq_ignore_ascii_case("1") || val.eq_ignore_ascii_case("true")
    } else {
        false
    }
}

/// Parse a default-on environment flag — a kill switch: enabled unless the
/// resolved value is `0` or `false` (any case).
///
/// The same compile-time-or-runtime precedence as [`env_flag_enabled`],
/// resolved through [`env_str`] so an empty runtime value falls through to
/// the compile-time half rather than reading as off.
fn env_flag_default_on(compile_time: Option<&'static str>, runtime: Option<String>) -> bool {
    env_str(compile_time, runtime)
        .is_none_or(|val| !(val.eq_ignore_ascii_case("0") || val.eq_ignore_ascii_case("false")))
}

/// The precedence-resolved value of a string-or-number-valued `FRUST_ENGINE_*`
/// env knob, mirroring `frust-render::context`'s `env_str` combinator: a
/// non-empty runtime (`std::env::var`) value wins even when a compile-time
/// (`option_env!`) value is also set; an empty (`""`) runtime value is
/// treated as unset and falls through to the compile-time half; `None` when
/// neither half carries a non-empty value. This is the same
/// compile-time-or-runtime shape `env_flag_enabled` uses for booleans, kept
/// as its own combinator because `max_texture_size`/`atlas_size` need the
/// raw string (to parse) rather than a bool.
fn env_str(compile_time: Option<&'static str>, runtime: Option<String>) -> Option<String> {
    fn non_empty(value: Option<String>) -> Option<String> {
        value.filter(|v| !v.is_empty())
    }
    non_empty(runtime).or_else(|| non_empty(compile_time.map(str::to_string)))
}

/// Parses a raw `FRUST_ENGINE_MAX_TEX` value (already resolved by
/// [`env_str`]) into the maximum texture edge length. An unset, empty, or
/// unparsable value falls back to `0` (no limit).
fn parse_max_texture_size(raw: Option<String>) -> u32 {
    raw.and_then(|s| s.parse().ok()).unwrap_or(0)
}

/// Parses a raw `FRUST_ENGINE_ATLAS_SIZE` value (already resolved by
/// [`env_str`]), e.g. `"2048x2048"`, into `(width, height)`. Returns `None`
/// if unset or not exactly two `x`-separated integers.
fn parse_atlas_size(raw: Option<String>) -> Option<(u32, u32)> {
    raw.and_then(|s| {
        let parts: Vec<&str> = s.split('x').collect();
        if parts.len() == 2 {
            let w = parts[0].parse::<u32>().ok()?;
            let h = parts[1].parse::<u32>().ok()?;
            Some((w, h))
        } else {
            None
        }
    })
}

/// Whether depth textures are disabled via `FRUST_ENGINE_NO_DEPTH`.
/// Cached: read once per process.
pub fn depth_disabled() -> bool {
    static DISABLED: OnceLock<bool> = OnceLock::new();
    *DISABLED.get_or_init(|| {
        env_flag_enabled(
            option_env!("FRUST_ENGINE_NO_DEPTH"),
            std::env::var("FRUST_ENGINE_NO_DEPTH").ok(),
        )
    })
}

/// Whether every strip run is forced through the whole (Uber) strip program
/// via `FRUST_ENGINE_UBER_PROGRAM`. Cached: read once per process.
///
/// The kill switch over paint-class specialisation
/// ([`crate::gpu::strips::PaintClass`]): when set, no pass segment is split
/// into class runs, no class program is warmed up or built, and every strip
/// pass draws exactly as the engine did before the classes existed — one
/// pipeline per pass, the whole `strip.wgsl` program (of the family
/// [`image_sampler_enabled`] picks). The escape hatch for
/// a driver that miscompiles a specialisation, and the off-arm of every
/// before/after measurement of it. `EngineRenderer::set_uber_program` is its
/// programmatic counterpart.
pub fn uber_program_forced() -> bool {
    static FORCED: OnceLock<bool> = OnceLock::new();
    *FORCED.get_or_init(|| {
        env_flag_enabled(
            option_env!("FRUST_ENGINE_UBER_PROGRAM"),
            std::env::var("FRUST_ENGINE_UBER_PROGRAM").ok(),
        )
    })
}

/// Whether the frame's surface opening stays three passes of its own via
/// `FRUST_ENGINE_NO_PASS_MERGE`. Cached: read once per process.
///
/// The kill switch over pass merging: by default a frame clears its surface,
/// draws its opaque strips and draws its first surface round's strips in ONE
/// render pass (see `crate::renderer`'s *The frame's passes*), which on a
/// tile-based GPU saves a whole-framebuffer load and store per pass folded
/// away. When set, the clear and the opaque strips are recorded as passes of
/// their own ahead of every round, and every surface round in a pass of its
/// own — the off-arm of every before/after measurement of it, and the escape hatch for
/// a driver that mishandles a pipeline switch inside a cleared pass.
/// `EngineRenderer::set_pass_merge` is its programmatic counterpart.
pub fn pass_merge_disabled() -> bool {
    static DISABLED: OnceLock<bool> = OnceLock::new();
    *DISABLED.get_or_init(|| {
        env_flag_enabled(
            option_env!("FRUST_ENGINE_NO_PASS_MERGE"),
            std::env::var("FRUST_ENGINE_NO_PASS_MERGE").ok(),
        )
    })
}

/// Whether Medium-quality atlas images are filtered through the hardware
/// sampler — on unless `FRUST_ENGINE_IMAGE_SAMPLER=0` (or `false`) says
/// otherwise. Cached: read once per process.
///
/// On, the renderer compiles the image-sampling strip programs from their
/// `IMAGE_SAMPLER` specialisation (see [`crate::gpu::shader_src`]): a bilinear
/// atlas image is read with one filtered `textureSampleLevel` instead of four
/// `textureLoad` taps, at the filtering precision of the hardware rather than
/// in full `f32` — within the image tolerance the CPU-oracle gate already
/// holds, at about three quarters of the GPU cost on a magnified image stream.
/// The kill switch (`0`) compiles the manual family instead: no strip layout
/// declares a sampler and every program is the four-tap one — pixel for pixel
/// what the engine drew before the sampler existed — which is the escape hatch
/// for a driver that filters wrongly, and the off-arm of every before/after
/// measurement of it. `EngineRenderer::with_image_sampler` is its
/// programmatic counterpart.
pub fn image_sampler_enabled() -> bool {
    static ENABLED: OnceLock<bool> = OnceLock::new();
    *ENABLED.get_or_init(|| {
        env_flag_default_on(
            option_env!("FRUST_ENGINE_IMAGE_SAMPLER"),
            std::env::var("FRUST_ENGINE_IMAGE_SAMPLER").ok(),
        )
    })
}

/// The shortest class run worth a pipeline switch of its own, via
/// `FRUST_ENGINE_RUN_SPLIT_MIN=<n>`; [`crate::gpu::strips::RUN_SPLIT_MIN`]
/// when unset or unparsable. Cached: read once per process.
///
/// A diagnostic knob for re-measuring the threshold on a device (a build-time
/// `--define` reaches it through `option_env!`); see
/// [`crate::gpu::strips::split_class_runs`] for what it decides.
pub fn run_split_min() -> u32 {
    static MIN: OnceLock<u32> = OnceLock::new();
    *MIN.get_or_init(|| {
        parse_run_split_min(env_str(
            option_env!("FRUST_ENGINE_RUN_SPLIT_MIN"),
            std::env::var("FRUST_ENGINE_RUN_SPLIT_MIN").ok(),
        ))
    })
}

/// Parses a raw `FRUST_ENGINE_RUN_SPLIT_MIN` value (already resolved by
/// [`env_str`]); an unset or unparsable value is the measured default.
fn parse_run_split_min(raw: Option<String>) -> u32 {
    raw.and_then(|s| s.trim().parse().ok())
        .unwrap_or(crate::gpu::strips::RUN_SPLIT_MIN)
}

/// Whether atlas allocation is disabled via `FRUST_ENGINE_NO_ATLAS`.
/// Cached: read once per process.
///
/// Consulted by [`crate::cache::images::ImageResidency`]: when set, every
/// image resolution answers a logged skip instead of touching the atlas.
pub fn atlas_disabled() -> bool {
    static DISABLED: OnceLock<bool> = OnceLock::new();
    *DISABLED.get_or_init(|| {
        env_flag_enabled(
            option_env!("FRUST_ENGINE_NO_ATLAS"),
            std::env::var("FRUST_ENGINE_NO_ATLAS").ok(),
        )
    })
}

/// Whether glyph quads are disabled via `FRUST_ENGINE_NO_GLYPH_QUADS`.
/// Cached: read once per process.
///
/// Consulted when a [`crate::compile::SceneCompiler`] is built: with it set, a
/// glyph run resolved entirely out of the glyph atlas is lowered the way every
/// atlas glyph was before glyph quads existed — one image record per glyph and
/// coverage strips generated from the glyph's rectangle — instead of one
/// record per run and one rect instance per glyph. The kill switch for a
/// device whose glyph quads disagree with that lowering;
/// [`crate::compile::SceneCompiler::set_glyph_quads`] is the per-compiler
/// counterpart a caller comparing the two arms uses.
pub fn glyph_quads_disabled() -> bool {
    static DISABLED: OnceLock<bool> = OnceLock::new();
    *DISABLED.get_or_init(|| {
        env_flag_enabled(
            option_env!("FRUST_ENGINE_NO_GLYPH_QUADS"),
            std::env::var("FRUST_ENGINE_NO_GLYPH_QUADS").ok(),
        )
    })
}

/// Whether parallel strip generation is disabled via
/// `FRUST_ENGINE_NO_PARALLEL`. Cached: read once per process.
///
/// Consulted when a [`crate::compile::SceneCompiler`] is built: with it set,
/// the compiler starts with one worker, so every command's strips are
/// generated on the calling thread during the walk and no helper thread is
/// ever spawned. The kill switch for a device or a host where the per-frame
/// helper costs more than it saves;
/// [`crate::compile::SceneCompiler::set_parallel_workers`] is the
/// per-compiler counterpart a caller comparing the two arms uses.
pub fn parallel_walk_disabled() -> bool {
    static DISABLED: OnceLock<bool> = OnceLock::new();
    *DISABLED.get_or_init(|| {
        env_flag_enabled(
            option_env!("FRUST_ENGINE_NO_PARALLEL"),
            std::env::var("FRUST_ENGINE_NO_PARALLEL").ok(),
        )
    })
}

/// The number of threads a frame's strips are generated on, the calling
/// thread included, via `FRUST_ENGINE_PARALLEL_WORKERS=<n>`; `None` when unset
/// or unparsable, which leaves the compiler's own default. Cached: read once
/// per process.
///
/// A diagnostic knob for re-measuring the worker count on a device (a
/// build-time `--define` reaches it through `option_env!`).
/// `FRUST_ENGINE_NO_PARALLEL` wins over it.
pub fn parallel_workers() -> Option<usize> {
    static WORKERS: OnceLock<Option<usize>> = OnceLock::new();
    *WORKERS.get_or_init(|| {
        parse_parallel_workers(env_str(
            option_env!("FRUST_ENGINE_PARALLEL_WORKERS"),
            std::env::var("FRUST_ENGINE_PARALLEL_WORKERS").ok(),
        ))
    })
}

/// Parses a raw `FRUST_ENGINE_PARALLEL_WORKERS` value (already resolved by
/// [`env_str`]); zero, like an unset or unparsable value, is no override.
fn parse_parallel_workers(raw: Option<String>) -> Option<usize> {
    raw.and_then(|s| s.trim().parse().ok())
        .filter(|workers: &usize| *workers > 0)
}

/// The estimated cost a frame's planned strip generation must reach before a
/// helper thread is spawned for it, via `FRUST_ENGINE_PARALLEL_MIN_COST=<n>`;
/// `None` when unset or unparsable, which leaves
/// [`crate::compile::DEFAULT_PARALLEL_MIN_COST`]. Cached: read once per
/// process.
///
/// A diagnostic knob: `0` hands every frame with a planned shape command to
/// the helpers, which is how a suite of small scenes — the golden images —
/// is run through them.
pub fn parallel_min_cost() -> Option<u64> {
    static MIN_COST: OnceLock<Option<u64>> = OnceLock::new();
    *MIN_COST.get_or_init(|| {
        parse_parallel_min_cost(env_str(
            option_env!("FRUST_ENGINE_PARALLEL_MIN_COST"),
            std::env::var("FRUST_ENGINE_PARALLEL_MIN_COST").ok(),
        ))
    })
}

/// Parses a raw `FRUST_ENGINE_PARALLEL_MIN_COST` value (already resolved by
/// [`env_str`]). Unlike the worker count, zero is a value here — every frame
/// with a planned command spawns — so only an unset or unparsable value is no
/// override.
fn parse_parallel_min_cost(raw: Option<String>) -> Option<u64> {
    raw.and_then(|s| s.trim().parse().ok())
}

/// Whether the resident glyph-run cache is disabled via
/// `FRUST_ENGINE_NO_GLYPH_RUN_CACHE`. Cached: read once per process.
///
/// Consulted when a [`crate::compile::SceneCompiler`] is built: with it set,
/// every glyph run the atlas serves is resolved glyph by glyph through `glifo`
/// on every frame — key, probe, LRU touch, one sink call sequence per glyph —
/// instead of being drawn from the slots the glyph-atlas policy remembered for
/// it on an earlier frame. The kill switch for a device whose cached runs
/// disagree with `glifo`'s own placement;
/// [`crate::compile::SceneCompiler::set_glyph_run_cache`] is the per-compiler
/// counterpart a caller comparing the two arms uses.
pub fn glyph_run_cache_disabled() -> bool {
    static DISABLED: OnceLock<bool> = OnceLock::new();
    *DISABLED.get_or_init(|| {
        env_flag_enabled(
            option_env!("FRUST_ENGINE_NO_GLYPH_RUN_CACHE"),
            std::env::var("FRUST_ENGINE_NO_GLYPH_RUN_CACHE").ok(),
        )
    })
}

/// Whether offscreen fragment-shader effects are disabled via
/// `FRUST_ENGINE_NO_SHADER_EFFECTS`. Cached: read once per process.
///
/// Consulted by [`crate::effects::shader_quad`] and by the compiler's
/// [`frust_scene::Command::ShaderQuad`] lowering: when set, no user fragment
/// program is compiled and no shader quad is drawn — the frame renders
/// everything else and reports the skip once at warning level. The escape
/// hatch for a driver that miscompiles a user shader, where the alternative
/// is losing the whole application rather than one effect.
pub fn shader_effects_disabled() -> bool {
    static DISABLED: OnceLock<bool> = OnceLock::new();
    *DISABLED.get_or_init(|| {
        env_flag_enabled(
            option_env!("FRUST_ENGINE_NO_SHADER_EFFECTS"),
            std::env::var("FRUST_ENGINE_NO_SHADER_EFFECTS").ok(),
        )
    })
}

/// Whether layer caching is disabled via `FRUST_ENGINE_NO_LAYERS`.
/// Cached: read once per process.
///
/// The engine-side kill switch over retained pages
/// ([`crate::cache::retained`]): when set, the renderer's compiler records no
/// retained bracket and lowers every `PushRetained` inline, so the store stays
/// empty, the resident-key ledger stays empty, and a widget tree reading it
/// never emits a `DrawRetained`. The upstream switch, `FRUST_NO_RETAINED_LAYERS`,
/// stops the widgets emitting the commands at all; this one is for a driver
/// that mishandles the page round itself. `SceneCompiler::set_retained_layers`
/// is its programmatic counterpart.
pub fn layers_disabled() -> bool {
    static DISABLED: OnceLock<bool> = OnceLock::new();
    *DISABLED.get_or_init(|| {
        env_flag_enabled(
            option_env!("FRUST_ENGINE_NO_LAYERS"),
            std::env::var("FRUST_ENGINE_NO_LAYERS").ok(),
        )
    })
}

/// The retained-page budget in MiB via `FRUST_ENGINE_RETAINED_BUDGET_MB=<n>`,
/// overriding the adapter tier's own (see
/// [`RetainedBudget::for_caps`](crate::cache::retained::RetainedBudget::for_caps)).
/// `None` when unset, empty or not a whole number; `Some(0)` is a budget no
/// page fits in, which refuses every bracket and retains nothing. Cached: read
/// once per process.
pub fn retained_budget_mb() -> Option<u64> {
    static BUDGET: OnceLock<Option<u64>> = OnceLock::new();
    *BUDGET.get_or_init(|| {
        parse_retained_budget_mb(env_str(
            option_env!("FRUST_ENGINE_RETAINED_BUDGET_MB"),
            std::env::var("FRUST_ENGINE_RETAINED_BUDGET_MB").ok(),
        ))
    })
}

/// Parses a raw `FRUST_ENGINE_RETAINED_BUDGET_MB` value (already resolved by
/// [`env_str`]): a whole number of MiB, or `None`.
fn parse_retained_budget_mb(raw: Option<String>) -> Option<u64> {
    raw.and_then(|value| value.trim().parse().ok())
}

/// Whether resource pooling is disabled via `FRUST_ENGINE_NO_POOL`.
/// Cached: read once per process.
///
/// Reserved: parsed and cached, consulted by nothing yet; wired when its
/// subsystem lands.
pub fn pool_disabled() -> bool {
    static DISABLED: OnceLock<bool> = OnceLock::new();
    *DISABLED.get_or_init(|| {
        env_flag_enabled(
            option_env!("FRUST_ENGINE_NO_POOL"),
            std::env::var("FRUST_ENGINE_NO_POOL").ok(),
        )
    })
}

/// Maximum texture resolution (each axis) via `FRUST_ENGINE_MAX_TEX=<n>`.
/// Parsed as an integer; defaults to 0 (no limit). Cached: read once per process.
///
/// Reserved: parsed and cached, consulted by nothing yet; wired when its
/// subsystem lands.
pub fn max_texture_size() -> u32 {
    static MAX_SIZE: OnceLock<u32> = OnceLock::new();
    *MAX_SIZE.get_or_init(|| {
        parse_max_texture_size(env_str(
            option_env!("FRUST_ENGINE_MAX_TEX"),
            std::env::var("FRUST_ENGINE_MAX_TEX").ok(),
        ))
    })
}

/// Atlas size via `FRUST_ENGINE_ATLAS_SIZE=<WxH>` (e.g., "2048x2048").
/// Parsed as `(width, height)` or returns `None` if not set or invalid.
/// Cached: read once per process.
///
/// Consulted by [`crate::cache::images::AtlasBudget`]: when set, it overrides
/// the capability-chosen per-layer atlas extent (runtime wins).
pub fn atlas_size() -> Option<(u32, u32)> {
    static ATLAS_SIZE: OnceLock<Option<(u32, u32)>> = OnceLock::new();
    *ATLAS_SIZE.get_or_init(|| {
        parse_atlas_size(env_str(
            option_env!("FRUST_ENGINE_ATLAS_SIZE"),
            std::env::var("FRUST_ENGINE_ATLAS_SIZE").ok(),
        ))
    })
}

/// Downlevel mode via `FRUST_ENGINE_DOWNLEVEL=1`.
/// Cached: read once per process.
pub fn downlevel_mode() -> bool {
    static DOWNLEVEL: OnceLock<bool> = OnceLock::new();
    *DOWNLEVEL.get_or_init(|| {
        env_flag_enabled(
            option_env!("FRUST_ENGINE_DOWNLEVEL"),
            std::env::var("FRUST_ENGINE_DOWNLEVEL").ok(),
        )
    })
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_env_flag_enabled() {
        assert!(env_flag_enabled(Some("1"), None));
        assert!(env_flag_enabled(Some("true"), None));
        assert!(env_flag_enabled(Some("TRUE"), None));
        assert!(!env_flag_enabled(Some("0"), None));
        assert!(!env_flag_enabled(Some("false"), None));
        assert!(!env_flag_enabled(None, None));
    }

    #[test]
    fn test_runtime_overrides_compile_time() {
        assert!(env_flag_enabled(Some("0"), Some("1".to_string())));
        assert!(!env_flag_enabled(Some("1"), Some("0".to_string())));
    }

    #[test]
    fn test_env_str_unset_is_none() {
        assert_eq!(env_str(None, None), None);
    }

    #[test]
    fn test_env_str_runtime_wins_over_compile_time() {
        assert_eq!(
            env_str(Some("1024"), Some("2048".to_string())),
            Some("2048".to_string())
        );
    }

    #[test]
    fn test_env_str_empty_runtime_falls_through_to_compile_time() {
        assert_eq!(
            env_str(Some("1024"), Some(String::new())),
            Some("1024".to_string())
        );
    }

    #[test]
    fn test_env_str_compile_time_only() {
        assert_eq!(env_str(Some("1024"), None), Some("1024".to_string()));
    }

    #[test]
    fn test_env_str_runtime_only() {
        assert_eq!(
            env_str(None, Some("2048".to_string())),
            Some("2048".to_string())
        );
    }

    /// The production reader itself, on the value the process was started
    /// with: unset in the gate, so the switch is off and shader effects run.
    /// Reading it here also pins that the reader parses and caches without
    /// panicking, which is what the frame path depends on.
    #[test]
    fn shader_effects_are_enabled_unless_the_switch_is_set() {
        assert!(!shader_effects_disabled());
    }

    #[test]
    fn parallel_workers_parses_a_positive_count_only() {
        assert_eq!(parse_parallel_workers(Some("3".into())), Some(3));
        assert_eq!(parse_parallel_workers(Some(" 2 ".into())), Some(2));
        assert_eq!(parse_parallel_workers(Some("0".into())), None);
        assert_eq!(parse_parallel_workers(Some("two".into())), None);
        assert_eq!(parse_parallel_workers(None), None);
    }

    /// Zero is the one value that differs from the worker count: it is a
    /// threshold every planned frame reaches, not an absent override.
    #[test]
    fn parallel_min_cost_parses_any_count_including_zero() {
        assert_eq!(parse_parallel_min_cost(Some("8000".into())), Some(8000));
        assert_eq!(parse_parallel_min_cost(Some(" 12 ".into())), Some(12));
        assert_eq!(parse_parallel_min_cost(Some("0".into())), Some(0));
        assert_eq!(parse_parallel_min_cost(Some("-1".into())), None);
        assert_eq!(parse_parallel_min_cost(Some("many".into())), None);
        assert_eq!(parse_parallel_min_cost(Some(String::new())), None);
        assert_eq!(parse_parallel_min_cost(None), None);
    }

    /// The switch's own parsing rules, exercised through the combinator every
    /// `FRUST_ENGINE_*` boolean shares — including the runtime-wins
    /// precedence, which is what lets a compile-time-disabled build be
    /// re-enabled at launch.
    #[test]
    fn shader_effects_switch_parses_like_every_other_engine_flag() {
        assert!(env_flag_enabled(None, Some("1".to_string())));
        assert!(env_flag_enabled(None, Some("TRUE".to_string())));
        assert!(!env_flag_enabled(None, Some("0".to_string())));
        assert!(!env_flag_enabled(None, Some(String::new())));
        // Runtime wins in both directions.
        assert!(env_flag_enabled(Some("0"), Some("1".to_string())));
        assert!(!env_flag_enabled(Some("1"), Some("0".to_string())));
    }

    // The `OnceLock` getters (`uber_program_forced`, `pass_merge_disabled`,
    // `image_sampler_enabled`, `run_split_min`, `glyph_quads_disabled`,
    // `glyph_run_cache_disabled`) are
    // deliberately not asserted here: they read the process environment, and
    // a machine running the off-arm captures exports exactly these knobs. The
    // pure parsers above and below are the contract.

    /// A kill switch reads the other way round from every other boolean
    /// here: unset — or set to anything but `0`/`false` — is on.
    #[test]
    fn a_default_on_flag_is_off_only_when_switched_off() {
        assert!(env_flag_default_on(None, None));
        assert!(env_flag_default_on(None, Some("1".to_string())));
        assert!(env_flag_default_on(None, Some(String::new())));
        assert!(!env_flag_default_on(None, Some("0".to_string())));
        assert!(!env_flag_default_on(None, Some("FALSE".to_string())));
        assert!(!env_flag_default_on(Some("0"), None));
        // Runtime wins in both directions; an empty runtime value falls
        // through to the compile-time half.
        assert!(env_flag_default_on(Some("0"), Some("1".to_string())));
        assert!(!env_flag_default_on(Some("1"), Some("0".to_string())));
        assert!(!env_flag_default_on(Some("0"), Some(String::new())));
    }

    #[test]
    fn the_run_split_threshold_parses_or_falls_back_to_the_measured_default() {
        use crate::gpu::strips::RUN_SPLIT_MIN;
        assert_eq!(parse_run_split_min(Some("64".to_string())), 64);
        assert_eq!(parse_run_split_min(Some(" 256 ".to_string())), 256);
        assert_eq!(parse_run_split_min(Some("0".to_string())), 0);
        assert_eq!(parse_run_split_min(Some("many".to_string())), RUN_SPLIT_MIN);
        assert_eq!(parse_run_split_min(None), RUN_SPLIT_MIN);
    }

    #[test]
    fn the_retained_budget_parses_a_whole_number_of_mib_only() {
        assert_eq!(parse_retained_budget_mb(None), None);
        assert_eq!(parse_retained_budget_mb(Some("64".into())), Some(64));
        assert_eq!(parse_retained_budget_mb(Some(" 0 ".into())), Some(0));
        assert_eq!(parse_retained_budget_mb(Some("1.5".into())), None);
        assert_eq!(parse_retained_budget_mb(Some("lots".into())), None);
    }

    #[test]
    fn test_max_texture_size_parsing() {
        assert_eq!(parse_max_texture_size(Some("1024".to_string())), 1024);
        assert_eq!(parse_max_texture_size(Some("0".to_string())), 0);
        assert_eq!(parse_max_texture_size(Some("invalid".to_string())), 0);
        assert_eq!(parse_max_texture_size(None), 0);
    }

    #[test]
    fn test_atlas_size_parsing() {
        assert_eq!(
            parse_atlas_size(Some("2048x2048".to_string())),
            Some((2048, 2048))
        );
        assert_eq!(
            parse_atlas_size(Some("1024x512".to_string())),
            Some((1024, 512))
        );
        assert_eq!(parse_atlas_size(Some("2048".to_string())), None);
        assert_eq!(parse_atlas_size(Some("2048x2048x2048".to_string())), None);
        assert_eq!(parse_atlas_size(None), None);
    }
}