Skip to content

Use texImage2D for gsplat splat-order uploads#8656

Merged
slimbuck merged 2 commits into
playcanvas:mainfrom
slimbuck:webglsort-dev
Apr 27, 2026
Merged

Use texImage2D for gsplat splat-order uploads#8656
slimbuck merged 2 commits into
playcanvas:mainfrom
slimbuck:webglsort-dev

Conversation

@slimbuck
Copy link
Copy Markdown
Member

Summary

On WebGL, the gsplat CPU-sort path uploads a per-frame Uint32Array of sorted
splat indices into an R32UI texture via UploadStream.uploadPBO
gl.bufferSubData (PBO orphan) → gl.texSubImage2D. For multi-MB integer
textures, this stalls the main thread on Chrome's renderer→GPU IPC.

A ?cpu-sort (WebGPU CPU sort, same JS sorter) vs ?webgl (WebGL2 CPU sort)
comparison on the same splat scene:

WebGL2 WebGPU CPU-sort
FireAnimationFrame p90 74 ms 2.2 ms
FireAnimationFrame max 93 ms 2.4 ms
Top hotspot bufferSubData (~25% of CPU) uploadStaging (negligible)

Switching WebglUploadStream.uploadDirect to call gl.texImage2D directly
(full-buffer, fresh allocation each frame) takes a different — much cheaper —
IPC path on Chrome and eliminates the stall. WebGPU is unchanged.

Changes

  • WebglUploadStream.uploadDirect rewritten to call gl.texImage2D directly,
    bypassing Texture.upload() (which uses texSubImage2D after the first
    frame). Wraps the source TypedArray as Uint8Array when the texture's
    pixel type is UNSIGNED_BYTE.
  • GSplatWorkBuffer (unified) and GSplatSorter (legacy) construct their
    UploadStream with useSingleBuffer = !device.isWebGPU, so WebGL routes
    through the new uploadDirect. WebGPU continues using the staging path.

Test plan

  • WebGL2 gsplat scene (unified + legacy) renders correctly
  • WebGPU gsplat scene unchanged (no visual or perf regression)
  • Profile confirms main-thread stall is eliminated on WebGL
  • Smoke-test on Windows / Linux WebGL2 to confirm no platform regresses

@slimbuck slimbuck requested a review from Copilot April 27, 2026 11:50
@slimbuck slimbuck self-assigned this Apr 27, 2026
@slimbuck slimbuck added the area: graphics Graphics related issue label Apr 27, 2026
Copy link
Copy Markdown
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

Improves WebGL gsplat CPU-sort performance by changing how the per-frame splat-order index buffer is uploaded, avoiding a costly Chrome renderer→GPU IPC path associated with large integer texSubImage2D updates.

Changes:

  • Route WebGL gsplat splat-order uploads through UploadStream single-buffer mode to use uploadDirect.
  • Rework WebglUploadStream.uploadDirect to perform full uploads via gl.texImage2D (fresh allocation each call), bypassing the engine Texture.upload() path.
  • Keep WebGPU behavior unchanged by continuing to use the staging-buffer path.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/scene/gsplat/gsplat-sorter.js Switch legacy gsplat sorter uploads to single-buffer mode on WebGL so it uses the new texImage2D direct upload path.
src/scene/gsplat-unified/gsplat-work-buffer.js Switch unified gsplat work buffer per-frame order uploads to single-buffer mode on WebGL; keep WebGPU on staging.
src/platform/graphics/webgl/webgl-upload-stream.js Implement direct texture uploads using gl.texImage2D (full upload) to avoid Chrome stalls from texSubImage2D for large integer uploads.

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

@slimbuck slimbuck requested a review from a team April 27, 2026 12:32
@slimbuck slimbuck marked this pull request as ready for review April 27, 2026 12:32
Comment thread src/platform/graphics/webgl/webgl-upload-stream.js Outdated
@slimbuck slimbuck merged commit c3cb41f into playcanvas:main Apr 27, 2026
6 of 8 checks passed
@slimbuck slimbuck deleted the webglsort-dev branch April 27, 2026 13:15
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.

3 participants