Switch to SLUG/DrawGlyph font drawing stack (#1042)
* Switch to SLUG/DrawGlyph font drawing stack (via Codex) * Improve same-frame new glyph caching and SLUG packed instances * avoid performance regression by batch updating slug atlas cache * TextFlow: separate SLUG glyph batches to avoid interleaving HTML text drawing * SLUG optimization: append instead of a full clone each generation * trying out codex perf fix for linux wayland * Disable SLUG glyps on Linux for now * Fix Linux SLUG rendering, warmup, and promotion behavior - re-enable Linux SLUG through a separate Linux-only DrawText helper instead of bloating the normal DrawText shader path - preserve widget text styling on Linux SLUG by syncing common DrawText state into the helper, including base colors, gradients, and interactive states such as hover, focus, down, active, pressed, drag, empty, and disabled - keep normal Linux UI text on the raster/MSDF path and only switch to SLUG above the Linux cutoff, while still falling back cleanly when SLUG data is unavailable - fix Linux SLUG glyph placement so promoted text uses the correct glyph origin, layout position, and atlas packing - add progressive SLUG warmup on Linux by budgeting glyph generation and uploads across redraws and falling back to raster/MSDF until SLUG data is actually ready - lazily register and prewarm the shared Linux SLUG helper so app startup and first-use latency stay low - opt only the Linux SLUG helper into async GL shader compilation and use parallel shader compile support when available, avoiding the large startup and first-tab stalls seen before - fix Linux runtime shader issues caused by copied widget text shaders and custom get_color logic by using a shared helper shader with the expected text-state inputs - stabilize Linux SLUG promotion by preventing stale retained areas, cleaning up raster/helper ownership correctly during draw, and shadow-promoting the first ready SLUG frame before making it visible - eliminate the visible SLUG handoff flicker so Linux text now switches from raster/MSDF to SLUG without freezes or noticeable visual artifacts - add a dedicated UIZoo SLUG tab with side-by-side below-cutoff and above-cutoff examples, plus diagnostic cases for plain labels, gradients, custom text shaders, and glyph/color probes - keep the final diff focused by removing unrelated formatting-only churn from the worktree during cleanup * Tighten Linux SLUG promotion and helper sync - make Linux SLUG promotion state local to each DrawText instance instead of using a global per-redraw gate - cache Linux SLUG helper shader field intersections so helper state syncing avoids repeated per-draw allocations and linear membership checks - harden the shadow-promotion fallback path so failed helper batching only takes a single raster fallback path - preserve DrawText memory alignment after adding Linux SLUG bookkeeping * try to fix emoji on Android * emoji fix take 2 * uizoo example: allow touch/drag scroll. Don't panic in FileTree demo * Fix emoji on Android * Windows: async HLSL shader compile + extend SLUG helper path to Windows Fixes two major performance issues on Windows that made uizoo unusable on first launch: 1. **60-75s startup stall** caused by synchronous `D3DCompile` of ~30+ SLUG-bearing text shader variants on the UI thread before the window could present. 2. **3-4s hang when opening the SLUG tab** caused by synchronous compile of the fat DrawTextSlug helper shader the first time a SLUG glyph was needed. Also fixes a latent HLSL-only `CreateInputLayout` E_INVALIDARG crash triggered by shaders with >26 instance inputs (exposed by DrawTextSlug). `DrawTextLinuxSlug` → `DrawTextSlug` and all `linux_slug_*` / `LinuxSlug*` symbols dropped their `Linux` prefix. Cfg guards expanded from `target_os = "linux"` to `any(target_os = "linux", target_os = "windows")` so Windows now: - uses the same lean base `DrawText` shader (SDF/MSDF only, no SLUG curve-solver HLSL inlined) - uses a separate `DrawTextSlug` helper shader for the SLUG path - has the same progressive glyph-build budget and DPI cutoff (`default_slug_new_glyphs_per_redraw`, `default_slug_min_dpxs_per_em` in `fonts.rs` now match `OsType::Windows` alongside the Linux variants) - falls back to raster/MSDF while the SLUG helper shader or its glyph data isn't yet ready macOS/iOS/Android/WASM paths are untouched — they still use the fat all-in-one `DrawText` shader via `cfg(not(any(linux, windows)))`. Added `AsyncHlslCompile` in `d3d11.rs` and an `async_hlsl_compile` field on `CxOs`. Shaders flagged `async_compile: true` (the SLUG helper) now dispatch to a background thread per shader via `std::thread::Builder` (named `hlsl-compile-<id>` for debugging). Workers call `D3DCompile` off the UI thread, write the resulting DXBC to the on-disk cache, and send only a status result (not the bytes themselves — SLUG is ~240 KB and ferrying it through the channel is wasteful) back via an mpsc channel guarded by a `Mutex`. `hlsl_compile_shaders` drains completed results at the top of each call, constructs `CxOsDrawShader` objects on the main thread (the bytes come from the cache-hit path in `CxOsDrawShader::new`), and triggers `redraw_all()` so widgets whose shaders just became ready get re-rendered. The existing `sh.os_shader_id.is_none()` guard in `render_view` handles skipping the draw call while a shader is pending. Added `Cx::is_draw_shader_window_ready()` on Windows for the SLUG helper's readiness check; on Windows it's simply `os_shader_id.is_some()` since HLSL compile is either synchronous (cache hit) or tracked via the async path. Cold-start still compiled 30+ shaders synchronously (parallelized via `std::thread::scope`) which took ~5-10s because FXC's per-call speed is the bottleneck and parallelism helps less than expected. Now `hlsl_compile_shaders` partitions queued shaders by cache state: - cache hit → sync path: disk read + D3D11 object creation, a few ms - cache miss OR `async_compile: true` → async path: worker thread On a fully cold cache, every shader is a cache miss → the window presents on the first frame with no compile work on the UI thread. Widgets fill in over the next ~1-2s as their shaders become ready. On a warm cache every shader is a hit → instant startup as before. Added `shader_bytes_cached()` for cheap existence checking of the cache entries. `d3d_compile_hlsl` now passes `D3DCOMPILE_SKIP_OPTIMIZATION`. FXC's optimizer is what makes individual compiles burn hundreds of ms to seconds on text shaders with loops; UI shaders don't benefit enough from it to justify the cold-cache cost. If a specific shader is later shown to be a runtime hotspot, the fix is to recompile it optimized on a background thread and hot-swap, not to pay the cost upfront for every shader. Bumped `CACHE_KEY_VERSION` to 2 so pre-existing `.dxbc` blobs compiled with the old flags are invalidated cleanly on upgrade. `d3d11.rs` used its own `index_to_char(i) = i + 'A'` which produced invalid HLSL semantic names (`[`, `\`, `]`, …) past 26 inputs, while the HLSL generator in `shader_hlsl.rs` already used a correct multi-character scheme (`A..Z, AA..AZ, BA..`). `CreateInputLayout` returned E_INVALIDARG because the names didn't match. Replaced with `makepad_script::shader_hlsl::index_to_semantic` so both sides of the binding agree. This was a latent bug — no existing shader had >26 instance inputs until `DrawTextSlug` (which inherits many interactive-state fields from Label-derived shaders). Linux/GLSL is unaffected because GLSL binds by identifier, not semantic name. - Hoisted `d3d_compile_hlsl`, `hlsl_cache_key`, and `get_or_compile_shader_bytes` out of `CxOsDrawShader::new` to module scope so they can be shared with the async worker. - Compute `hlsl_cache_key` once per shader during partition and reuse at dispatch instead of recomputing. - Scoped borrows in the async drain loop eliminate mapping/bindings clones. - `platform/src/os/windows/d3d11.rs` — compile pipeline, async infra, semantic-name fix - `platform/src/os/windows/windows.rs` — `async_hlsl_compile` field on `CxOs` - `draw/src/shader/draw_text.rs` — rename `LinuxSlug*` → `Slug*`, expand cfg gates - `draw/src/text/fonts.rs` — extend SLUG cutoff/budget defaults to Windows No changes to macOS, iOS, Android, or WASM paths.
K
Kevin Boos committed
85fbea9b0fa99889b39bb5889ce77f910cb855dd
Parent: 03a64a9
Committed by GitHub <noreply@github.com>
on 4/16/2026, 8:50:48 PM