Skip to content

GSplat: GPU-driven sorting and frustum culling pipeline on WebGPU#8453

Merged
mvaligursky merged 4 commits intomainfrom
gsplat-unified-culling
Feb 13, 2026
Merged

GSplat: GPU-driven sorting and frustum culling pipeline on WebGPU#8453
mvaligursky merged 4 commits intomainfrom
gsplat-unified-culling

Conversation

@mvaligursky
Copy link
Contributor

@mvaligursky mvaligursky commented Feb 12, 2026

GSplat: GPU-driven sorting and frustum culling pipeline

Summary

  • Add GPU frustum culling using a render-pass-based node visibility test. Octree bounding spheres are tested against camera frustum planes and results are written to a bit-packed visibility texture.
  • Add GPU stream compaction (flag, prefix-sum, scatter) that filters visible splats into a dense buffer, enabling indirect draw with only visible splats rendered and sorted.
  • Support both pre-sort (GPU path: compact then sort) and post-sort (CPU path: sort then compact) compaction modes, with automatic switching between them.
  • Standardize all single-entry-point WGSL compute shader entry points to main (engine default), removing explicit computeEntryPoint settings.

Public API Changes

  • GSplatParams.culling: boolean - Enable GPU frustum culling (WebGPU only)

Updated Examples

  • lod-streaming - Added GPU Sorting and Culling toggles (WebGPU only)
  • radix-sort-indirect-compute - a hidden example for indirect radix sort testing
  • Hide GPU Sorting and Culling controls on WebGL in the lod-streaming example since they are WebGPU-only features.

Other changes

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a GPU-driven GSplat visibility + sorting pipeline (WebGPU-focused) by introducing frustum culling, stream compaction, and indirect dispatch/draw, while also standardizing WGSL compute entry points to main and centralizing some sizing utilities.

Changes:

  • Add GPU frustum culling for octree/node bounds and bit-packed visibility output, integrated into the unified GSplat work-buffer pipeline.
  • Add GPU stream compaction (flag → prefix-sum → scatter) to produce dense visible splat ID buffers and drive indirect draw/dispatch.
  • Extend radix sort and sort-key generation to support indirect sort counts written by the GPU, plus shared sizing helpers (TextureUtils.calcTextureSize, Compute.calcDispatchSize).

Reviewed changes

Copilot reviewed 35 out of 38 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/scene/shader-lib/wgsl/chunks/radix-sort/compute-radix-sort-reorder.js Switch entry point to main; support GPU-written element count for indirect mode.
src/scene/shader-lib/wgsl/chunks/radix-sort/compute-radix-sort-4bit.js Switch entry point to main; read element count from storage buffer when indirect.
src/scene/shader-lib/wgsl/chunks/gsplat/vert/gsplatSource.js Add indirect-draw path with compacted IDs + single/double indirection options.
src/scene/shader-lib/wgsl/chunks/gsplat/frag/gsplatNodeCulling.js New WGSL fragment shader for packed frustum-culling visibility output.
src/scene/shader-lib/wgsl/chunks/gsplat/frag/gsplatCopyToWorkbuffer.js Output per-splat node indices to a work-buffer stream to enable GPU culling.
src/scene/shader-lib/wgsl/chunks/gsplat/compute-gsplat-write-indirect-args.js New compute shader writing indirect draw + dispatch args from prefix-sum count.
src/scene/shader-lib/wgsl/chunks/gsplat/compute-gsplat-sort-key.js Indirect-dispatch compatible sort key generation; supports compacted splat IDs.
src/scene/shader-lib/wgsl/chunks/gsplat/compute-gsplat-compact-scatter.js New scatter pass for stream compaction (dense visible splat ID output).
src/scene/shader-lib/wgsl/chunks/gsplat/compute-gsplat-compact-flag.js New flag pass for stream compaction using node visibility texture.
src/scene/shader-lib/glsl/chunks/gsplat/frag/gsplatNodeCulling.js New GLSL fragment shader equivalent for packed node visibility output.
src/scene/shader-lib/glsl/chunks/gsplat/frag/gsplatCopyToWorkbuffer.js GLSL work-buffer copy shader updated to write node indices.
src/scene/materials/material.js Minor formatting fix in meshInstance iteration loops.
src/scene/lighting/world-clusters.js Use centralized TextureUtils.calcTextureSize for cluster texture sizing.
src/scene/gsplat/gsplat-streams.js Use centralized TextureUtils.calcTextureSize for stream texture sizing.
src/scene/gsplat/gsplat-sog-data.js Replace legacy quad drawing with RenderPassQuad / QuadRender pipeline.
src/scene/gsplat/gsplat-resource-base.js Add HAS_NODE_MAPPING define when octree node mapping texture exists.
src/scene/gsplat/gsplat-format.js Add stream removal support for work-buffer formats (removeExtraStreams).
src/scene/gsplat-unified/gsplat-work-buffer.js Add bounds/transform textures, culling pass integration, and visibility texture management.
src/scene/gsplat-unified/gsplat-work-buffer-render-pass.js Bind per-splat bounds-base index and node-to-local-bounds lookup resources.
src/scene/gsplat-unified/gsplat-sort-key-compute.js Add indirect sort-key generation variant + indirect-specific bind group format.
src/scene/gsplat-unified/gsplat-renderer.js Add indirect draw enable/disable and compacted-order mode selection.
src/scene/gsplat-unified/gsplat-params.js Add culling toggle; allow work-buffer stream removal; make IDs togglable.
src/scene/gsplat-unified/gsplat-octree.js Generate and attach node-mapping textures for GPU bounds lookup.
src/scene/gsplat-unified/gsplat-octree-node.js Precompute per-node bounding spheres (Vec4) for GPU culling.
src/scene/gsplat-unified/gsplat-node-cull-render-pass.js New render pass wrapper for node culling shader execution.
src/scene/gsplat-unified/gsplat-manager.js Orchestrate culling + compaction + indirect sort/draw (GPU + CPU hybrid modes).
src/scene/gsplat-unified/gsplat-info.js Add node-to-local-bounds texture + bounds sphere writing support per GSplatInfo.
src/scene/gsplat-unified/gsplat-compaction.js New GPU compaction manager (flag/prefix-sum/scatter + indirect args writer).
src/scene/graphics/compute-radix-sort.js Add indirect-sort mode (GPU-written count + indirect dispatch support).
src/platform/graphics/texture-utils.js Add calcTextureSize helper with optional width-multiple rounding.
src/platform/graphics/compute.js Add Compute.calcDispatchSize helper for near-square 2D dispatch sizing.
examples/thumbnails/test_radix-sort-indirect-compute_small.webp Thumbnail for new hidden indirect radix sort example.
examples/thumbnails/test_radix-sort-indirect-compute_large.webp Thumbnail for new hidden indirect radix sort example.
examples/src/examples/test/radix-sort-indirect-compute.example.mjs New hidden example validating indirect radix sort with varying visible counts.
examples/src/examples/test/radix-sort-indirect-compute.controls.mjs Controls for the indirect radix sort test example.
examples/src/examples/gaussian-splatting/world.example.mjs Enable GPU sorting + culling on non-mobile devices.
examples/src/examples/gaussian-splatting/lod-streaming.example.mjs Add GPU Sorting/Culling toggles gated to WebGPU and wire them to scene params.
examples/src/examples/gaussian-splatting/lod-streaming.controls.mjs Hide GPU Sorting/Culling controls on non-WebGPU devices.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mvaligursky mvaligursky merged commit 0cb1423 into main Feb 13, 2026
8 checks passed
@mvaligursky mvaligursky deleted the gsplat-unified-culling branch February 13, 2026 10:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: graphics Graphics related issue enhancement Request for a new feature performance Relating to load times or frame rate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant