refactor(path-layer): separate dash arclength from geometry - #10647
Open
chrisgervang wants to merge 3 commits into
Open
refactor(path-layer): separate dash arclength from geometry#10647chrisgervang wants to merge 3 commits into
chrisgervang wants to merge 3 commits into
Conversation
This was referenced Sep 3, 2026
This was referenced Sep 3, 2026
chrisgervang
marked this pull request as ready for review
September 3, 2026 19:33
Greptile SummaryThis PR separates dash arclength from PathLayer’s geometric coordinates while preserving clipped TripsLayer timestamp interpolation.
Confidence Score: 5/5The PR appears safe to merge with no concrete correctness, security, or build failures identified. The GLSL and WGSL implementations consistently separate geometric and dash coordinates, preserve source-relative interpolation through clipping, and maintain matching conditional shader interfaces with focused assembly and rendering coverage.
|
| Filename | Overview |
|---|---|
| modules/layers/src/path-layer/path-layer-vertex.glsl.ts | Separates geometric segment coordinates from source-segment dash arclength while preserving billboard clipping and 3D scaling. |
| modules/layers/src/path-layer/path-layer-fragment.glsl.ts | Unifies cap, joint, and antialiasing geometry checks across dashed and undashed variants. |
| modules/layers/src/path-layer/path-layer.wgsl.ts | Mirrors the coordinate separation and location-8 varying replacement in the WGSL implementation. |
| modules/extensions/src/path-style/shaders.glsl.ts | Moves dash phase, justification, and offset remapping to the dedicated source-segment coordinate. |
| modules/geo-layers/src/trips-layer/trips-layer.ts | Uses source-relative dash progress for timestamp interpolation when clipping shortens billboard geometry. |
| modules/geo-layers/src/trips-layer/trips-layer.wgsl.ts | Mirrors conditional source-relative timestamp interpolation in WGSL. |
| test/modules/extensions/path.spec.ts | Updates shader-ordering and dash-justification assertions for vDashSegment. |
| test/modules/geo-layers/trips-layer.spec.ts | Adds enabled and disabled WGSL assembly coverage for dash-based TripsLayer interpolation. |
| test/modules/layers/path-antialiasing.spec.ts | Verifies dashed and undashed core fragment geometry remain structurally identical. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
Source[Source segment] --> Vertex[PathLayer vertex shader]
Vertex --> Geometry[Geometric coordinates<br/>vPathPosition + vPathLength]
Vertex --> Dash[Dash arclength<br/>vDashSegment]
Geometry --> Core[Caps, joints, miters, analytic AA]
Dash --> Style[PathStyle dash phase and justification]
Dash --> Trips[TripsLayer source-relative time]
Core --> Fragment[Fragment output]
Style --> Fragment
Trips --> Fragment
Reviews (1): Last reviewed commit: "Merge updated clipped Trips baseline" | Re-trigger Greptile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Goal
Keep PathLayer's geometric coordinates geometric when dashing is enabled.
DASH_ENABLEDpreviously repurposedvPathPosition.yandvPathLengthfor 3D/source-segment arclength. The fragment shader then needed a second bounds varying just to recover the original cap and joint geometry. This change gives dashing one dedicated packed coordinate and lets PathLayer use the same geometric cap, joint, miter, and analytic-AA logic in every variant.Stack (merge bottom-up): #10644 → #10646 → #10647 → #10648 → #10649
Changes
vPathBoundswithvDashSegment, a packed[source-segment position, complete segment length]varying.vPathPosition,vPathLength, andgeometry.uvgeometric with or withoutDASH_ENABLED.No public TypeScript props/types, uniforms, attributes, package-entrypoint exports, or checked-in golden images change. PathStyleExtension remains WebGL-only; the WGSL work keeps the core synthetic
DASH_ENABLEDpath structurally aligned and compilable, but does not add WebGPU PathStyle support.Render equivalence
A strict same-machine A/B against #10646 captured 55 WebGL behaviors: 44 PathStyle dash cases, 10 PathLayer cases, and the TripsLayer case. All 55 behavior captures were byte-for-byte and pixel-for-pixel identical.
That matrix includes the clipped dash composition baseline and #10646's clipped Trips interpolation baseline, plus segment/path modes, units, justification, offsets, rounded caps, analytic AA, subpixel patterns, billboard paths, 3D paths, and ordinary PathLayer/Trips rendering. No golden image changed in this PR.
Internal shader compatibility
vPathPosition,vPathLength, andgeometry.uvare internal shader values rather than public layer API. A custom shader injection that intentionally relied on their dash-only source-arclength meaning should usevDashSegmentunderDASH_ENABLED. Built-in TripsLayer is migrated in this commit.Performance and resource impact
The refactor adds no vertex attribute, buffer layout, uniform, binding, draw call, or per-instance byte.
vDashSegmentreplacesvPathBoundsas one packedvec2and reuses WGSL location 8. There is one narrower linked-shader cost: in whole-path mode the geometricvPathLengthis now used by core cap/joint logic, whereas the parent shader could optimize that scalar away. Active WebGL interstage use moves from 10 variables / 20 scalar components to 11 / 21 in path mode, and is unchanged in segment mode.The existing PathStyle attribute costs remain:
At 100,000 rendered segments with accessor-driven values, those existing PathStyle buffers cost about 0.76 MiB for each two-float attribute and 0.38 MiB for offsets, or up to 1.91 MiB for path-mode dashing plus offset. Constant dash arrays and offsets can use constant attributes instead of per-segment buffers. This PR allocates none of that memory anew and changes none of those sizes.
On the local 16-location WebGL2 device, plain PathLayer uses 13 locations, segment dashing 14, path dashing 15, and path dashing plus offset 16. Plain TripsLayer uses 15 and TripsLayer plus segment dashing uses 16. TripsLayer plus path-mode dashing requires 17 and fails to link on that device; adding offset can require 17 or 18. These are inherited feature-composition limits, not a delta from this refactor.
The resulting varying budget remains comfortable: the largest audited WebGL combination, TripsLayer plus dashing, uses 12 logical varying locations / 22 scalar components, versus 31 / 124 on headless SwiftShader and 30 / 120 on the Apple M1 Max / ANGLE Metal benchmark device. The WGSL path reuses location 8 for the replacement pair rather than allocating a new interstage location.
Apple M1 Max, Chrome/ANGLE Metal, WebGL2 timestamp queries, 3840x2160. The table is the median of four alternating parent/head rounds with 30 samples per variant and workload in each round, comparing
17137f6c0cwith35b98fef56:The fragment-heavy path and all-controls cases measured +1.42% and +1.32%. The plain control moved +0.10%, so the path-mode signal is larger than ordinary run drift and is consistent with the extra live geometric scalar. The largest absolute sparse delta was 0.0393 ms, about 0.24% of a 60 Hz frame or 0.47% of a 120 Hz frame. The latest synchronized merge commits preserve these direct feature trees.
Validation
yarn buildyarn lint— 1,181 files; lockfile validyarn test-headless --run test/modules/layers/path-antialiasing.spec.ts test/modules/extensions/path.spec.ts test/modules/extensions/clip.spec.ts test/modules/geo-layers/trips-layer.spec.ts— 39/39 passedRENDER_TEST_DEVICE=webgl yarn test-render --run test/render/test-cases/path-dash.spec.ts test/render/test-cases/path-layer.spec.ts test/render/test-cases/polygon-layer.spec.ts test/render/test-cases/trips-layer.spec.ts— 63 passed, 5 intentional skipsgit diff --exit-code origin/codex/path-style-trips-dash-baseline -- test/render/golden-imagesThe focused WGSL assembly/device tests passed locally, and GitHub's
test-webgpucheck passed on the current synchronized head. PathStyleExtension itself remains WebGL-only.Note
Medium Risk
Changes core path/Trips shader varyings and coordinate semantics; custom shader injections that relied on dash-only meaning of
vPathPosition.ymust switch tovDashSegment, though public layer API is unchanged.Overview
PathLayer no longer overloads
vPathPosition/vPathLengthfor dash math whenDASH_ENABLEDis on. A dedicatedvDashSegmentvarying ([position along source segment, full segment length]) replacesvPathBounds, so caps, joints, analytic AA, and clipping use the same geometric coordinates with or without dashing.PathStyleExtension dash phase, justification, and offset remapping now read
vDashSegmentinstead of repurposed path position. TripsLayer (GLSL/WGSL) interpolates trip time fromvDashSegmentwhen dashing is enabled so timestamps stay tied to the full source segment when billboard clipping shortens visible geometry.Core PathLayer fragment shaders drop dash-specific bound checks; tests assert dash and non-dash fragment bodies stay aligned aside from the new varying.
Reviewed by Cursor Bugbot for commit 5dd2826. Bugbot is set up for automated code reviews on this repo. Configure here.