Skip to content

refactor(gsplat): move GPU sort/cull pipeline into the hybrid renderer#8924

Merged
mvaligursky merged 7 commits into
mainfrom
mv-gsplat-renderer-gpu-pipeline
Jun 18, 2026
Merged

refactor(gsplat): move GPU sort/cull pipeline into the hybrid renderer#8924
mvaligursky merged 7 commits into
mainfrom
mv-gsplat-renderer-gpu-pipeline

Conversation

@mvaligursky

Copy link
Copy Markdown
Contributor

Moves the GPU sort/projection/cull pipeline out of GSplatManager and into GSplatHybridRenderer, so each renderer owns its own per-view GPU work. Behavior-preserving. This is the prerequisite for an upcoming directional-shadow renderer that needs to reuse the per-view cull without duplicating manager plumbing.

Changes:

  • GSplatManager is slimmed to: GSplatWorld ownership, the world version lifecycle (markSorted/onSorted), the CPU worker sorter, and per-frame orchestration (~500 fewer lines). The version lifecycle stays here via a new _markSortedIfNeeded (the synchronous GPU counterpart of onSorted), called before delegating. The manager passes per-call parameter bags to the renderer, with no renderer→manager back-reference.
  • GSplatHybridRenderer now owns its GPU pipeline: the radix sorter, projector, interval compaction, and indirect draw/dispatch slots (created in its constructor, freed in destroy()), plus the cull/project/sort methods (prepareRenderView, sortAndProjectForCamera, _runFrustumCulling, computeDistanceRange, allocateAndWriteIntervalIndirectArgs). Picking moves to preparePickingView.
  • GSplatRenderer (base) gains capability getters (usesGpuSort / requiresBounds / requiresCpuSort) and the prepareRenderView / preparePickingView / invalidateCullUpload interface, plus a GSplatRenderViewParams typedef for the per-call param bag. The manager now branches on these capabilities instead of activeRenderer.
  • The two per-frame GPU sort call sites collapse into one; vestigial frustum-change trackers (testFrustumChanged, lastCulling*) and the canCull getter are removed. GSplatQuadRenderer (CPU sort) is unchanged.

API Changes:

  • None. All affected classes are internal (@ignore).

Performance:

  • No change to rendered output or steady-state cost — this is a behavior-preserving move (autoRender = true and on-demand paths both unchanged).

Martin Valigursky added 5 commits June 18, 2026 14:27
…ches

Step 1-2 of moving the GPU pipeline into the renderer: add usesGpuSort/
requiresBounds/requiresCpuSort getters (base false, hybrid true) and route the
manager's per-frame activeRenderer checks through them. No behavior change;
activeRenderer is now used only for the prepareRendererMode mode-compare.
Step 3-4: extract _markSortedIfNeeded() (the first-sort version-advance + rebuild
reaction) as the synchronous GPU counterpart of onSorted, and call it from update()
before delegating the GPU sort; collapse the two GPU sortGpuHybrid call sites into one
unconditional per-frame GPU delegate (behavior-identical) and remove the now-duplicate
markSorted call from sortGpuHybridForCamera. No behavior change.
Step 5: the hybrid renderer now owns its radix sorter, projector, interval
compaction and indirect slots, and the cull/project/sort methods
(prepareRenderView, sortAndProjectForCamera, _runFrustumCulling,
computeDistanceRange, allocateAndWriteIntervalIndirectArgs). Picking moves to
the renderer's preparePickingView. The manager keeps the world, the version
lifecycle (markSorted/onSorted), and the CPU worker sorter, passing per-call
param bags to the renderer (no back-reference). Behavior-preserving.
Step 6-8: the GPU path culls/sorts every frame, so the frustum-change trackers
(testFrustumChanged, lastCullingCameraFwd/ProjMat) were vestigial after the move —
remove them; the CPU re-sort trackers (testCameraMovedForSort, lastSortCamera*)
stay. Remove the now-unused canCull getter and refresh the manager class doc to
describe the world/CPU-sort vs renderer-GPU-pipeline split.
… param bag

Replace the untyped 'object' param bag with a GSplatRenderViewParams typedef defined
on GSplatRenderer (the interface owner) and referenced from the manager and hybrid
renderer. Also adds the base prepareRenderView/preparePickingView stubs (typed) and
types the world/worldState params. Type-only change.
@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown

Build size report

This PR changes the size of the minified bundles.

Bundle Minified Gzip Brotli
playcanvas.min.js 2284.2 KB (−0.2 KB, −0.01%) 586.1 KB (+0.8 KB, +0.13%) 455.7 KB (−0.1 KB, −0.01%)
playcanvas.min.mjs 2281.6 KB (−0.2 KB, −0.01%) 585.1 KB (+0.7 KB, +0.13%) 455.2 KB (+0.3 KB, +0.06%)

…public API)

The typedef is internal plumbing between the manager and the hybrid renderer, not
public API. Add @ignore so TypeDoc/api-report exclude it, and reference GSplatVaryings
via an inline import() type (keeps it resolvable without a separate @import line that
lint would prune as unused once the typedef is ignored).
@mvaligursky mvaligursky merged commit abbfd02 into main Jun 18, 2026
10 checks passed
@mvaligursky mvaligursky deleted the mv-gsplat-renderer-gpu-pipeline branch June 18, 2026 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant