Skip to content

Conversation

@RenaudRohlinger
Copy link
Collaborator

@RenaudRohlinger RenaudRohlinger commented Nov 29, 2025

Description
Edit: Add array support to indirectOffset which allow to easily batch multiple indirect draw with multiple indirectOffset, allowing to do all sort of super fast batch with WebGPU (notably a real BatchedMesh support command-wise in the future).

Here’s a demonstration of the potential: an indirect port of batched mesh, composed of thousands of geometries, GPU-culled via a compute shader and rendered in 0.5 ms, rendered via a single bundled command of thousands of indirect draw with each different data and indirect offset:
Screenshot 2025-11-29 at 18 12 14

To achieve this with this PR, all that’s required is increasing the size of the indirect buffer:

const indirectAttribute = new THREE.IndirectStorageBufferAttribute( new Uint32Array( 5 * 1000 ), 5 );
geometry.setIndirect(indirectAttribute)

/cc @holtsetio

This contribution is funded by Utsubo & Three.js Blocks

@RenaudRohlinger RenaudRohlinger added this to the r182 milestone Nov 29, 2025
@github-actions
Copy link

github-actions bot commented Nov 29, 2025

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 350.26
83.06
350.26
83.06
+0 B
+0 B
WebGPU 613.73
170.42
613.84
170.44
+110 B
+26 B
WebGPU Nodes 612.33
170.15
612.44
170.17
+110 B
+24 B

🌳 Bundle size after tree-shaking

Minimal build including a renderer, camera, empty scene, and dependencies.

Before After Diff
WebGL 482.25
117.84
482.25
117.84
+0 B
+0 B
WebGPU 684.87
186.19
684.98
186.22
+110 B
+23 B
WebGPU Nodes 634.71
173.38
634.82
173.41
+110 B
+22 B

@holtsetio
Copy link
Contributor

holtsetio commented Nov 29, 2025

The use case in our current project is a particle system with lots of different types of particles which are all rendered with different types of geometries & materials, so using a batched mesh wouldn't work. I had this use case before in other non-threejs projects so I dont think it's that uncommon.
Your new commit allows to draw lots of different geometries (through batchedMesh) with the same material, but not much else.
Maybe to accomodate all use cases geometry should have an array of indirectBuffer/offset pairs?

@holtsetio
Copy link
Contributor

On another note, it feels wrong to set this on the BufferGeometry level, shouldn't it rather be part of the Mesh class?

@RenaudRohlinger
Copy link
Collaborator Author

Maybe to accomodate all use cases geometry should have an array of indirectBuffer/offset pairs?

Oh I see, that was the final solution I was thinking about but thought it was overkill, I guess it's not if we want to accomodate all use cases indeed!

@RenaudRohlinger
Copy link
Collaborator Author

RenaudRohlinger commented Nov 29, 2025

So an API such as adding Array support:

Multiple:

const indirectAttribute = new THREE.IndirectStorageBufferAttribute( new Uint32Array( 5 * 100 ), 5 );
const indirectOffset = new Array( 5 * 100 )
geometry.setIndirect(indirectAttribute, indirectOffset) // <-- indirectOffset being Array or number

Single:

const indirectAttribute = new THREE.IndirectStorageBufferAttribute( new Uint32Array( 5 * 5 ), 5 );
const indirectOffset = 20
geometry.setIndirect(indirectAttribute, indirectOffset) // <-- number

I will update this PR to keep your work, add Array support in addition to single number indirectOffset, and consume that indirectOffset instead of hardcoding the indirectOffset in the Renderer

@RenaudRohlinger
Copy link
Collaborator Author

Should be good, is this version ok with you @holtsetio?

@holtsetio
Copy link
Contributor

Looks good to me!

@Mugen87 Mugen87 merged commit 8687381 into mrdoob:dev Nov 29, 2025
10 checks passed
@Mugen87 Mugen87 changed the title WebGPUBackend: Add support indirectOffset based on IndirectStorageBufferAttribute count BufferGeometry: Let indirectOffset accept an array of offsets. Nov 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants