Skip to content

feat: radix sort facade, indirect mode, and WebGPU subgroup sizing#8647

Merged
mvaligursky merged 3 commits into
mainfrom
mv-radix-sort-facade
Apr 24, 2026
Merged

feat: radix sort facade, indirect mode, and WebGPU subgroup sizing#8647
mvaligursky merged 3 commits into
mainfrom
mv-radix-sort-facade

Conversation

@mvaligursky

Copy link
Copy Markdown
Contributor

Refactors WebGPU compute radix sort behind a single ComputeRadixSort entry point, adds optional indirect-dispatch integration for GSplat, and fixes subgroup size fields read from the adapter.

Changes:

  • Move multipass and OneSweep implementations under src/scene/graphics/radix-sort/ with a shared ComputeRadixSortBase and public ComputeRadixSort facade; backend selection uses RADIX_SORT_AUTO / RADIX_SORT_PORTABLE / RADIX_SORT_ONESWEEP constants.
  • Add indirect constructor option so only the needed shader variant is compiled; prepareIndirect / sortIndirect assert when used without it.
  • Add sortIndirectArgsCS WGSL chunk (writeSortIndirectArgs) and wire GSplat indirect-arg shaders to prepareIndirect() metadata.
  • OneSweep: unified artefact lifecycle, ragged-tail global histogram handling, subgroup sizing from minSubgroupSize.
  • WebGPU: read minSubgroupSize / maxSubgroupSize from gpuAdapter.info (subgroupMinSize / subgroupMaxSize), not limits.
  • Radix sort compute example updated to use the facade and kind option.

Examples:

  • examples/src/examples/test/radix-sort-compute.example.mjs

Refactor compute radix sort behind ComputeRadixSort with portable and
OneSweep backends, indirect dispatch metadata, WGSL sort-indirect-args
chunk, and fix subgroup min/max from adapter info.

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.

Pull request overview

This PR refactors the WebGPU compute radix sort into a unified ComputeRadixSort facade with selectable backends, adds an optional indirect-dispatch mode for GSplat integration, and updates WebGPU subgroup sizing to read from adapter info.

Changes:

  • Introduces ComputeRadixSort facade + shared ComputeRadixSortBase, moving multipass/OneSweep implementations under src/scene/graphics/radix-sort/.
  • Adds indirect-dispatch support end-to-end (new WGSL helper chunk sortIndirectArgsCS, GSplat write-args shader + interval compaction wiring, prepareIndirect() / sortIndirect() APIs).
  • Updates OneSweep shaders for indirect-mode element-count handling and ragged-tail histogram, and switches subgroup size reads to gpuAdapter.info.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/scene/shader-lib/wgsl/collections/shader-chunks-wgsl.js Registers the new WGSL helper chunk for indirect sort dispatch args.
src/scene/shader-lib/wgsl/chunks/radix-sort/onesweep-scan.js Adds indirect-mode element-count binding and derives threadBlocks from GPU count.
src/scene/shader-lib/wgsl/chunks/radix-sort/onesweep-global-hist.js Adds indirect-mode numKeys source and ragged-tail handling for non-vec4-multiple counts.
src/scene/shader-lib/wgsl/chunks/radix-sort/onesweep-binning.js Adds indirect-mode element-count binding and localizes threadBlocks usage.
src/scene/shader-lib/wgsl/chunks/gsplat/compute-gsplat-write-indirect-args.js Delegates sort dispatch-slot writes to writeSortIndirectArgs using sorter metadata.
src/scene/shader-lib/wgsl/chunks/common/comp/sort-indirect-args.js New WGSL helper to write sorter dispatch args from stable metadata.
src/scene/gsplat-unified/gsplat-manager.js Switches GSplat to ComputeRadixSort(..., { indirect: true }) and reserves variable slot counts.
src/scene/gsplat-unified/gsplat-interval-compaction.js Extends indirect-args write path to pass sorter metadata (uvec4) into the shader.
src/scene/graphics/radix-sort/compute-radix-sort.js New public facade selecting multipass vs OneSweep and exposing direct/indirect APIs.
src/scene/graphics/radix-sort/compute-radix-sort-onesweep.js Relocates/refactors OneSweep under the new base class and adds indirect-dispatch variant.
src/scene/graphics/radix-sort/compute-radix-sort-multipass.js Relocates/refactors portable multipass backend under the new base class and indirect-only mode.
src/scene/graphics/radix-sort/compute-radix-sort-base.js New shared base for buffer lifecycle + indirect metadata plumbing.
src/scene/constants.js Adds RADIX_SORT_AUTO / RADIX_SORT_PORTABLE / RADIX_SORT_ONESWEEP constants.
src/platform/graphics/webgpu/webgpu-graphics-device.js Reads minSubgroupSize/maxSubgroupSize from gpuAdapter.info fields.
src/index.js Re-exports ComputeRadixSort from the new path and removes the OneSweep export.
examples/src/examples/test/radix-sort-compute.example.mjs Updates the example to use the new facade + kind option.
Comments suppressed due to low confidence (1)

src/scene/graphics/radix-sort/compute-radix-sort-onesweep.js:231

  • elementCountBinding is a single BindStorageBufferFormat instance that gets pushed into 3 different BindGroupFormats. BindGroupFormat mutates format.slot during construction, so reusing the same instance will leave earlier bind group formats with the wrong slot index for b_sortElementCount (likely causing a bind group / pipeline layout mismatch at runtime). Create a fresh BindStorageBufferFormat('b_sortElementCount', ...) per bind group instead of sharing one object.

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

Comment thread src/platform/graphics/webgpu/webgpu-graphics-device.js
@mvaligursky mvaligursky merged commit 5d2c168 into main Apr 24, 2026
8 checks passed
@mvaligursky mvaligursky deleted the mv-radix-sort-facade branch April 24, 2026 14:31
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