perf(ui): hoist loop-invariant per-item/per-glyph math out of the per-pixel loop (#125) #142
No reviewers
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Catcrafts/Crafter.Graphics!142
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "claude/issue-125"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Hoists loop-invariant per-item / per-glyph math out of the per-pixel inner loop and into shared memory at cooperative-load time, where each item is already streamed in once per workgroup. The compiler can't hoist these itself — they read shared memory at a varying index.
Two values, both precomputed once per item into new shared slots:
ui-images,ui-text,ui-fusedimages+text phases):invRectSize = 1.0/rect.zwprecomputed at load, so(sp - rect.xy) / rect.zwbecomes a multiply bys_invRectSize[c].ui-text,ui-fusedtext phase): thebandscale — a vec2 divide plus two maxes that depend only on the glyph's uv span and rect size — is now computed once per glyph intos_band[c].In
ui-fusedthe new shared slots (s_inv,s_band) are reused across the four phases like the existings_v*scratch, so the LDS bump stays at the per-category level rather than summing.Testing
crafter-build test— all 23 tests pass, includingUIFusedShader(compiles the real kernel with glslang + spirv-val and pins the push-constant layout).--target-env vulkan1.4and passspirv-valwith the engine's block-layout flags.HelloUIexample against a live device; text, rounded quads, slider circle, and progress bar all render correctly (text remains crisp, confirming the SDF-band hoist).Screenshots
Resolves #125
The cooperative-load section already streams each item into shared memory once per workgroup, but the per-pixel inner loop then recomputed values that are constant for the whole item/glyph. The compiler can't hoist them itself — they read shared memory at a varying index. Precompute them once per item at load time into new shared slots: - ui-images / ui-text / ui-fused (images+text phases): invRectSize = 1.0/rect.zw, turning the per-pixel `(sp-rect.xy)/rect.zw` vec2 divide into a multiply. - ui-text / ui-fused (text phase): the SDF AA `band` (a vec2 divide + two maxes depending only on the glyph's uv span and rect size). In ui-fused the new slots (s_inv, s_band) are reused across phases like the existing s_v* scratch, so the LDS bump is per-category, not summed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>