fix(OpenGL/Framebuffer): release owned resources on delete - #3619
Open
PaulHax wants to merge 1 commit into
Open
Conversation
populateFramebuffer creates a color texture and a depth renderbuffer that nothing ever freed: releaseGraphicsResources deleted the framebuffer but not the attachments, and delete did not call it. Track ownership of what populateFramebuffer creates and free it together with the framebuffer when the framebuffer is released or deleted. Caller-supplied attachments stay borrowed. When the render window is already deleted but the shared GL context is still alive, the owned texture is freed directly on the context. Nulling glFramebuffer on release also repairs the getSize and getGLFramebuffer resize checks in OpenGL/VolumeMapper, ForwardPass, Convolution2DPass and RadialDistortionPass, which previously reused a deleted framebuffer object. removeColorBuffer clears the slot instead of splicing, keeping array indices aligned with GL color attachment points, and bind skips the holes. create re-binds the new framebuffer when the one it released was bound, since deleting a bound framebuffer resets the GL binding to the default one. Tests cover attachment ownership, repopulation and delete through the public API, counting live WebGL objects.
PaulHax
marked this pull request as ready for review
August 28, 2026 21:32
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
vtkFramebuffer.populateFramebuffer()creates a color texture and a depth renderbuffer that nothing ever frees:releaseGraphicsResources()deletes the framebuffer but not the attachments, anddelete()never calls it. Every torn-down consumer (hardware selector, volume mapper, render passes) leaks a full-window RGBA texture and DEPTH_COMPONENT16 renderbuffer.Results
Releasing or deleting a framebuffer now frees everything
populateFramebuffercreated along with the GL framebuffer; the live WebGL object count returns to baseline in the new tests. Caller-supplied attachments stay borrowed. NullingglFramebufferon release also repairs thegetSize()/getGLFramebuffer()resize checks inOpenGL/VolumeMapper,ForwardPass,Convolution2DPassandRadialDistortionPass, which previously reused a deleted framebuffer object.Changes
populateFramebuffer()creates and frees them onreleaseGraphicsResources(), which is now chained intodelete(). When the render window is already deleted but the shared GL context is still alive (multi-view teardown order), the owned texture is freed directly on the context.removeColorBufferclears the slot instead of splicing. The previous code shifted later entries down, desynchronizing array indices from GL color attachment points (COLOR_ATTACHMENT0 + n) for consumers using multiple attachments (SurfaceLIC attaches 0, 2, 3).bind()skips empty slots.create()re-binds the new framebuffer when the one it released was bound: deleting a bound framebuffer resets the GL binding to the default, which would send bind-then-create callers (SurfaceLIC) rendering to the canvas.populateFramebufferstill releases attachments before creating new ones. That is redundant withcreate()at every current call site, but it is what keeps a repeatpopulateFramebuffer()from leaking, and both paths now share onereleaseAttachments()implementation.PR and Code Checklist
npm run reformatto have correctly formatted code