Part of #776 — SOLID architecture debt umbrella.
Phase: P3 · Finding: M21
Problem
Two mutable globals violate DIP:
modules/engine-ui/src/font.zig:8 var active_atlas — hidden global pointer, no synchronization, set by UISystemManager and read on every drawText/measureTextWidth.
modules/game-core/src/settings/json_presets.zig:51 pub var graphics_presets — process-wide mutable list, no mutex. Loaded once at startup, read from game-ui settings screens.
Evidence
(Full evidence and file:line citations are in the umbrella #776.)
Fix
- Font atlas: pass it via injection through the UI draw context instead of a global.
- graphics_presets: gate behind an accessor that holds a mutex, or make immutable after load.
Verification
nix develop --command zig build test (includes shader validation)
- If rendering-touching: capture headless screenshot baseline before/after (
-Dskip-present)
- If behavior-preserving refactor: golden-output test must stay green
Constraints
- Small reviewable PR targeting
dev; conventional commit (refactor: / feat:)
- Preserve current behavior unless this issue explicitly changes it
- Keep worker-thread RHI isolation intact (no RHI calls off main thread)
Notes
Currently safe only because UI runs single-threaded on the main thread after single-shot init — an undocumented invariant. Fix removes the latent hazard.
Tracking: #776
Part of #776 — SOLID architecture debt umbrella.
Phase: P3 · Finding: M21
Problem
Two mutable globals violate DIP:
modules/engine-ui/src/font.zig:8var active_atlas— hidden global pointer, no synchronization, set byUISystemManagerand read on everydrawText/measureTextWidth.modules/game-core/src/settings/json_presets.zig:51pub var graphics_presets— process-wide mutable list, no mutex. Loaded once at startup, read from game-ui settings screens.Evidence
(Full evidence and
file:linecitations are in the umbrella #776.)Fix
Verification
nix develop --command zig build test(includes shader validation)-Dskip-present)Constraints
dev; conventional commit (refactor:/feat:)Notes
Currently safe only because UI runs single-threaded on the main thread after single-shot init — an undocumented invariant. Fix removes the latent hazard.
Tracking: #776