Remove per-resource instance vertex buffer from GSplat rendering#8513
Merged
mvaligursky merged 2 commits intomainfrom Mar 9, 2026
Merged
Remove per-resource instance vertex buffer from GSplat rendering#8513mvaligursky merged 2 commits intomainfrom
mvaligursky merged 2 commits intomainfrom
Conversation
Replace vertex_id_attrib with attributeless instancing, deriving the splat base index from gl_InstanceID / pcInstanceIndex GPU builtins. This eliminates per-resource GPU memory allocation and dynamic reallocation for instance index vertex buffers. MeshInstance.setInstancing now accepts `true` for attributeless instancing (count-only, no per-instance VB). Made-with: Cursor
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refactors GSplat rendering to remove the per-resource instance-index vertex buffer and instead derive the base splat index from the GPU instance index builtins (gl_InstanceID / pcInstanceIndex), reducing GPU allocations and reallocations as splat counts change.
Changes:
- Switched GSplat shaders (GLSL/WGSL) to compute
source.orderfrom the instance index builtin and a{GSPLAT_INSTANCE_SIZE}replacement define. - Removed per-resource instance index vertex buffer creation/ownership from
GSplatResourceBaseand removed dynamic resizing logic from the unified renderer/manager path. - Extended
MeshInstance.setInstancingto accepttruefor attributeless instancing (instance-count only).
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/scene/shader-lib/wgsl/chunks/gsplat/vert/gsplatSource.js | Uses pcInstanceIndex + {GSPLAT_INSTANCE_SIZE} to derive splat order (no vertex_id_attrib). |
| src/scene/shader-lib/glsl/chunks/gsplat/vert/gsplatSource.js | Uses gl_InstanceID + {GSPLAT_INSTANCE_SIZE} to derive splat order (no vertex_id_attrib). |
| src/scene/mesh-instance.js | Adds attributeless instancing mode via setInstancing(true, ...). |
| src/scene/gsplat/gsplat-resource-base.js | Removes per-resource instance index VB allocation and lifetime management. |
| src/scene/gsplat/gsplat-material.js | Drops vertex_id_attrib attribute binding; injects {GSPLAT_INSTANCE_SIZE} define. |
| src/scene/gsplat/gsplat-instance.js | Switches legacy path to attributeless instancing; injects {GSPLAT_INSTANCE_SIZE} define during configuration. |
| src/scene/gsplat-unified/gsplat-renderer.js | Switches unified path to attributeless instancing; removes setMaxNumSplats; injects/protects {GSPLAT_INSTANCE_SIZE} define. |
| src/scene/gsplat-unified/gsplat-manager.js | Removes calls to the deleted renderer.setMaxNumSplats. |
Comments suppressed due to low confidence (1)
src/scene/gsplat-unified/gsplat-renderer.js:426
- In indirect-draw mode (when draw commands are provided),
instancingCountis GPU-driven andnumInstancesis ignored byWebgpuGraphicsDevice.draw(), but the forward/shadow renderers still skip any draw call whereinstancingData.count <= 0. With attributeless instancing,setInstancing(true, ...)initializesInstancingDatawithcount = 0andcreateMeshInstance()leavesinstancingCount = 0, so indirect GSplat rendering will be skipped entirely. Consider settingmeshInstance.instancingCountto a non-zero sentinel (for example 1) when indirect draw is enabled (e.g. insetIndirectDraw/updateIndirect) or initializing attributeless instancing with a default count of 1 for indirect-driven paths.
const mesh = GSplatResourceBase.createMesh(this.device);
const meshInstance = new MeshInstance(mesh, this._material);
meshInstance.node = this.node;
meshInstance.setInstancing(true, true);
// only start rendering the splat after we've received the splat order data
meshInstance.instancingCount = 0;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
Replaces the per-resource instance vertex buffer (
vertex_id_attrib) in GSplat rendering with attributeless instancing, deriving the splat base index fromgl_InstanceID/pcInstanceIndexGPU builtins instead.Changes:
createInstanceIndicesand all per-resource instance VB allocation/reallocation fromGSplatResourceBasesetMaxNumSplatsdynamic reallocation fromGSplatRenderergsplatSourceshaders to computesource.orderfrom the instance index builtin multiplied by aGSPLAT_INSTANCE_SIZEdefineGSplatRenderer) and legacy (GSplatInstance) rendering pathsAPI Changes:
MeshInstance.setInstancingnow acceptstrueas thevertexBufferparameter to enable attributeless instancing (count-only, no per-instance vertex buffer). The caller must setinstancingCountmanually.Performance: