Skip to content

perf(gsplat): scalable per-splat culling for hybrid shadows#8939

Merged
mvaligursky merged 1 commit into
mainfrom
mv-gsplat-shadow-cull-opt
Jun 22, 2026
Merged

perf(gsplat): scalable per-splat culling for hybrid shadows#8939
mvaligursky merged 1 commit into
mainfrom
mv-gsplat-shadow-cull-opt

Conversation

@mvaligursky

@mvaligursky mvaligursky commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Adds per-splat culling (opacity, size, frustum) to the GPU-sort (hybrid) directional-shadow path, while sharing its candidate buffer with the forward renderer to save GPU memory.

Changes:

  • The hybrid directional-shadow cull now runs as a projector-style two pass: a coarse per-node frustum compaction (reusing GSplatIntervalCompaction with the light's frustum) produces a dense candidate list, then a flat one-thread-per-candidate pass applies the per-splat fine tests — opacity (alphaClip), world-space size (a CPU-precomputed orthographic threshold; no per-splat projection), and the 6 light frustum planes — and compacts the survivors. This replaces the previous coarse-only cull and applies the same gsplatModifyVS vertex-modify as the draw, so cast shadows still match the forward pass.
  • The flat fine-cull dispatch keeps full GPU occupancy regardless of how a scene is split into intervals (a single large object vs many octree nodes), fixing a pathological case where few/large intervals serialized the cull onto a handful of workgroups.
  • The compaction candidate buffer is now shared, per manager, between the forward hybrid renderer and the shadow cull (new internal GSplatHybridRendererScratch, manager-owned, created only while a GPU-sort renderer is in use). They use it at disjoint points in the frame, so one allocation suffices.

The GPU-sort (hybrid) directional-shadow cull now does per-splat culling
(opacity, world-space size, and per-splat frustum) instead of coarse
per-node only, implemented as a projector-style two pass:

- Pass 1 reuses GSplatIntervalCompaction with the light's frustum to produce
  a dense candidate list (coarse per-node frustum cull + compaction).
- Pass 2 is a flat one-thread-per-candidate fine cull (opacity <= alphaClip,
  max world-space scale below a CPU-precomputed orthographic size threshold,
  and the 6 light frustum planes), compacting survivors into the per-light
  draw list. It applies the same vertex-modify as the draw, so cast shadows
  match the forward pass.

The flat fine-cull dispatch keeps full GPU occupancy regardless of how a
scene is split into intervals, fixing a pathological case where a few large
intervals (e.g. non-octree objects) serialized the cull onto a handful of
workgroups.

The compaction candidate buffer is now shared, per manager, between the
forward hybrid renderer and the shadow cull via a manager-owned
GSplatHybridRendererScratch (created only while a GPU-sort renderer is in
use). The two paths use it at disjoint points in the frame, so a single
allocation suffices, saving one candidate buffer per manager.
@github-actions

Copy link
Copy Markdown

Build size report

This PR changes the size of the minified bundles.

Bundle Minified Gzip Brotli
playcanvas.min.js 2282.8 KB (+2.2 KB, +0.10%) 585.6 KB (+0.8 KB, +0.13%) 455.3 KB (+0.5 KB, +0.12%)
playcanvas.min.mjs 2280.3 KB (+2.2 KB, +0.10%) 584.8 KB (+0.8 KB, +0.15%) 454.6 KB (+0.6 KB, +0.12%)

@mvaligursky mvaligursky requested a review from Copilot June 22, 2026 13:12
@mvaligursky mvaligursky added the area: graphics Graphics related issue label Jun 22, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@mvaligursky mvaligursky merged commit 6c2d149 into main Jun 22, 2026
10 checks passed
@mvaligursky mvaligursky deleted the mv-gsplat-shadow-cull-opt branch June 22, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: graphics Graphics related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants