Skip to content

Conversation

@Sanchit2662
Copy link

@Sanchit2662 Sanchit2662 commented Jan 15, 2026

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 lint passes

Add dispose() methods to p5.Shader and p5.Texture classes and register
cleanup hook in p5.RendererGL to free GPU resources when remove() is called.

Signed-off-by: Sanchit2662 <sanchit2662@gmail.com>
@Sanchit2662
Copy link
Author

Hi @davepagurek,
This PR fixes a WebGL lifecycle issue where shader programs and textures weren’t being released when a sketch was removed, which could lead to unbounded GPU memory growth in long-running or hot-reload scenarios. The update adds explicit cleanup for WebGL resources and ensures everything is properly disposed on sketch.remove().

Whenever you have time, I’d appreciate a review. Thanks!

@davepagurek
Copy link
Contributor

Thanks for taking this on! Some small thoughts:

  • Could we use the remove() naming everywhere for consistency rather than introducing dispose() for some things?
  • This PR is into the main branch, which is just for 1.x code. The dev-2.0 branch has our work on p5 2.x, which will become default sometime this year. If you're up for it, before calling the issue resolved, we should make similar changes there, although it's a bit more complicated because we have both WebGL and WebGPU support for these objects. It's likely complicated enough that we'd want to make some unit tests there too.

this._curShader = undefined;

// Register cleanup hook to free WebGL resources when sketch is removed
this._pInst.registerMethod('remove', this._cleanupWebGLResources.bind(this));
Copy link
Contributor

Choose a reason for hiding this comment

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

The tests are also showing errors that this method is not defined when inside of createGraphics

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