Skip to content

WebGPURenderer: Preserve material side during async compilation#34104

Open
RenaudRohlinger wants to merge 1 commit into
mrdoob:devfrom
RenaudRohlinger:fix-compile-async-material-side
Open

WebGPURenderer: Preserve material side during async compilation#34104
RenaudRohlinger wants to merge 1 commit into
mrdoob:devfrom
RenaudRohlinger:fix-compile-async-material-side

Conversation

@RenaudRohlinger

@RenaudRohlinger RenaudRohlinger commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Preserves BackSide and FrontSide when compileAsync() yields during double-pass transparent material compilation.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 365.88
86.71
365.88
86.71
+0 B
+0 B
WebGPU 685.67
189.48
685.27
189.38
-398 B
-106 B
WebGPU Nodes 683.65
189.16
683.26
189.05
-398 B
-104 B

🌳 Bundle size after tree-shaking

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

Before After Diff
WebGL 510.55
124.02
510.55
124.02
+0 B
+0 B
WebGPU 764.04
205.54
763.64
205.43
-398 B
-105 B
WebGPU Nodes 713.54
192.96
713.14
192.86
-397 B
-98 B

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown

🖼️ E2E screenshot tests

✅ All examples render correctly again (run).

@RenaudRohlinger
RenaudRohlinger marked this pull request as draft July 23, 2026 23:31
@RenaudRohlinger
RenaudRohlinger force-pushed the fix-compile-async-material-side branch 2 times, most recently from 5af4b01 to 7269b7f Compare July 24, 2026 01:09
@RenaudRohlinger
RenaudRohlinger marked this pull request as ready for review July 24, 2026 01:14
@RenaudRohlinger RenaudRohlinger added this to the r186 milestone Jul 24, 2026
@RenaudRohlinger
RenaudRohlinger requested a review from Mugen87 July 24, 2026 01:27
* @return {NodeBuilder} The configured node builder.
*/
_createNodeBuilder( renderObject, material ) {
_createNodeBuilder( renderObject, material, materialSide = material.side ) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the property be inside RenderObject? That way, perhaps we could make the function signatures cleaner. We have a backSide passId that is also used, while keeping the RenderObject unique in a similar context.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed! The side now lives on RenderObject as materialSide, they're already unique per pass thanks to the backSide passId, so the extra params are gone and the signatures are back to normal.

The root issue was compileAsync() calling _objects.get() after material.side had been restored. It now requests the render object during the traversal instead, so all the temporary save/restore is gone. The pipeline cache key and cull mode read it too, otherwise compileAsync() precompiles the wrong pipeline and the first render has to build it again anyway.

The diff removes more lines than it adds now 🙂

While working on it I also realized I wrongly implemented getForRenderDeferred a few months ago which is deadcode, I will remove that deadcode in a follow up PR.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to block the PR but I'm in general not happy how much complexity the whole async compile feature introduces into the renderer.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to discuss the bigger picture in another thread. On this PR specifically it goes in your direction: it removes the duplicated sync/async path in createObjectPipeline, −73/+56 lines.

On the feature in general I agree, which is even why I considered rethinking the whole thing in #33766. But part of it is unavoidable: in the WebGLRenderer things like cull face, blending and the render target are set at draw time, while in the WebGPURenderer they're baked into the pipeline. So precompiling needs the full render context, and that's where the complexity comes from.

@RenaudRohlinger
RenaudRohlinger force-pushed the fix-compile-async-material-side branch 2 times, most recently from a063a72 to 3c297d7 Compare July 25, 2026 02:47
@RenaudRohlinger
RenaudRohlinger force-pushed the fix-compile-async-material-side branch from 3c297d7 to e0c2048 Compare July 25, 2026 02:54
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