Skip to content

Conversation

@holtsetio
Copy link
Contributor

@holtsetio holtsetio commented Nov 26, 2025

Fixed #32375.

Description

This change fixes the memory length calculation for the StructTypeNode so three.js allocates enough memory for custom structs.
I have also renamed the getByteBoundaryFromType() function to getAlignmentFromType() and fixed the values for mat3/mat4 according to https://webgpufundamentals.org/webgpu/lessons/webgpu-memory-layout.html

@github-actions
Copy link

github-actions bot commented Nov 26, 2025

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 350.29
83.05
350.29
83.05
+0 B
+0 B
WebGPU 612.89
170.29
612.89
170.27
+1 B
-17 B
WebGPU Nodes 611.49
170.01
611.49
169.99
+1 B
-13 B

🌳 Bundle size after tree-shaking

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

Before After Diff
WebGL 482.23
117.82
482.23
117.82
+0 B
+0 B
WebGPU 683.78
186
683.78
186
+0 B
+0 B
WebGPU Nodes 633.61
173.18
633.61
173.18
+0 B
+0 B

@holtsetio
Copy link
Contributor Author

holtsetio commented Nov 26, 2025

Edit: Disregard this, adressed with the next commit!

To note here:
getLength() now returns the length that a buffer with a single object of this struct would occupy in memory.
In some edge cases (examples below), the returned length is too long for buffers with multiple objects of this struct. However, mitigating this is hard with the current code structure and allocating a few bytes too much is definitely better than allocating too little, as it was before..

Examples:

const testStruct = struct({
	a: { type: "vec2" },
	aa: { type: "vec2" },
	aaa: { type: "vec2" },
});

getLength() for this struct now returns 8 (32 bytes), which is correct for a buffer with a single element, e.g. instancedArray(1, testStruct);
However, for instancedArray(2, testStruct); this would result in a length of 2*32=64 bytes, even though this buffer only occupies 48 bytes.

const testStruct = struct({
	a: { type: "float" },
});

getLength() for this struct now returns 4 (16 bytes), which is correct for a buffer with a single element, e.g. instancedArray(1, testStruct);
However, for instancedArray(4, testStruct); this would result in a length of 4*32=128 bytes, even though this buffer only occupies 16 bytes.

Maybe to fully address this, there would need to be a getLength() function that also takes the number of elements of this struct into account?

@holtsetio
Copy link
Contributor Author

holtsetio commented Nov 26, 2025

Ok, I added another commit that adresses above concerns. getLength() should now also return correct lengths for structs with different alignments. getLength() now doesn't necessary return multiples of 4 anymore, but multiples of the biggest alignment value within the struct. (following https://webgpufundamentals.org/webgpu/lessons/webgpu-memory-layout.html#a-struct-array-size-alignment)

@Mugen87 Mugen87 added this to the r182 milestone Nov 26, 2025
@sunag sunag changed the title Fix memory length calculations for StructTypeNode (#32375) StructTypeNode: Fix memory length calculations (#32375) Nov 26, 2025
@sunag sunag merged commit 5240f29 into mrdoob:dev Nov 26, 2025
9 of 10 checks passed
@sunag
Copy link
Collaborator

sunag commented Nov 26, 2025

I think the next step is to align UniformsGroup with these changes.

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.

The structNode does not calculate the correct size in memory with respect to WebGPU alignment requirements

3 participants