perf(font): upload only the dirty sub-rect of the glyph atlas (#51) #83
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!83
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "claude/issue-51"
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?
Problem
FontAtlas::Updatere-uploaded the entire 1024×1024 R8 atlas (1 MiB) wheneverdirtywas set — anddirtyflipped the moment a single glyph was rasterized. During warm-up / language-switch / size-churn that was roughly one full-atlas copy (full-extentvkCmdCopyBufferToImage+ host-write barrier + two whole-image transitions on Vulkan; fullwriteTextureon WebGPU) per frame that added a codepoint.Fix
Accumulate a dirty bounding box as glyphs are placed and copy only that sub-rect.
FontAtlas::DirtyRect— a half-open[minX,maxX) × [minY,maxY)box grown byMarkDirtyinEnsure/Initialize.UploadBoxclamps it to the atlas and converts it to an(origin, extent)upload rect.dirtystays the cheap per-frame poll flag, kept in lockstep with the rect.ImageVulkan::UpdateRegion: the staging buffer keeps the full atlas row stride, sobufferRowLengthstays the atlas width andbufferOffsetpoints at the rect's first texel, whileimageOffset/imageExtentcarve out the rect. Layout transitions stay whole-image (cheap); only the copy extent shrinks. Single-mip only (the atlas carries no mips). R8 has a 1-byte texel block, so the offset-alignment caveat is moot — confirmed validation-clean.wgpuWriteAtlasRegion, which already acceptedx/y/w/h.The freshly-zeroed atlas marks its whole extent dirty in
Initialize, so the firstUpdateclears the image once; thereafter every untouched texel stays the zero it was uploaded as, keeping the GPU image byte-identical to the staging copy.Tests
FontAtlasDirtyRectunit test — drives the accumulation / degenerate-glyph / clamp /dirty-lockstep math directly (no GPU device needed at runtime).crafter-build test→ all 4 tests green.Screenshots
Native Vulkan (left) and WebGPU in Firefox (right) — glyphs render crisply from the partially-uploaded atlas, no garbage in untouched regions:
Resolves #51
🤖 Generated with Claude Code