Use texImage2D for gsplat splat-order uploads#8656
Merged
Conversation
Contributor
There was a problem hiding this comment.
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
UploadStreamsingle-buffer mode to useuploadDirect. - Rework
WebglUploadStream.uploadDirectto perform full uploads viagl.texImage2D(fresh allocation each call), bypassing the engineTexture.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.
mvaligursky
reviewed
Apr 27, 2026
mvaligursky
approved these changes
Apr 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
On WebGL, the gsplat CPU-sort path uploads a per-frame
Uint32Arrayof sortedsplat indices into an
R32UItexture viaUploadStream.uploadPBO→gl.bufferSubData(PBO orphan) →gl.texSubImage2D. For multi-MB integertextures, 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:
bufferSubData(~25% of CPU)uploadStaging(negligible)Switching
WebglUploadStream.uploadDirectto callgl.texImage2Ddirectly(full-buffer, fresh allocation each frame) takes a different — much cheaper —
IPC path on Chrome and eliminates the stall. WebGPU is unchanged.
Changes
WebglUploadStream.uploadDirectrewritten to callgl.texImage2Ddirectly,bypassing
Texture.upload()(which usestexSubImage2Dafter the firstframe). Wraps the source
TypedArrayasUint8Arraywhen the texture'spixel type is
UNSIGNED_BYTE.GSplatWorkBuffer(unified) andGSplatSorter(legacy) construct theirUploadStreamwithuseSingleBuffer = !device.isWebGPU, so WebGL routesthrough the new
uploadDirect. WebGPU continues using the staging path.Test plan