Skip to content

Conversation

@Mugen87
Copy link
Collaborator

@Mugen87 Mugen87 commented Sep 9, 2025

Related issue: #31747

Description

@Makio64's live example from #31747 (comment) was really helpful to fix an edge case in WebGPURenderer's texture management.

When you start loading a texture and call dispose() during the loading process, the backends delete the GPU texture objects of the default textures. That should not happen since these objects are cached and shared across other compatible textures. The PR fixes this issue my performing the dispose() as usual except for the deletion of the GPU texture object. That requires to delegate the isDefaultTexture flag down to the texture utils components for both backends.

@Mugen87
Copy link
Collaborator Author

Mugen87 commented Sep 9, 2025

@Makio64 Your live example was really helpful to discover this bug! It does not yet fix the root cause of #31747 though. That is a different issue I'll try to fix with a different PR (bindings and textures getting out of sync).

@github-actions
Copy link

github-actions bot commented Sep 9, 2025

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 338.24
79.14
338.24
79.14
+0 B
+0 B
WebGPU 579.91
160.21
579.98
160.23
+68 B
+13 B
WebGPU Nodes 578.52
159.97
578.59
159.99
+68 B
+14 B

🌳 Bundle size after tree-shaking

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

Before After Diff
WebGL 469.88
113.85
469.88
113.85
+0 B
+0 B
WebGPU 649.62
175.88
649.69
175.9
+68 B
+14 B
WebGPU Nodes 603.73
165.04
603.8
165.05
+68 B
+16 B

@Makio64
Copy link
Contributor

Makio64 commented Sep 9, 2025

@Mugen87 thank you, happy it helps!


this.backend.destroySampler( texture );
this.backend.destroyTexture( texture );
this.backend.destroyTexture( texture, isDefaultTexture );
Copy link
Collaborator

Choose a reason for hiding this comment

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

Couldn't we put the condition here instead of taking it to the backend?

if ( isDefaultTexture === false ) {

		this.backend.destroyTexture( texture );

}

Copy link
Collaborator Author

@Mugen87 Mugen87 Sep 9, 2025

Choose a reason for hiding this comment

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

In this case, the backend does not delete the texture data which is done inside the destroyTexture() methods. Meaning:

backend.delete( texture );

That was indeed the main reason why I have introduced a new parameter.

We could move backend.delete( texture ); into Textures._destroyTexture() however WebGPUTextureUtils.destroyTexture() is used at other places as well so we would have to copy this line multiple times which seems error prone.

Copy link
Collaborator

Choose a reason for hiding this comment

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

You tried to add/use a flag like isDefault through the backend method backend.createDefaultTexture() similar to the one used in WebGLBackend?

backend.set( texture, {
textureGPU,
glTextureType,
isDefault: true
} );

Copy link
Collaborator Author

@Mugen87 Mugen87 Sep 10, 2025

Choose a reason for hiding this comment

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

I've added the same flag in WebGPUTextureUtils for testing but unfortunately this introduces a regression that textures are not destroyed anymore at all since the isDefault flag persists with the texture data. It would be necessary to remove this flag or set it to false when the real texture data are available.

This kind of management already exists in Textures and it seems error prone to duplicate it in both backends.

For consistency reasons, I have removed the isDefault flag from WebGLTextureUtils since it was not evaluated it the code base anyway.

@sunag sunag merged commit bface43 into mrdoob:dev Sep 10, 2025
9 checks passed
@Mugen87 Mugen87 added this to the r181 milestone Sep 10, 2025
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