Skip to content

Conversation

mvaligursky
Copy link
Contributor

@mvaligursky mvaligursky commented Oct 14, 2025

Overview

Introduces a new UploadStream API for efficient, non-blocking GPU data uploads and refactors GSplat unified rendering to use storage buffers on WebGPU with optimized upload strategies for both WebGL and WebGPU.

New API: UploadStream

A platform-agnostic private API for uploading data to GPU resources (texture on WebGL / storage buffer on WebGPU) with two modes:

  • Simple mode (useSingleBuffer: true): Direct uploads for low-frequency updates. Blocking if the resource is still in use by the GPU.
  • Optimized mode (useSingleBuffer: false): Non-blocking uploads using PBOs (WebGL) or staging buffers (WebGPU)

Signature: upload(data, target, offset = 0, size = data.length)

StorageBuffer API Extensions

  • Added an optional addStorageUsage parameter to the StorageBuffer constructor (defaults to true) to support creating staging buffers
  • Also added a copy(srcOffset, dstBuffer, dstOffset, size) method that wraps copyBufferToBuffer for efficient GPU-side buffer copies, enabling the staging buffer pattern used by UploadStream.

Key Changes

WebGL Optimizations (WebglUploadStream)

  • PBO-based asynchronous texture uploads with "orphan + bufferSubData" pattern
  • Non-blocking fence polling using clientWaitSync(..., 0, 0)
  • Explicit pixel-store parameter configuration to prevent hidden CPU repacks

WebGPU Optimizations (WebgpuUploadStream)

  • Staging buffer ring for non-blocking uploads via copyBufferToBuffer
  • Direct StorageBuffer.write() for simple mode

GSplat Unified Rendering

  • Added orderBuffer (StorageBuffer) for WebGPU alongside orderTexture for WebGL
  • Integrated UploadStream in setOrderData() for non-blocking uploads

Shader Updates

  • gsplatSource.js (WGSL): Added conditional compilation via #ifdef STORAGE_ORDER
    • Storage buffer path for WebGPU: var<storage, read> splatOrder: array<u32>
    • Added splatTextureSize uniform

Profiling on Apple M4 Max

WebGPU

The impact is huge. The CPU thread is no longer blocked on the upload, and runs 60fps instead of 20 or so. We're still GPU limited, and so the frames are still skipped - but that can be addressed by GPU optimization.

before
webgpu before

now
webgpu now

WebGL

A lot lower impact, as there is no completely non-blocking way to upload, and performance depends on the driver implementation. In theory, this should deliver the same performance as WebGPU though.

before
webgl before

now
webgl now

Copy link
Contributor

@Copilot 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

Introduces a new UploadStream API for efficient, non-blocking GPU data uploads and refactors GSplat unified rendering to use storage buffers on WebGPU with optimized upload strategies for both WebGL and WebGPU.

  • Added new UploadStream API with platform-specific implementations for WebGL (PBO-based) and WebGPU (staging buffer-based) non-blocking data uploads
  • Extended StorageBuffer with optional storage usage parameter and buffer copy functionality
  • Refactored GSplat unified rendering to use storage buffers on WebGPU and texture-based approach on WebGL with conditional shader compilation

Reviewed Changes

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

Show a summary per file
File Description
src/scene/shader-lib/wgsl/chunks/gsplat/vert/gsplatSource.js Added conditional compilation for storage buffer vs texture-based splat order access in WGSL shader
src/scene/shader-lib/glsl/chunks/gsplat/vert/gsplatSource.js Updated GLSL shader to use uniform texture size parameter instead of computing from texture dimensions
src/scene/gsplat/gsplat-instance.js Refactored material order texture setup into reusable method that sets both texture and size parameters
src/scene/gsplat-unified/gsplat-work-buffer.js Added UploadStream integration and dual texture/storage buffer support based on graphics device type
src/scene/gsplat-unified/gsplat-renderer.js Updated renderer to handle both WebGL texture and WebGPU storage buffer order data with frame-based updates
src/scene/gsplat-unified/gsplat-manager.js Integrated new renderer update and frame update methods for optimized order data handling
src/platform/graphics/webgpu/webgpu-upload-stream.js Implemented WebGPU-specific UploadStream using staging buffers with recycling for non-blocking uploads
src/platform/graphics/webgpu/webgpu-graphics-device.js Added WebGPU UploadStream implementation factory method
src/platform/graphics/webgpu/webgpu-dynamic-buffer.js Fixed JSDoc type annotation formatting
src/platform/graphics/webgl/webgl-upload-stream.js Implemented WebGL-specific UploadStream using PBO orphaning pattern for optimized texture uploads
src/platform/graphics/webgl/webgl-graphics-device.js Added WebGL UploadStream implementation factory method
src/platform/graphics/upload-stream.js Created platform-agnostic UploadStream API for efficient GPU resource uploads
src/platform/graphics/storage-buffer.js Extended StorageBuffer with optional storage usage flag and buffer copy functionality
src/platform/graphics/shader-chunks/frag/shared-wgsl.js Added WEBGPU preprocessor define
src/platform/graphics/null/null-graphics-device.js Added null implementation for UploadStream factory method

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@mvaligursky mvaligursky self-assigned this Oct 15, 2025
@mvaligursky mvaligursky added enhancement Request for a new feature area: graphics Graphics related issue labels Oct 15, 2025
@mvaligursky mvaligursky requested a review from a team October 15, 2025 09:58
@slimbuck
Copy link
Member

What's the reason not to use this for the non-managed path as well?

@mvaligursky
Copy link
Contributor Author

No reason, can be done in a separate PR. I tried doing it but it was looking to be a larger change with the way sorter is handling data, so I didn't do it as part of this PR.

@slimbuck
Copy link
Member

No reason, can be done in a separate PR. I tried doing it but it was looking to be a larger change with the way sorter is handling data, so I didn't do it as part of this PR.

Ok awesome. This is such a significant improvement that we need it everywhere all at once right now :)

@mvaligursky mvaligursky merged commit 1ce725e into main Oct 15, 2025
7 checks passed
@mvaligursky mvaligursky deleted the mv-gsplat-storage-buffer branch October 15, 2025 11:42
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants