From 378170d723c97f4608f1bef8f8b22fb3d1e293f8 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 18 Mar 2017 13:01:08 +0100 Subject: [PATCH] Add ability to tag objects in the gl_lost_manager --- GPU/GLES/DrawEngineGLES.cpp | 5 ++--- UI/TextureUtil.h | 2 +- ext/native/gfx/gl_lost_manager.cpp | 27 ++++++++++++++++----------- ext/native/gfx/gl_lost_manager.h | 13 +++++++++++-- ext/native/gfx_es2/glsl_program.cpp | 4 ++-- ext/native/thin3d/thin3d_gl.cpp | 4 ++-- 6 files changed, 34 insertions(+), 21 deletions(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 49d51dbb5..60b344fb1 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -145,7 +145,7 @@ DrawEngineGLES::DrawEngineGLES() indexGen.Setup(decIndex); InitDeviceObjects(); - register_gl_resource_holder(this); + register_gl_resource_holder(this, "drawengine_gles"); tessDataTransfer = new TessellationDataTransferGLES(gl_extensions.VersionGEThan(3, 0, 0)); } @@ -200,7 +200,6 @@ void DrawEngineGLES::DestroyDeviceObjects() { bufferNameInfo_.clear(); freeSizedBuffers_.clear(); bufferNameCacheSize_ = 0; - if (sharedVao_ != 0) { glDeleteVertexArrays(1, &sharedVao_); } @@ -209,7 +208,7 @@ void DrawEngineGLES::DestroyDeviceObjects() { void DrawEngineGLES::GLLost() { ILOG("TransformDrawEngine::GLLost()"); - // The objects have already been deleted. + // The objects have already been deleted by losing the context, so we don't call DestroyDeviceObjects. bufferNameCache_.clear(); bufferNameInfo_.clear(); freeSizedBuffers_.clear(); diff --git a/UI/TextureUtil.h b/UI/TextureUtil.h index eaa5b14a2..df9414335 100644 --- a/UI/TextureUtil.h +++ b/UI/TextureUtil.h @@ -16,7 +16,7 @@ class ManagedTexture : public GfxResourceHolder { public: ManagedTexture(Draw::DrawContext *draw) : draw_(draw), texture_(nullptr) { if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) - register_gl_resource_holder(this); + register_gl_resource_holder(this, "managed_texture"); } ~ManagedTexture() { if (texture_) diff --git a/ext/native/gfx/gl_lost_manager.cpp b/ext/native/gfx/gl_lost_manager.cpp index 61e68f20d..944ca5c14 100644 --- a/ext/native/gfx/gl_lost_manager.cpp +++ b/ext/native/gfx/gl_lost_manager.cpp @@ -4,18 +4,23 @@ #include "base/logging.h" #include "gfx/gl_lost_manager.h" -std::vector *holders; +struct Holder { + GfxResourceHolder *holder; + const char *desc; +}; + +std::vector *holders; static bool inLost; static bool inRestore; -void register_gl_resource_holder(GfxResourceHolder *holder) { +void register_gl_resource_holder(GfxResourceHolder *holder, const char *desc) { if (inLost || inRestore) { FLOG("BAD: Should not call register_gl_resource_holder from lost/restore path"); return; } if (holders) { - holders->push_back(holder); + holders->push_back({ holder, desc }); } else { WLOG("GL resource holder not initialized, cannot register resource"); } @@ -28,7 +33,7 @@ void unregister_gl_resource_holder(GfxResourceHolder *holder) { } if (holders) { for (size_t i = 0; i < holders->size(); i++) { - if ((*holders)[i] == holder) { + if ((*holders)[i].holder == holder) { holders->erase(holders->begin() + i); return; } @@ -47,12 +52,12 @@ void gl_restore() { return; } - ILOG("gl_restore() restoring %i items:", (int)holders->size()); + ILOG("gl_restore() restoring %d items:", (int)holders->size()); for (size_t i = 0; i < holders->size(); i++) { - ILOG("gl_restore(%i / %i, %p, %08x)", (int)(i + 1), (int)holders->size(), (*holders)[i], *((uint32_t *)((*holders)[i]))); - (*holders)[i]->GLRestore(); + ILOG("gl_restore(%d / %d, %s)", (int)(i + 1), (int)holders->size(), (*holders)[i].desc); + (*holders)[i].holder->GLRestore(); } - ILOG("gl_restore() completed on %i items:", (int)holders->size()); + ILOG("gl_restore() completed on %d items:", (int)holders->size()); inRestore = false; } @@ -66,8 +71,8 @@ void gl_lost() { ILOG("gl_lost() clearing %i items:", (int)holders->size()); for (size_t i = 0; i < holders->size(); i++) { - ILOG("gl_lost(%i / %i, %p, %08x)", (int)(i + 1), (int)holders->size(), (*holders)[i], *((uint32_t *)((*holders)[i]))); - (*holders)[i]->GLLost(); + ILOG("gl_lost(%d / %d, %s)", (int)(i + 1), (int)holders->size(), (*holders)[i].desc); + (*holders)[i].holder->GLLost(); } ILOG("gl_lost() completed on %i items:", (int)holders->size()); inLost = false; @@ -78,7 +83,7 @@ void gl_lost_manager_init() { FLOG("Double GL lost manager init"); // Dead here (FLOG), no need to delete holders } - holders = new std::vector(); + holders = new std::vector(); } void gl_lost_manager_shutdown() { diff --git a/ext/native/gfx/gl_lost_manager.h b/ext/native/gfx/gl_lost_manager.h index cfb09601a..fc60609dd 100644 --- a/ext/native/gfx/gl_lost_manager.h +++ b/ext/native/gfx/gl_lost_manager.h @@ -3,17 +3,26 @@ // On Android, even OpenGL can lose allocated resources. This is a utility to keep // track of them. +// It's important to realize that with OpenGL, there's no Lost event that can be relied upon. +// The only solid indication we get is onSurfaceCreated. That is called every time the graphics +// surface that we render upon has been recreated. When that's called, we know that any +// gl resources we owned before it was called have been killed and need to be recreated. + +// However, with D3D UWP, and potentially other platforms, there is a lost event. +// So we keep that infrastructure, but with GL we simply call both Lost and Restore when we detect a Restore. + class GfxResourceHolder { public: virtual ~GfxResourceHolder() {} - virtual void GLRestore() = 0; virtual void GLLost() = 0; + virtual void GLRestore() = 0; }; void gl_lost_manager_init(); void gl_lost_manager_shutdown(); -void register_gl_resource_holder(GfxResourceHolder *holder); +// The string pointed to by desc must be a constant or otherwise live for the entire registered lifetime of the object. +void register_gl_resource_holder(GfxResourceHolder *holder, const char *desc); void unregister_gl_resource_holder(GfxResourceHolder *holder); // Notifies all objects it's time to forget / delete things. diff --git a/ext/native/gfx_es2/glsl_program.cpp b/ext/native/gfx_es2/glsl_program.cpp index c0c08a7cd..989e4e00e 100644 --- a/ext/native/gfx_es2/glsl_program.cpp +++ b/ext/native/gfx_es2/glsl_program.cpp @@ -49,7 +49,7 @@ GLSLProgram *glsl_create(const char *vshader, const char *fshader, std::string * delete program; return 0; } - register_gl_resource_holder(program); + register_gl_resource_holder(program, "glsl_program"); return program; } @@ -70,7 +70,7 @@ GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src delete program; return 0; } - register_gl_resource_holder(program); + register_gl_resource_holder(program, "glsl_program_src"); return program; } diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 441e3e2b3..e82b2ac6e 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -369,7 +369,7 @@ class OpenGLPipeline : public Pipeline, GfxResourceHolder { public: OpenGLPipeline() { program_ = 0; - register_gl_resource_holder(this); + register_gl_resource_holder(this, "drawcontext_pipeline"); } ~OpenGLPipeline() { unregister_gl_resource_holder(this); @@ -890,7 +890,7 @@ public: totalSize_ = size; glBindBuffer(target_, buffer_); glBufferData(target_, size, NULL, usage_); - register_gl_resource_holder(this); + register_gl_resource_holder(this, "drawcontext_buffer"); } ~OpenGLBuffer() override { unregister_gl_resource_holder(this);