Skip to content

WebGLRenderer: Allow InstancedMesh provide a unique ID for WebGLBindingStates.#32556

Merged
Mugen87 merged 3 commits into
mrdoob:devfrom
OndrejSpanel:instanced-binding-state
Dec 16, 2025
Merged

WebGLRenderer: Allow InstancedMesh provide a unique ID for WebGLBindingStates.#32556
Mugen87 merged 3 commits into
mrdoob:devfrom
OndrejSpanel:instanced-binding-state

Conversation

@OndrejSpanel

@OndrejSpanel OndrejSpanel commented Dec 15, 2025

Copy link
Copy Markdown
Contributor

Fixed #32552.

Description

Allow meshes to provide a specific ID for WebGLBindingState cache, and implement this for InstancedMesh.

This makes sure two different InstancedMesh which share the same geometry get a different binding state, caching VAO for them, including their custom attributes like instanceMatrix or instanceColor.

@github-actions

github-actions Bot commented Dec 15, 2025

Copy link
Copy Markdown

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 355.17
84.44
355.64
84.53
+467 B
+90 B
WebGPU 618.32
171.7
618.32
171.7
+0 B
+0 B
WebGPU Nodes 616.92
171.45
616.92
171.45
+0 B
+0 B

🌳 Bundle size after tree-shaking

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

Before After Diff
WebGL 487.34
119.31
487.81
119.41
+467 B
+96 B
WebGPU 688.95
187.13
688.95
187.13
+0 B
+0 B
WebGPU Nodes 638.79
174.32
638.79
174.32
+0 B
+0 B

@OndrejSpanel OndrejSpanel force-pushed the instanced-binding-state branch 3 times, most recently from 8958a54 to 0829483 Compare December 15, 2025 00:39
@OndrejSpanel OndrejSpanel force-pushed the instanced-binding-state branch from 0829483 to b6e1d52 Compare December 15, 2025 00:50
@OndrejSpanel OndrejSpanel marked this pull request as ready for review December 15, 2025 00:51
Comment thread src/renderers/webgl/WebGLBindingStates.js Outdated
@OndrejSpanel OndrejSpanel requested a review from Mugen87 December 15, 2025 10:14
Comment thread src/renderers/webgl/WebGLBindingStates.js Outdated
@Mugen87

Mugen87 commented Dec 15, 2025

Copy link
Copy Markdown
Collaborator

For other reviewers: The effective changes of this PR are quite compact. It's easier to see by removing changes to the formatting from the diff: https://github.com/mrdoob/three.js/pull/32556/files?w=1

@Mugen87 Mugen87 added this to the r183 milestone Dec 15, 2025
@OndrejSpanel OndrejSpanel force-pushed the instanced-binding-state branch from 1fc3313 to 7a8ea1b Compare December 15, 2025 10:19
@OndrejSpanel

OndrejSpanel commented Dec 15, 2025

Copy link
Copy Markdown
Contributor Author

It's easier to see by removing changes to the formatting from the diff

I could try removing them, if I knew how.

... oh wait, the changes are mostly caused by changed nesting level. No way to remove that, I guess.

@OndrejSpanel OndrejSpanel requested a review from Mugen87 December 15, 2025 10:22
@OndrejSpanel OndrejSpanel marked this pull request as draft December 15, 2025 10:46
@OndrejSpanel

Copy link
Copy Markdown
Contributor Author

I think there is one more thing to be checked / considered. When disposing InstancedMesh, corresponding bingings states need to be removed as well. Marking as draft before this is clarified, as not handling this properly could cause resource leaks.

@OndrejSpanel OndrejSpanel force-pushed the instanced-binding-state branch from 7b99bc5 to 04c19ee Compare December 15, 2025 11:03
Comment thread src/renderers/webgl/WebGLBindingStates.js Fixed
@OndrejSpanel OndrejSpanel force-pushed the instanced-binding-state branch 7 times, most recently from bf51f43 to ce0fb9a Compare December 15, 2025 12:42
@OndrejSpanel

OndrejSpanel commented Dec 15, 2025

Copy link
Copy Markdown
Contributor Author

As I am testing this in the game, I realized I need a slightly different id. I have different InstancedMesh instances which share the same instanceMatrix / instanceColor. This is done because I create a copy of the scene for shadow map rendering and to render env. reflection map, and the copy is as shallow as possible (meshes sharing geometries and attributes with the main scene).

Instead of checking for InstancedMesh, I need to check for instanceMatrix BufferAtrribute.id (and perhaps even instanceColor, although in my case those two are always paired and checking one of them is enough).

Without this I am unable to implement the proper cleanup.

I think the nicest way how to get this working would be to go back to the original idea of using getBindingStateId and implementing it as getBindingStateId = this.instanceMatrix.id, but if you prefer, I can still use the isInstancedMesh test and access the property (which I have committed now).

@OndrejSpanel

Copy link
Copy Markdown
Contributor Author

This is done because I create a copy of the scene for shadow map rendering and to render env. reflection map, and the copy is as shallow as possible (meshes sharing geometries and attributes with the main scene).

Turns out this is not true. Shadow and env. scenes have each their own instancer and create different instance chains. Original design should be fine, at least for my use case.

@Mugen87 However if you prefer the new version, I am fine with that as well, both should work equally well for me.

That said, I experience some resource leaks with current implementation in my game and I will not mark this as Ready for review until I solve it.

@OndrejSpanel OndrejSpanel force-pushed the instanced-binding-state branch from 5c1c2f6 to ce0fb9a Compare December 15, 2025 16:23
@OndrejSpanel

Copy link
Copy Markdown
Contributor Author

That said, I experience some resource leaks with current implementation in my game and I will not mark this as Ready for review until I solve it.

The issue was on the application side, shadow scene was missing dispose of instanced meshes.

I have different InstancedMesh instances which share the same instanceMatrix / instanceColor

If anyone was tempted to do this, I would warn against it. It is hard to get it right, as on any mesh disposal its atributes are destroyed (gl.deleteBuffer), shared or not, making cached binding states of any other meshes sharing the same attribute invalid.

@OndrejSpanel OndrejSpanel force-pushed the instanced-binding-state branch from ce0fb9a to ff67342 Compare December 15, 2025 16:29
@OndrejSpanel OndrejSpanel marked this pull request as ready for review December 15, 2025 17:12
@Mugen87 Mugen87 merged commit decc02e into mrdoob:dev Dec 16, 2025
10 checks passed
@Mugen87 Mugen87 changed the title Allow InstancedMesh provide a unique ID for WebGLBindingStates WebGLRenderer: Allow InstancedMesh provide a unique ID for WebGLBindingStates. Dec 16, 2025
@Mugen87

Mugen87 commented Dec 16, 2025

Copy link
Copy Markdown
Collaborator

Tested the disposal with webgl_instancing_dynamic and the result looks as expected 👍 .

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.

VAO not cached when two different InstancedMesh use the same InstancedBufferGeometry

3 participants