perf(ui): scope inter-dispatch barrier to the swapchain image (#48) #88

Merged
catbot merged 1 commit from claude/issue-48 into master 2026-06-16 18:54:34 +02:00
Member

Summary

UIRenderer::Dispatch inserted a queue-wide VkMemoryBarrier (SHADER_WRITE -> SHADER_READ|WRITE) before every dispatch after the first. As a global memory barrier it flushes/invalidates all shader caches, even though the only hazard is the read-modify-write of the single swapchain storage image that every UI pass shares. A typical quads/circles/images/text frame pays 3 of these.

This narrows it to a VkImageMemoryBarrier scoped to the swapchain image's subresource (COMPUTE_SHADER -> COMPUTE_SHADER, GENERAL -> GENERAL, no layout transition). Same correctness — later passes still observe earlier passes' writes — but only this image's caches are flushed; unrelated buffers/images are no longer invalidated.

Honest limit

This is a narrower cache flush only. The execution dependency stays compute->compute over the whole queue, so the passes still do not overlap. Eliminating the barriers entirely requires fusing consecutive passes into one dispatch, tracked separately in #47 and intentionally out of scope here.

Per the issue's Do NOT: a VkBufferMemoryBarrier would be the wrong barrier type for an image hazard and would corrupt output — this uses an image barrier.

Testing

  • crafter-build test — 7 passed.
  • Built and ran the HelloUI example natively (Wayland/Vulkan, NVIDIA RTX 4090) with validation layers (GPU-AV + Core Check) enabled. The multi-pass frame (quads -> circles -> text) renders with no validation/sync errors and correct overdraw ordering.

Screenshots

HelloUI rendered with quads, circles and text

Resolves #48

## Summary `UIRenderer::Dispatch` inserted a queue-wide `VkMemoryBarrier` (`SHADER_WRITE -> SHADER_READ|WRITE`) before every dispatch after the first. As a global memory barrier it flushes/invalidates **all** shader caches, even though the only hazard is the read-modify-write of the single swapchain storage image that every UI pass shares. A typical quads/circles/images/text frame pays 3 of these. This narrows it to a `VkImageMemoryBarrier` scoped to the swapchain image's subresource (`COMPUTE_SHADER -> COMPUTE_SHADER`, `GENERAL -> GENERAL`, no layout transition). Same correctness — later passes still observe earlier passes' writes — but only this image's caches are flushed; unrelated buffers/images are no longer invalidated. ## Honest limit This is a **narrower cache flush only**. The execution dependency stays compute->compute over the whole queue, so the passes still do not overlap. Eliminating the barriers entirely requires fusing consecutive passes into one dispatch, tracked separately in #47 and intentionally out of scope here. Per the issue's *Do NOT*: a `VkBufferMemoryBarrier` would be the wrong barrier type for an image hazard and would corrupt output — this uses an image barrier. ## Testing - `crafter-build test` — 7 passed. - Built and ran the HelloUI example natively (Wayland/Vulkan, NVIDIA RTX 4090) with validation layers (GPU-AV + Core Check) enabled. The multi-pass frame (quads -> circles -> text) renders with no validation/sync errors and correct overdraw ordering. ## Screenshots ![HelloUI rendered with quads, circles and text](https://forgejo.catcrafts.net/attachments/c4a38b09-2171-4364-b54a-f4f1f6cbc185) Resolves #48
UIRenderer::Dispatch inserted a queue-wide VkMemoryBarrier
(SHADER_WRITE -> SHADER_READ|WRITE) before every dispatch after the
first, flushing/invalidating all shader caches even though the only
hazard is the read-modify-write of the single swapchain storage image
that every UI pass shares.

Narrow it to a VkImageMemoryBarrier scoped to that image's subresource
(COMPUTE -> COMPUTE, GENERAL -> GENERAL, no layout transition). Same
correctness — later passes still observe earlier passes' writes — but
only this image's caches are flushed; unrelated resources are no longer
invalidated.

This is a narrower cache flush only: the execution dependency stays
compute->compute queue-wide, so passes still do not overlap. Eliminating
the barriers entirely requires pass fusion (#47) and is intentionally
out of scope here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
catbot merged commit c1bd5fe244 into master 2026-06-16 18:54:34 +02:00
catbot deleted branch claude/issue-48 2026-06-16 18:54:34 +02:00
Sign in to join this conversation.
No reviewers
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!88
No description provided.