Skip to content

TSL: Support layout functions with uniforms shared across materials - #33666

Open
shotamatsuda wants to merge 5 commits into
mrdoob:devfrom
shotamatsuda:feat/layout-fn-shared
Open

TSL: Support layout functions with uniforms shared across materials#33666
shotamatsuda wants to merge 5 commits into
mrdoob:devfrom
shotamatsuda:feat/layout-fn-shared

Conversation

@shotamatsuda

@shotamatsuda shotamatsuda commented May 28, 2026

Copy link
Copy Markdown
Contributor

Related issue: #31325

Description

This PR adds support for using layout functions with uniforms shared across different materials, by caching them per material when they contain uniform nodes.

Layout functions are built and cached per backend for the first material, and associated uniforms become invalid for other materials. This causes the following situation to fail.

const x = uniform(1)

const f = Fn(() => x).setLayout({ type: 'float', name: 'f', inputs: [] })

const material1 = new NodeMaterial()
material1.fragmentNode = f()

const material2 = new NodeMaterial()
material2.fragmentNode = f()

With this PR, the example above works. Nested layout functions that includes uniforms are also supported.

const x = uniform(1)

const f = Fn(() => x).setLayout({ type: 'float', name: 'f', inputs: [] })
const g = Fn(() => f()).setLayout({ type: 'float', name: 'g', inputs: [] })
const h = Fn(() => f()).setLayout({ type: 'float', name: 'h', inputs: [] })

const material1 = new NodeMaterial()
material1.fragmentNode = h().add(g())

const material2 = new NodeMaterial()
material2.fragmentNode = f().add(g())

@github-actions

github-actions Bot commented May 28, 2026

Copy link
Copy Markdown

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 365.43
86.79
365.43
86.79
+0 B
+0 B
WebGPU 661.82
182.63
662.29
182.74
+472 B
+105 B
WebGPU Nodes 659.86
182.33
660.34
182.44
+472 B
+103 B

🌳 Bundle size after tree-shaking

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

Before After Diff
WebGL 498.49
121.58
498.49
121.58
+0 B
+0 B
WebGPU 733.06
197.45
733.53
197.56
+472 B
+104 B
WebGPU Nodes 682.28
184.86
682.75
184.96
+472 B
+99 B

@Mugen87

Mugen87 commented May 28, 2026

Copy link
Copy Markdown
Collaborator

TBH, I find it not ideal that an additional flag would have to be used to avoid this issue. Can't the layout functions be cached per node builder by default?

@shotamatsuda

Copy link
Copy Markdown
Contributor Author

I find it not ideal that an additional flag would have to be used to avoid this issue.

I agree, but it will have broader performance ramifications, I suppose, when layout functions are cached per material by default, since all the complex functions like those in mx_noise.js must be rebuilt for each material.

@shotamatsuda

Copy link
Copy Markdown
Contributor Author

I roughly measured the performance difference in the first frame involving node building in webgpu_materialx_noise:

Cache per backend: approx. 100-105ms
Cache per material: approx. 120-125ms

@shotamatsuda

shotamatsuda commented May 28, 2026

Copy link
Copy Markdown
Contributor Author

Although it needs further testing, by detecting whether a layout function has uniforms, it appears that the user-set "shared" flag will be unnecessary.

@shotamatsuda shotamatsuda changed the title TSL: Add "shared" option in setLayout TSL: Support layout functions with uniforms shared across materials May 28, 2026
@shotamatsuda
shotamatsuda marked this pull request as ready for review May 28, 2026 18:17
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.

2 participants