Skip to content

Conversation

@Berthur
Copy link
Contributor

@Berthur Berthur commented Aug 26, 2025

There is an inconsistency between the WebGL and WebGPU implementations regarding the Texture.onUpdate() callback.

A common(?) use case for this callback is to dispose of the image from RAM once it has been uploaded to the GPU. Currently, in WebGL, one can do:

const texture = new Texture();
// ... set texture properties, source image etc.
texture.onUpdate = myDisposeFunction;

where myDisposeFunction does something like delete texture.source.data; or equivalent, thus allowing the image resource to be garbage collected.

With this, the texture can then be added to the scene at leisure, and one can be confident that whenever it get uploaded to the GPU, the dispose function will be called. Since the texture is already on the GPU, one might no longer need it in RAM, and this memory management is necessary for some projects. In WebGL mode, this code currently works fine.

However, in WebGPU mode, this same code causes an error, because Three.js will try to create mipmaps AFTER texture.onUpdate() has been called. The mipmaps will try to access the deleted image source, throwing an error. The mipmaps might also actually be needed for the texture, so they should probably be generated first.

Indeed, when comparing WebGLTextures.js:uploadTexture() with Textures.js:updateTexture(), we can see that in WebGL, mipmap generation happens before the onUpdate() callback is called. In WebGPU, it's done after.

In this pull request, I try to fix this issue, with the motivation of making it conform with how it works in WebGL. This fix definitely solves the issue at least for my project. I welcome feedback or discussion from those more familiar with this part of the code, as I am a new contributor.

@github-actions
Copy link

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 338.91
79.11
338.91
79.11
+0 B
+0 B
WebGPU 578.16
159.25
578.16
159.25
+0 B
-2 B
WebGPU Nodes 576.76
159.01
576.76
159.01
+0 B
-2 B

🌳 Bundle size after tree-shaking

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

Before After Diff
WebGL 470.78
113.9
470.78
113.9
+0 B
+0 B
WebGPU 648.69
175.28
648.69
175.28
+0 B
-1 B
WebGPU Nodes 602.79
164.41
602.79
164.4
+0 B
-1 B


if ( options.needsMipmaps && texture.mipmaps.length === 0 ) backend.generateMipmaps( texture );

if ( texture.onUpdate ) texture.onUpdate( texture );
Copy link
Collaborator

Choose a reason for hiding this comment

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

This code actually fixes the missing onUpdate() in the WebGL backend 👍 .

@Mugen87 Mugen87 added this to the r180 milestone Aug 26, 2025
@Mugen87 Mugen87 merged commit bcbf031 into mrdoob:dev Aug 26, 2025
9 checks passed
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