Merge pull request 'perf(font): upload only the dirty sub-rect of the glyph atlas (#51)' (#83) from claude/issue-51 into master
This commit is contained in:
commit
991a39e094
5 changed files with 276 additions and 6 deletions
|
|
@ -39,13 +39,17 @@ void FontAtlas::Initialize(GraphicsCommandBuffer cmd) {
|
|||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
);
|
||||
std::memset(image.buffer.value, 0, kAtlasSize * kAtlasSize);
|
||||
dirty = true;
|
||||
#else
|
||||
(void)cmd;
|
||||
staging.assign(kAtlasSize * kAtlasSize, 0);
|
||||
textureHandle = WebGPU::wgpuCreateAtlasTexture(kAtlasSize, kAtlasSize);
|
||||
dirty = true;
|
||||
#endif
|
||||
// The freshly-zeroed atlas backs an image whose contents are undefined
|
||||
// (Vulkan) / unwritten (WebGPU). Mark the whole extent dirty so the
|
||||
// first Update clears it once; thereafter only glyph sub-rects flip
|
||||
// dirty, and every untouched texel stays the zero it was uploaded as —
|
||||
// so partial uploads keep the image byte-identical to the staging copy.
|
||||
MarkDirty(0, 0, kAtlasSize, kAtlasSize);
|
||||
}
|
||||
|
||||
bool FontAtlas::ShelfPlace(int w, int h, int& outX, int& outY) {
|
||||
|
|
@ -112,7 +116,7 @@ bool FontAtlas::Ensure(Font& font, std::uint32_t codepoint) {
|
|||
g.v0 = static_cast<float>(py) / kAtlasSize;
|
||||
g.u1 = static_cast<float>(px + sw) / kAtlasSize;
|
||||
g.v1 = static_cast<float>(py + sh) / kAtlasSize;
|
||||
dirty = true;
|
||||
MarkDirty(px, py, sw, sh);
|
||||
}
|
||||
|
||||
cache_.emplace(key, g);
|
||||
|
|
@ -126,16 +130,28 @@ const Glyph* FontAtlas::Lookup(Font& font, std::uint32_t codepoint) const {
|
|||
|
||||
void FontAtlas::Update(GraphicsCommandBuffer cmd) {
|
||||
if (!dirty) return;
|
||||
|
||||
// Clamp the accumulated box to the atlas and convert to (origin,
|
||||
// extent). Add() works in glyph coordinates that are always in-bounds,
|
||||
// but clamping keeps the copy extent provably valid. The `dirty` guard
|
||||
// above guarantees the rect is non-empty, so UploadBox always fills the
|
||||
// outputs.
|
||||
std::uint32_t x = 0, y = 0, w = 0, h = 0;
|
||||
dirtyRect.UploadBox(kAtlasSize, x, y, w, h);
|
||||
|
||||
#ifndef CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
image.Update(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
image.UpdateRegion(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, x, y, w, h);
|
||||
#else
|
||||
(void)cmd;
|
||||
// Full-atlas upload. Future: track dirty region.
|
||||
// The staging buffer keeps the full atlas row stride, so srcBytesPerRow
|
||||
// stays kAtlasSize and (dstX, dstY) index the sub-rect's first texel.
|
||||
WebGPU::wgpuWriteAtlasRegion(
|
||||
textureHandle, staging.data(),
|
||||
kAtlasSize, kAtlasSize, kAtlasSize,
|
||||
0, 0, kAtlasSize, kAtlasSize
|
||||
static_cast<std::int32_t>(x), static_cast<std::int32_t>(y),
|
||||
static_cast<std::int32_t>(w), static_cast<std::int32_t>(h)
|
||||
);
|
||||
#endif
|
||||
dirty = false;
|
||||
dirtyRect.Reset();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue