feat(rendering): geometry pixel snapping on the GPU — closes R2#389
Conversation
…o the vertex shaders
…delete the CPU snap path
Bundle ReportChanges will increase total bundle size by 292.59kB (1.23%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: exo-iife-min-Exo-iifeAssets Changed:
Files in
view changes for bundle: exo-esm-modules-esmAssets Changed:
Files in
Files in
Files in
Files in
Files in
Files in
Files in
Files in
Files in
Files in
Files in
Files in
Files in
Files in
Files in
Files in
view changes for bundle: exojs-react-esmAssets Changed:
view changes for bundle: exo-esm-esmAssets Changed:
Files in
view changes for bundle: exojs-physics-esmAssets Changed:
view changes for bundle: exojs-tilemap-esmAssets Changed:
Files in
Files in
view changes for bundle: exo-full-iife-Exo-iifeAssets Changed:
Files in
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…-snapped drawables The "CPU snap path deleted" commit (2295709) intentionally made both pixel-snap modes fully GPU-resolved and therefore recordable — the isRetainedFragmentRecordable() predicate no longer inspects pixelSnapMode at all. These two tests still asserted the pre-change expectation (geometry-snap = non-recordable / poisons the recording), which the CI run for this PR has been failing on since 2026-07-19.
Second and final PR of the GPU pixel-snapping track. PR 1 (#388) made the enum break and moved position snapping into the vertex shaders. This PR moves geometry boundary snapping there too, then deletes the entire CPU snap path and the last retained-recording exceptions — closing roadmap R2 completely (snapping is now one GPU mechanism).
What changes
floor(local · scale + 0.5) / scale) from the same composed pipeline the origin snap uses, gated on the row flag (m1.z == 2) and only when the composed transform is axis-aligned (decided in-shader from the linear part's cross-terms). Because a shared edge is the same absolute bit value and the round is pure, seams stay closed with no instance-format change.destW/destHderived from the snapped corners (shader strategy), so the tile period stays aligned to the snapped destination width.snapQuadsInto,snapBoundsInto,buildPixelSnapContext,snapLocalBoundary,resolveEffectivePixelSnapMode, the render-quad helpers) plusSprite.getRenderBounds/NineSlice/RepeatinggetRenderQuads/getRenderBoundsand the dead_getSnapPixelSizebackend methods.pixelSnap.tsnow exports onlyPixelSnapMode+isPixelSnapMode.Testing
rendering-perfstructural gates: geometry-snapped sprites and a geometry-snapped tilemap inside aRetainedContainernow reach the recorded tier under a camera pan (zero instance/transform re-upload); the old "geometry still poisons" gate is replaced.@internal).Behavior note: the once-per-frame
geometry downgraded to positiondev-warn is removed with the CPU path. The downgrade still happens, now silently in-shader.