perf(ui): subgroup prefix-sum stream compaction in the UI compute shaders (#124) #145
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!145
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "claude/issue-124"
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?
Summary
uiCompactChunk(and the same pattern inlined in the four standalone UI shaders) ran the per-chunk survivor scan entirely ongl_LocalInvocationIndex == 0— ~64 serial iterations with 63/64 lanes idle, between two barriers, 4× per chunk in the fused kernel. It has to produce a stable in-order (buffer-order) exclusive prefix of the survivors intos_order[]so the per-pixel inner loop still sees items in draw order.This replaces the lane-0 scan with a subgroup exclusive prefix-sum + cross-subgroup carry:
subgroupExclusiveAdd(keep)(rank within the subgroup) andsubgroupAdd(keep)(its survivor total) at register speed.s_subTotals[].base + subPrefix= the number of survivors with a smaller local index → buffer (draw) order preserved exactly. (AnatomicAddwould scramble order — deliberately avoided, per the issue.)The carry makes it correct for any subgroup width (2 subgroups on the 32-wide
descriptor_heaptarget, up to 8/16 on narrower parts), relying only on thegl_LocalInvocationIndex↔(gl_SubgroupID, gl_SubgroupInvocationID)linear mapping every Vulkan compute implementation provides. The feature is free at the device baseline (apiVersion 1.4+VK_EXT_descriptor_heapimplies Vulkan 1.1 subgroup arithmetic), so no correctness fallback is needed. WebGPU is unaffected (it runs separate embedded WGSL).Applied to
ui-fused.comp.glsland the inlined pattern inui-quads/circles/images/text.Verification
crafter-build test— all 23 pass, includingUIFusedShader(recompilesui-fused.comp.glslwith glslang, runsspirv-val, and pins the push-constant member offsets — unchanged).HelloUI(which usesDispatchFusedwith quads + circles + text) renders correctly on an RTX 4090 — the 2-subgroups-per-workgroup carry path. Text composites on top of the button quad and the circle knob on top of the slider track, confirming draw order is intact.Screenshots
Resolves #124