From 98101f56feea576f8e240061c457541abc797aa1 Mon Sep 17 00:00:00 2001 From: struktured Date: Sun, 29 Mar 2026 17:29:12 -0400 Subject: [PATCH] Detach textures from framebuffers before deleting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GL drivers keep internal references to textures attached to framebuffers. Deleting a texture while still attached can cause use-after-free in driver memory, observed as crashes on NVIDIA during rapid preset switching or window resize. Detach all textures before deletion in both ~Framebuffer() and SetSize(), using a three-phase detach → resize → reattach pattern in SetSize() to avoid referencing stale texture IDs. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/libprojectM/Renderer/Framebuffer.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libprojectM/Renderer/Framebuffer.cpp b/src/libprojectM/Renderer/Framebuffer.cpp index 29994d19f4..9a06449ba5 100644 --- a/src/libprojectM/Renderer/Framebuffer.cpp +++ b/src/libprojectM/Renderer/Framebuffer.cpp @@ -24,11 +24,11 @@ Framebuffer::~Framebuffer() { if (!m_framebufferIds.empty()) { - // Delete attached textures first - m_attachments.clear(); - + // Delete FBOs first — this also releases driver references to attached textures. glDeleteFramebuffers(static_cast(m_framebufferIds.size()), m_framebufferIds.data()); m_framebufferIds.clear(); + + m_attachments.clear(); } } @@ -94,6 +94,8 @@ bool Framebuffer::SetSize(int width, int height) Bind(attachments.first); for (auto& texture : attachments.second) { + // Detach old texture, resize (destroys old and creates new), reattach new. + glFramebufferTexture2D(GL_FRAMEBUFFER, texture.first, GL_TEXTURE_2D, 0, 0); texture.second->SetSize(width, height); glFramebufferTexture2D(GL_FRAMEBUFFER, texture.first, GL_TEXTURE_2D, texture.second->Texture()->TextureID(), 0); }