Fix WebGL shader and texture memory leak on sketch removal by Sanchit2662 · Pull Request #8418 · processing/p5.js
Summary
This PR fixes a critical WebGL lifecycle issue where shader programs and textures were never explicitly released from GPU memory when a sketch was destroyed. As a result, applications that repeatedly create and remove WebGL sketches (e.g. hot-reload editors, instance-mode apps, long-running installations) experienced unbounded GPU memory growth.
The fix introduces explicit dispose() methods for WebGL-backed resources and registers a renderer-level cleanup hook that is automatically invoked when sketch.remove() is called.
Impact
Before
- WebGL shaders, programs, and textures remain allocated after
remove() - GPU memory grows unboundedly in multi-sketch or hot-reload scenarios
- No user-level workaround is possible
After
- All WebGL shader and texture resources are explicitly released
- GPU memory remains stable across repeated sketch creation/destruction
- Instance-mode and long-running WebGL sketches behave reliably
Changes
1. p5.Shader.dispose()
Adds an explicit teardown path for shader GPU resources.
dispose() { if (!this._gl || !this._glProgram) return; this._glProgram = null; }
- Properly detaches shaders before deletion
- Deletes both shader objects and the linked program
- Guards against double deletion or uninitialized shaders
2. p5.Texture.dispose()
Ensures GPU textures are freed when no longer needed.
dispose() { if (this.glTex && !this.isFramebufferTexture) { } }
- Releases GPU texture memory
- Skips framebuffer-managed textures to avoid double-freeing
3. Renderer-level cleanup hook (p5.RendererGL)
Introduces a centralized cleanup method that disposes all WebGL resources owned by the renderer.
Key resources cleaned:
- Default and user shaders
- Cached textures (
this.textures) - Filter shaders and filter layers
- Framebuffers and retained-mode buffers
- Empty texture singleton
The cleanup is automatically invoked on sketch teardown:
this._pInst.registerMethod( 'remove', this._cleanupWebGLResources.bind(this) );
PR Checklist
-
npm run lintpasses