From 994eda485288c4850fb6267144a1b16495cb6587 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 26 Dec 2019 00:37:47 +0100 Subject: [PATCH] Fix shutdown crash caused by C# finalizers deleting texture objects after renderdevice already left the building --- Source/Native/OpenGL/GLIndexBuffer.cpp | 2 ++ Source/Native/OpenGL/GLIndexBuffer.h | 2 ++ Source/Native/OpenGL/GLRenderDevice.cpp | 16 +++++++++++++--- Source/Native/OpenGL/GLRenderDevice.h | 4 ++++ Source/Native/OpenGL/GLTexture.cpp | 6 ++++-- Source/Native/OpenGL/GLTexture.h | 2 ++ 6 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Source/Native/OpenGL/GLIndexBuffer.cpp b/Source/Native/OpenGL/GLIndexBuffer.cpp index cbc123c0..8adbcc51 100644 --- a/Source/Native/OpenGL/GLIndexBuffer.cpp +++ b/Source/Native/OpenGL/GLIndexBuffer.cpp @@ -27,6 +27,8 @@ GLIndexBuffer::~GLIndexBuffer() { if (Device && mBuffer != 0) { + Device->mIndexBuffers.erase(ItBuffer); + Device = nullptr; glDeleteBuffers(1, &mBuffer); mBuffer = 0; } diff --git a/Source/Native/OpenGL/GLIndexBuffer.h b/Source/Native/OpenGL/GLIndexBuffer.h index 4d20f47b..64ea71c8 100644 --- a/Source/Native/OpenGL/GLIndexBuffer.h +++ b/Source/Native/OpenGL/GLIndexBuffer.h @@ -22,6 +22,7 @@ #pragma once #include "../Backend.h" +#include class GLRenderDevice; @@ -33,6 +34,7 @@ public: GLuint GetBuffer(); GLRenderDevice* Device = nullptr; + std::list::iterator ItBuffer; private: GLuint mBuffer = 0; diff --git a/Source/Native/OpenGL/GLRenderDevice.cpp b/Source/Native/OpenGL/GLRenderDevice.cpp index f34f266f..9c6d988a 100644 --- a/Source/Native/OpenGL/GLRenderDevice.cpp +++ b/Source/Native/OpenGL/GLRenderDevice.cpp @@ -82,6 +82,11 @@ GLRenderDevice::~GLRenderDevice() { Context->MakeCurrent(); + ProcessDeleteList(); + for (GLTexture* tex : mTextures) mDeleteList.Textures.push_back(tex); + for (GLIndexBuffer* buffer : mIndexBuffers) mDeleteList.IndexBuffers.push_back(buffer); + for (GLVertexBuffer* buffer : mSharedVertexBuffers[0]->VertexBuffers) mDeleteList.VertexBuffers.push_back(buffer); + for (GLVertexBuffer* buffer : mSharedVertexBuffers[1]->VertexBuffers) mDeleteList.VertexBuffers.push_back(buffer); ProcessDeleteList(); glDeleteBuffers(1, &mStreamVertexBuffer); @@ -89,9 +94,6 @@ GLRenderDevice::~GLRenderDevice() for (auto& sharedbuf : mSharedVertexBuffers) { - for (GLVertexBuffer* buf : sharedbuf->VertexBuffers) - buf->Device = nullptr; - GLuint handle = sharedbuf->GetBuffer(); glDeleteBuffers(1, &handle); handle = sharedbuf->GetVAO(); @@ -107,6 +109,7 @@ GLRenderDevice::~GLRenderDevice() } } + mShaderManager->ReleaseResources(); Context->ClearCurrent(); } @@ -584,6 +587,11 @@ bool GLRenderDevice::SetIndexBufferData(IndexBuffer* ibuffer, void* data, int64_ { CheckContext(); GLIndexBuffer* buffer = static_cast(ibuffer); + if (buffer->Device == nullptr) + { + buffer->ItBuffer = mIndexBuffers.insert(mIndexBuffers.end(), buffer); + buffer->Device = this; + } GLint oldbinding = 0; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &oldbinding); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->GetBuffer()); @@ -960,9 +968,11 @@ void GLRenderDevice::DeleteObject(GLTexture* texture) void GLRenderDevice::ProcessDeleteList() { std::unique_lock lock(GLRenderDevice::GetMutex()); + for (auto buffer : mDeleteList.IndexBuffers) delete buffer; for (auto buffer : mDeleteList.VertexBuffers) delete buffer; for (auto texture : mDeleteList.Textures) delete texture; + mDeleteList.IndexBuffers.clear(); mDeleteList.VertexBuffers.clear(); mDeleteList.Textures.clear(); diff --git a/Source/Native/OpenGL/GLRenderDevice.h b/Source/Native/OpenGL/GLRenderDevice.h index 7a9919f9..6d22a90b 100644 --- a/Source/Native/OpenGL/GLRenderDevice.h +++ b/Source/Native/OpenGL/GLRenderDevice.h @@ -23,6 +23,7 @@ #include "../Backend.h" #include "OpenGLContext.h" +#include class GLSharedVertexBuffer; class GLShader; @@ -150,6 +151,9 @@ public: std::unique_ptr mSharedVertexBuffers[2]; + std::list mTextures; + std::list mIndexBuffers; + std::unique_ptr mShaderManager; ShaderName mShaderName = {}; diff --git a/Source/Native/OpenGL/GLTexture.cpp b/Source/Native/OpenGL/GLTexture.cpp index f2dbaf7e..f41d86a0 100644 --- a/Source/Native/OpenGL/GLTexture.cpp +++ b/Source/Native/OpenGL/GLTexture.cpp @@ -120,6 +120,7 @@ void GLTexture::Invalidate() mFramebuffer = 0; mTexture = 0; mPBO = 0; + if (Device) Device->mTextures.erase(ItTexture); Device = nullptr; } @@ -128,6 +129,7 @@ GLuint GLTexture::GetTexture(GLRenderDevice* device) if (mTexture == 0) { Device = device; + ItTexture = Device->mTextures.insert(Device->mTextures.end(), this); GLint oldActiveTex = GL_TEXTURE0; glGetIntegerv(GL_ACTIVE_TEXTURE, &oldActiveTex); @@ -174,7 +176,7 @@ GLuint GLTexture::GetFramebuffer(GLRenderDevice* device, bool usedepthbuffer) { if (mFramebuffer == 0) { - GLuint texture = GetTexture(Device); + GLuint texture = GetTexture(device); glGenFramebuffers(1, &mFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); @@ -197,7 +199,7 @@ GLuint GLTexture::GetFramebuffer(GLRenderDevice* device, bool usedepthbuffer) if (mFramebuffer == 0) { - GLuint texture = GetTexture(Device); + GLuint texture = GetTexture(device); glGenFramebuffers(1, &mFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); diff --git a/Source/Native/OpenGL/GLTexture.h b/Source/Native/OpenGL/GLTexture.h index 3fbd7593..6c47e3a5 100644 --- a/Source/Native/OpenGL/GLTexture.h +++ b/Source/Native/OpenGL/GLTexture.h @@ -22,6 +22,7 @@ #pragma once #include "../Backend.h" +#include class GLRenderDevice; @@ -49,6 +50,7 @@ public: GLuint GetPBO(GLRenderDevice* device); GLRenderDevice* Device = nullptr; + std::list::iterator ItTexture; private: int mWidth = 0;