Detach textures from framebuffers before deleting#986
Detach textures from framebuffers before deleting#986struktured wants to merge 1 commit intomasterfrom
Conversation
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) <noreply@anthropic.com>
| // First detach all textures from framebuffer before destroying them. | ||
| // The GL driver keeps internal references to attached textures, so we must | ||
| // detach before deleting to avoid use-after-free in driver memory. | ||
| for (auto& texture : attachments.second) |
There was a problem hiding this comment.
Is there any real technical reason to add two new loops here? Each attachment is independently managed in an FBO, so the detach->reallocate->attach code can be placed in the very same loop without bloating the code.
| // Detach all textures from each framebuffer before destroying them. | ||
| // The GL driver keeps internal references to attached textures, so we must | ||
| // detach before deleting to avoid use-after-free in driver memory. | ||
| for (auto& [index, attachments] : m_attachments) |
There was a problem hiding this comment.
Please do not use C++17 constructs, instead replace with a standard range-based loop. projectM must still compile with C++14.
| for (auto& [index, attachments] : m_attachments) | ||
| { | ||
| glBindFramebuffer(GL_FRAMEBUFFER, m_framebufferIds.at(index)); | ||
| for (auto& [type, _] : attachments) | ||
| { | ||
| glFramebufferTexture2D(GL_FRAMEBUFFER, type, GL_TEXTURE_2D, 0, 0); | ||
| } | ||
| } | ||
| glBindFramebuffer(GL_FRAMEBUFFER, 0); |
There was a problem hiding this comment.
Instead of this loop, as the FBO is deleted anyways, it should also suffice to just move up glDeleteFramebuffers() before m_attachments.clear(); instead of adding more bloat. Deleting the FBO will also delete all registered attachments.
|
Addressed all review feedback:
Tested on NVIDIA RTX 3090 (driver 580.126.09), KDE Wayland, Qt 6.9.2. |
Summary
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.
This commit detaches all textures from their FBOs before deletion in both
~Framebuffer()andSetSize(). TheSetSize()path uses a three-phase detach → resize → reattach pattern to avoid referencing stale texture IDs afterSetSize()destroys and recreates the underlying GL texture.Changes
src/libprojectM/Renderer/Framebuffer.cpp(+25, -1)Test plan