Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGPURenderer: Fix texture view caching and dispose event stacking #30647

Merged
merged 4 commits into from
Mar 5, 2025

Conversation

RenaudRohlinger
Copy link
Collaborator

Related issue: #30560

Description

In the WebGPU backend before r172, there was a bug where renderTarget.activeMipmapLevel was incorrectly used instead of renderContext.activeMipmapLevel. This was partially fixed in PR #30155:
https://github.com/mrdoob/three.js/pull/30155/files#diff-dab3c57cef925d356099192da6cb6710336ac50052d2f6774897e1864d8c46a9L305-R331

However, my commit missed updating the cache invalidation condition:

  • Current: renderTargetData.activeMipmapLevel !== renderTarget.activeMipmapLevel
  • Should be: renderTargetData.activeMipmapLevel !== renderContext.activeMipmapLevel

This oversight exposed two critical memory leaks:

  1. The dispose event listener was being added repeatedly without proper cleanup, as cache invalidation was triggered incorrectly.

  2. The caching strategy for texture views in _getRenderPassDescriptor was inefficient. It should separate the caching into two steps:

    • Cache expensive texture views based on target dimensions and mipmap/face properties
    • Apply dynamic properties (loadOp, storeOp, clearValue) on demand without recreating views

Additionally, texture views in the clear() method were never cached at all, resulting in new views being created for every clear operation, accumulating indefinitely.

I investigated this issue following memory leaks on a Windows project that ultimately crashed the GPU after running for a few hours. This suggests different platforms may handle GPU resource accumulation and cleanup differently, with Windows potentially being less forgiving.

Before this PR: Texture views infinitely accumulating, consuming GPU memory that may not be promptly released even after JavaScript references are no longer used.
Screenshot 2025-03-04 at 23 51 24
(But you can test any WebGPU example and will see the texture views accumulating and onDispose event stacking.)

After (Texture Views reduced and cached to 79):
Screenshot 2025-03-04 at 23 51 05

This contribution is funded by Utsubo

Copy link

github-actions bot commented Mar 4, 2025

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 336.02
78.26
336.02
78.26
+0 B
+0 B
WebGPU 523.26
145.3
523.81
145.44
+551 B
+135 B
WebGPU Nodes 522.73
145.2
523.28
145.33
+551 B
+135 B

🌳 Bundle size after tree-shaking

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

Before After Diff
WebGL 465.06
112.14
465.06
112.14
+0 B
+0 B
WebGPU 593.67
160.91
594.22
161.04
+551 B
+130 B
WebGPU Nodes 548.79
150.34
549.34
150.47
+551 B
+130 B

@RenaudRohlinger RenaudRohlinger merged commit 1c45822 into mrdoob:dev Mar 5, 2025
12 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