perf(ui): skip the destination read-modify-write on empty tiles (#127)

The standalone per-category UI shaders (quads/circles/images/text)
unconditionally imageLoad the destination pixel up front and imageStore
it at the end, paying a full read-modify-write even on tiles no item
touches — the common case for a sparse UI. The fused uber-kernel already
amortizes a single load/store across all four categories; the standalone
Dispatch* path has no such umbrella.

Defer the imageLoad to just before the first surviving blend (`loaded`
flag) and skip the imageStore unless something was actually blended.
Output is bit-identical: before the first blend `dst` is unused, and a
skipped store leaves the pixel exactly as a no-op load+store would have
rewritten it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
catbot 2026-06-18 13:26:32 +00:00
commit 225556532a
4 changed files with 60 additions and 28 deletions

View file

@ -23,12 +23,16 @@ void main() {
ivec2 screenPx;
bool valid = uiResolveScreenPixel(pc.hdr, screenPx);
vec4 dst = vec4(0.0);
vec2 sp = vec2(0.0);
if (valid) {
dst = imageLoad(uiImages[pc.hdr.outImage], screenPx);
sp = vec2(screenPx) + 0.5;
}
// Defer the destination read-modify-write: a sparse UI leaves most tiles
// untouched, so only load the pixel when the first surviving item blends
// over it (`loaded`), and only store when something actually touched it.
// The fused kernel amortizes a single load/store across all categories; the
// standalone Dispatch* path has no such umbrella and otherwise pays a full
// read-modify-write per empty tile.
vec4 dst = vec4(0.0);
vec2 sp = vec2(0.0);
bool loaded = false;
if (valid) sp = vec2(screenPx) + 0.5;
vec2 tileMin, tileMax;
uiTileBounds(tileMin, tileMax);
@ -90,11 +94,15 @@ void main() {
}
if (src.a <= 0.0) continue;
if (!loaded) {
dst = imageLoad(uiImages[pc.hdr.outImage], screenPx);
loaded = true;
}
dst = uiBlendOver(dst, src);
}
}
barrier();
}
if (valid) imageStore(uiImages[pc.hdr.outImage], screenPx, dst);
if (loaded) imageStore(uiImages[pc.hdr.outImage], screenPx, dst); // loaded ⇒ valid
}