Fix shutdown crash caused by C# finalizers deleting texture objects after renderdevice already left the building

This commit is contained in:
Magnus Norddahl 2019-12-26 00:37:47 +01:00
parent 718405b580
commit 994eda4852
6 changed files with 27 additions and 5 deletions

View file

@ -27,6 +27,8 @@ GLIndexBuffer::~GLIndexBuffer()
{ {
if (Device && mBuffer != 0) if (Device && mBuffer != 0)
{ {
Device->mIndexBuffers.erase(ItBuffer);
Device = nullptr;
glDeleteBuffers(1, &mBuffer); glDeleteBuffers(1, &mBuffer);
mBuffer = 0; mBuffer = 0;
} }

View file

@ -22,6 +22,7 @@
#pragma once #pragma once
#include "../Backend.h" #include "../Backend.h"
#include <list>
class GLRenderDevice; class GLRenderDevice;
@ -33,6 +34,7 @@ public:
GLuint GetBuffer(); GLuint GetBuffer();
GLRenderDevice* Device = nullptr; GLRenderDevice* Device = nullptr;
std::list<GLIndexBuffer*>::iterator ItBuffer;
private: private:
GLuint mBuffer = 0; GLuint mBuffer = 0;

View file

@ -82,6 +82,11 @@ GLRenderDevice::~GLRenderDevice()
{ {
Context->MakeCurrent(); 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(); ProcessDeleteList();
glDeleteBuffers(1, &mStreamVertexBuffer); glDeleteBuffers(1, &mStreamVertexBuffer);
@ -89,9 +94,6 @@ GLRenderDevice::~GLRenderDevice()
for (auto& sharedbuf : mSharedVertexBuffers) for (auto& sharedbuf : mSharedVertexBuffers)
{ {
for (GLVertexBuffer* buf : sharedbuf->VertexBuffers)
buf->Device = nullptr;
GLuint handle = sharedbuf->GetBuffer(); GLuint handle = sharedbuf->GetBuffer();
glDeleteBuffers(1, &handle); glDeleteBuffers(1, &handle);
handle = sharedbuf->GetVAO(); handle = sharedbuf->GetVAO();
@ -107,6 +109,7 @@ GLRenderDevice::~GLRenderDevice()
} }
} }
mShaderManager->ReleaseResources(); mShaderManager->ReleaseResources();
Context->ClearCurrent(); Context->ClearCurrent();
} }
@ -584,6 +587,11 @@ bool GLRenderDevice::SetIndexBufferData(IndexBuffer* ibuffer, void* data, int64_
{ {
CheckContext(); CheckContext();
GLIndexBuffer* buffer = static_cast<GLIndexBuffer*>(ibuffer); GLIndexBuffer* buffer = static_cast<GLIndexBuffer*>(ibuffer);
if (buffer->Device == nullptr)
{
buffer->ItBuffer = mIndexBuffers.insert(mIndexBuffers.end(), buffer);
buffer->Device = this;
}
GLint oldbinding = 0; GLint oldbinding = 0;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &oldbinding); glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &oldbinding);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->GetBuffer()); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->GetBuffer());
@ -960,9 +968,11 @@ void GLRenderDevice::DeleteObject(GLTexture* texture)
void GLRenderDevice::ProcessDeleteList() void GLRenderDevice::ProcessDeleteList()
{ {
std::unique_lock<std::mutex> lock(GLRenderDevice::GetMutex()); std::unique_lock<std::mutex> lock(GLRenderDevice::GetMutex());
for (auto buffer : mDeleteList.IndexBuffers) delete buffer; for (auto buffer : mDeleteList.IndexBuffers) delete buffer;
for (auto buffer : mDeleteList.VertexBuffers) delete buffer; for (auto buffer : mDeleteList.VertexBuffers) delete buffer;
for (auto texture : mDeleteList.Textures) delete texture; for (auto texture : mDeleteList.Textures) delete texture;
mDeleteList.IndexBuffers.clear(); mDeleteList.IndexBuffers.clear();
mDeleteList.VertexBuffers.clear(); mDeleteList.VertexBuffers.clear();
mDeleteList.Textures.clear(); mDeleteList.Textures.clear();

View file

@ -23,6 +23,7 @@
#include "../Backend.h" #include "../Backend.h"
#include "OpenGLContext.h" #include "OpenGLContext.h"
#include <list>
class GLSharedVertexBuffer; class GLSharedVertexBuffer;
class GLShader; class GLShader;
@ -150,6 +151,9 @@ public:
std::unique_ptr<GLSharedVertexBuffer> mSharedVertexBuffers[2]; std::unique_ptr<GLSharedVertexBuffer> mSharedVertexBuffers[2];
std::list<GLTexture*> mTextures;
std::list<GLIndexBuffer*> mIndexBuffers;
std::unique_ptr<GLShaderManager> mShaderManager; std::unique_ptr<GLShaderManager> mShaderManager;
ShaderName mShaderName = {}; ShaderName mShaderName = {};

View file

@ -120,6 +120,7 @@ void GLTexture::Invalidate()
mFramebuffer = 0; mFramebuffer = 0;
mTexture = 0; mTexture = 0;
mPBO = 0; mPBO = 0;
if (Device) Device->mTextures.erase(ItTexture);
Device = nullptr; Device = nullptr;
} }
@ -128,6 +129,7 @@ GLuint GLTexture::GetTexture(GLRenderDevice* device)
if (mTexture == 0) if (mTexture == 0)
{ {
Device = device; Device = device;
ItTexture = Device->mTextures.insert(Device->mTextures.end(), this);
GLint oldActiveTex = GL_TEXTURE0; GLint oldActiveTex = GL_TEXTURE0;
glGetIntegerv(GL_ACTIVE_TEXTURE, &oldActiveTex); glGetIntegerv(GL_ACTIVE_TEXTURE, &oldActiveTex);
@ -174,7 +176,7 @@ GLuint GLTexture::GetFramebuffer(GLRenderDevice* device, bool usedepthbuffer)
{ {
if (mFramebuffer == 0) if (mFramebuffer == 0)
{ {
GLuint texture = GetTexture(Device); GLuint texture = GetTexture(device);
glGenFramebuffers(1, &mFramebuffer); glGenFramebuffers(1, &mFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 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) if (mFramebuffer == 0)
{ {
GLuint texture = GetTexture(Device); GLuint texture = GetTexture(device);
glGenFramebuffers(1, &mFramebuffer); glGenFramebuffers(1, &mFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

View file

@ -22,6 +22,7 @@
#pragma once #pragma once
#include "../Backend.h" #include "../Backend.h"
#include <list>
class GLRenderDevice; class GLRenderDevice;
@ -49,6 +50,7 @@ public:
GLuint GetPBO(GLRenderDevice* device); GLuint GetPBO(GLRenderDevice* device);
GLRenderDevice* Device = nullptr; GLRenderDevice* Device = nullptr;
std::list<GLTexture*>::iterator ItTexture;
private: private:
int mWidth = 0; int mWidth = 0;