mirror of
https://github.com/projectM-visualizer/projectm.git
synced 2026-03-31 11:43:31 +00:00
Detach textures from framebuffers before deleting
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>
This commit is contained in:
@ -24,7 +24,19 @@ Framebuffer::~Framebuffer()
|
||||
{
|
||||
if (!m_framebufferIds.empty())
|
||||
{
|
||||
// Delete attached textures first
|
||||
// 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)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebufferIds.at(index));
|
||||
for (auto& [type, _] : attachments)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, type, GL_TEXTURE_2D, 0, 0);
|
||||
}
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
m_attachments.clear();
|
||||
|
||||
glDeleteFramebuffers(static_cast<int>(m_framebufferIds.size()), m_framebufferIds.data());
|
||||
@ -92,9 +104,21 @@ bool Framebuffer::SetSize(int width, int height)
|
||||
for (auto& attachments : m_attachments)
|
||||
{
|
||||
Bind(attachments.first);
|
||||
// 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)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, texture.first, GL_TEXTURE_2D, 0, 0);
|
||||
}
|
||||
// Now safe to resize (which destroys old textures and creates new ones)
|
||||
for (auto& texture : attachments.second)
|
||||
{
|
||||
texture.second->SetSize(width, height);
|
||||
}
|
||||
// Reattach the new textures
|
||||
for (auto& texture : attachments.second)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, texture.first, GL_TEXTURE_2D, texture.second->Texture()->TextureID(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user