[perf][MEDIUM] Full 1 MiB font atlas re-upload on any single new glyph #51

Closed
opened 2026-06-16 16:51:31 +02:00 by jorijnvdgraaf · 0 comments

Subsystem: Font / FontAtlas
Location: implementations/Crafter.Graphics-FontAtlas.cpp:127-141
Impact: MEDIUM · Effort: Medium

Problem

Update uploads the entire 1024x1024 R8 atlas (1,048,576 bytes) whenever dirty is set — and dirty flips the moment one glyph is rasterized. Vulkan does a full-extent vkCmdCopyBufferToImage + host-write barrier + two whole-image transitions; WebGPU writes the full atlas. During warm-up/language-switch/size-churn this is ~one full-atlas copy per frame that adds a codepoint.

Proposed fix

Accumulate a dirty bounding rect in ShelfPlace/Ensure; copy only that sub-rect. The staging buffer is already laid out at full atlas row stride, so set bufferOffset = minY*kAtlasSize+minX, bufferRowLength = kAtlasSize, imageOffset/imageExtent to the rect. Reset the rect after upload. WebGPU's wgpuWriteAtlasRegion already takes x,y,w,h.

Correctness caveat

Layout transitions/barrier can stay whole-image (cheap); only the copy extent is load-bearing. Honor optimalBufferCopyOffsetAlignment (typically 1 for R8) — round the rect origin down if a driver reports coarser.

**Subsystem:** Font / FontAtlas **Location:** `implementations/Crafter.Graphics-FontAtlas.cpp:127-141` **Impact:** MEDIUM · **Effort:** Medium ### Problem `Update` uploads the entire 1024x1024 R8 atlas (1,048,576 bytes) whenever `dirty` is set — and `dirty` flips the moment one glyph is rasterized. Vulkan does a full-extent `vkCmdCopyBufferToImage` + host-write barrier + two whole-image transitions; WebGPU writes the full atlas. During warm-up/language-switch/size-churn this is ~one full-atlas copy per frame that adds a codepoint. ### Proposed fix Accumulate a dirty bounding rect in `ShelfPlace`/`Ensure`; copy only that sub-rect. The staging buffer is already laid out at full atlas row stride, so set `bufferOffset = minY*kAtlasSize+minX`, `bufferRowLength = kAtlasSize`, `imageOffset/imageExtent` to the rect. Reset the rect after upload. WebGPU's `wgpuWriteAtlasRegion` already takes x,y,w,h. ### Correctness caveat Layout transitions/barrier can stay whole-image (cheap); only the copy extent is load-bearing. Honor `optimalBufferCopyOffsetAlignment` (typically 1 for R8) — round the rect origin down if a driver reports coarser.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Catcrafts/Crafter.Graphics#51
No description provided.