From 7d0fc9ce65543419c3f4cb9da0934422521069f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 7 Dec 2017 14:56:19 +0100 Subject: [PATCH] Rework GL lost-device to work more like Vulkan. Gets rid of gl_lost manager etc. --- CMakeLists.txt | 2 - GPU/GLES/DrawEngineGLES.cpp | 18 ---- GPU/GLES/DrawEngineGLES.h | 5 +- GPU/GLES/FramebufferManagerGLES.cpp | 66 +++++++------- GPU/GLES/FramebufferManagerGLES.h | 12 ++- GPU/GLES/GPU_GLES.cpp | 9 +- GPU/GLES/TextureCacheGLES.cpp | 19 ++-- GPU/GLES/TextureCacheGLES.h | 2 + Qt/Debugger/debugger_memorytex.cpp | 1 - UI/EmuScreen.cpp | 18 ---- UI/EmuScreen.h | 2 - UI/NativeApp.cpp | 47 +++------- UI/TextureUtil.h | 25 +----- android/jni/app-android.cpp | 17 ++-- ext/native/Android.mk | 1 - ext/native/base/NativeApp.h | 7 -- ext/native/gfx/gl_lost_manager.cpp | 131 ---------------------------- ext/native/gfx/gl_lost_manager.h | 36 -------- ext/native/gfx_es2/draw_buffer.h | 1 - ext/native/gfx_es2/glsl_program.cpp | 20 ----- ext/native/gfx_es2/glsl_program.h | 6 +- ext/native/native.vcxproj | 2 - ext/native/native.vcxproj.filters | 6 -- ext/native/thin3d/thin3d_gl.cpp | 77 ++-------------- ext/native/ui/screen.cpp | 16 ---- ext/native/ui/screen.h | 4 - headless/SDLHeadlessHost.cpp | 5 -- 27 files changed, 90 insertions(+), 465 deletions(-) delete mode 100644 ext/native/gfx/gl_lost_manager.cpp delete mode 100644 ext/native/gfx/gl_lost_manager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 84ac29f736..16fe1ef6ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -868,8 +868,6 @@ add_library(native STATIC ext/native/gfx/gl_common.h ext/native/gfx/gl_debug_log.cpp ext/native/gfx/gl_debug_log.h - ext/native/gfx/gl_lost_manager.cpp - ext/native/gfx/gl_lost_manager.h ext/native/gfx/texture_atlas.cpp ext/native/gfx/texture_atlas.h ext/native/gfx/d3d9_shader.cpp diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index a60549a6fa..c669843952 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -132,7 +132,6 @@ DrawEngineGLES::DrawEngineGLES() : vai_(256) { indexGen.Setup(decIndex); InitDeviceObjects(); - register_gl_resource_holder(this, "drawengine_gles", 1); tessDataTransfer = new TessellationDataTransferGLES(gl_extensions.VersionGEThan(3, 0, 0)); } @@ -143,8 +142,6 @@ DrawEngineGLES::~DrawEngineGLES() { FreeMemoryPages(decIndex, DECODED_INDEX_BUFFER_SIZE); FreeMemoryPages(splineBuffer, SPLINE_BUFFER_SIZE); - unregister_gl_resource_holder(this); - delete tessDataTransfer; } @@ -191,21 +188,6 @@ void DrawEngineGLES::DestroyDeviceObjects() { } } -void DrawEngineGLES::GLLost() { - ILOG("TransformDrawEngine::GLLost()"); - // The objects have already been deleted by losing the context, so we don't call DestroyDeviceObjects. - bufferNameCache_.clear(); - bufferNameInfo_.clear(); - freeSizedBuffers_.clear(); - bufferNameCacheSize_ = 0; - ClearTrackedVertexArrays(); -} - -void DrawEngineGLES::GLRestore() { - ILOG("TransformDrawEngine::GLRestore()"); - InitDeviceObjects(); -} - struct GlTypeInfo { u16 type; u8 count; diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index f2be7c9a6f..d3e695a158 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -28,7 +28,6 @@ #include "GPU/Common/GPUStateUtils.h" #include "GPU/GLES/FragmentShaderGeneratorGLES.h" #include "gfx/gl_common.h" -#include "gfx/gl_lost_manager.h" class LinkedShader; class ShaderManagerGLES; @@ -100,7 +99,7 @@ public: }; // Handles transform, lighting and drawing. -class DrawEngineGLES : public DrawEngineCommon, public GfxResourceHolder { +class DrawEngineGLES : public DrawEngineCommon { public: DrawEngineGLES(); virtual ~DrawEngineGLES(); @@ -122,8 +121,6 @@ public: void RestoreVAO(); void InitDeviceObjects(); void DestroyDeviceObjects(); - void GLLost() override; - void GLRestore() override; void ClearTrackedVertexArrays() override; void DecimateTrackedVertexArrays(); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 37706d0710..4324cb17ac 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -75,6 +75,8 @@ static const char basic_vs[] = " gl_Position = a_position;\n" "}\n"; +const int MAX_PBO = 2; + void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u32 width, u32 height, GEBufferFormat format); void FramebufferManagerGLES::DisableState() { @@ -189,25 +191,11 @@ void FramebufferManagerGLES::BindPostShader(const PostShaderUniforms &uniforms) glUniform1f(videoLoc_, uniforms.video); } -void FramebufferManagerGLES::DestroyDraw2DProgram() { - if (draw2dprogram_) { - glsl_destroy(draw2dprogram_); - draw2dprogram_ = nullptr; - } - if (postShaderProgram_) { - glsl_destroy(postShaderProgram_); - postShaderProgram_ = nullptr; - } -} - FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) : FramebufferManagerCommon(draw), drawPixelsTex_(0), drawPixelsTexFormat_(GE_FORMAT_INVALID), convBuf_(nullptr), - draw2dprogram_(nullptr), - postShaderProgram_(nullptr), - stencilUploadProgram_(nullptr), videoLoc_(-1), timeLoc_(-1), pixelDeltaLoc_(-1), @@ -219,6 +207,7 @@ FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) : { needBackBufferYSwap_ = true; needGLESRebinds_ = true; + CreateDeviceObjects(); } void FramebufferManagerGLES::Init() { @@ -243,19 +232,38 @@ void FramebufferManagerGLES::SetDrawEngine(DrawEngineGLES *td) { drawEngine_ = td; } -FramebufferManagerGLES::~FramebufferManagerGLES() { - if (drawPixelsTex_) +void FramebufferManagerGLES::CreateDeviceObjects() { + CompileDraw2DProgram(); +} + +void FramebufferManagerGLES::DestroyDeviceObjects() { + if (draw2dprogram_) { + glsl_destroy(draw2dprogram_); + draw2dprogram_ = nullptr; + } + if (postShaderProgram_) { + glsl_destroy(postShaderProgram_); + postShaderProgram_ = nullptr; + } + if (drawPixelsTex_) { glDeleteTextures(1, &drawPixelsTex_); - DestroyDraw2DProgram(); + drawPixelsTex_ = 0; + } if (stencilUploadProgram_) { glsl_destroy(stencilUploadProgram_); + stencilUploadProgram_ = nullptr; } +} - for (auto it = tempFBOs_.begin(), end = tempFBOs_.end(); it != end; ++it) { - it->second.fbo->Release(); +FramebufferManagerGLES::~FramebufferManagerGLES() { + DestroyDeviceObjects(); + + if (pixelBufObj_) { + for (int i = 0; i < MAX_PBO; i++) { + glDeleteBuffers(1, &pixelBufObj_[i].handle); + } + delete[] pixelBufObj_; } - - delete [] pixelBufObj_; delete [] convBuf_; } @@ -761,7 +769,6 @@ void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) { CHECK_GL_ERROR_IF_DEBUG(); - const int MAX_PBO = 2; GLubyte *packed = 0; bool unbind = false; const u8 nextPBO = (currentPBO_ + 1) % MAX_PBO; @@ -1005,7 +1012,12 @@ void FramebufferManagerGLES::EndFrame() { void FramebufferManagerGLES::DeviceLost() { DestroyAllFBOs(); - DestroyDraw2DProgram(); + DestroyDeviceObjects(); +} + +void FramebufferManagerGLES::DeviceRestore(Draw::DrawContext *draw) { + draw_ = draw; + CreateDeviceObjects(); } void FramebufferManagerGLES::DestroyAllFBOs() { @@ -1046,8 +1058,6 @@ void FramebufferManagerGLES::Resized() { DestroyAllFBOs(); } - DestroyDraw2DProgram(); - #ifndef USING_GLES2 if (g_Config.iInternalResolution == 0) { glLineWidth(std::max(1, (int)(renderWidth_ / 480))); @@ -1057,10 +1067,6 @@ void FramebufferManagerGLES::Resized() { glPointSize((float)g_Config.iInternalResolution); } #endif - - if (!draw2dprogram_) { - CompileDraw2DProgram(); - } } bool FramebufferManagerGLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) { @@ -1069,4 +1075,4 @@ bool FramebufferManagerGLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) { buffer.Allocate(w, h, GPU_DBG_FORMAT_888_RGB, true); draw_->CopyFramebufferToMemorySync(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8_UNORM, buffer.GetData(), w); return true; -} +} \ No newline at end of file diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index 03b279c54c..94c87ae982 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -83,6 +83,8 @@ public: bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; virtual void RebindFramebuffer() override; + void DeviceRestore(Draw::DrawContext *draw); + protected: void SetViewport2D(int x, int y, int w, int h) override; void DisableState() override; @@ -94,6 +96,9 @@ protected: void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; private: + void CreateDeviceObjects(); + void DestroyDeviceObjects(); + void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) override; void Bind2DShader() override; void BindPostShader(const PostShaderUniforms &uniforms) override; @@ -113,10 +118,9 @@ private: u8 *convBuf_; u32 convBufSize_; - GLSLProgram *draw2dprogram_; - GLSLProgram *plainColorProgram_; - GLSLProgram *postShaderProgram_; - GLSLProgram *stencilUploadProgram_; + GLSLProgram *draw2dprogram_ = nullptr; + GLSLProgram *postShaderProgram_ = nullptr; + GLSLProgram *stencilUploadProgram_ = nullptr; int plainColorLoc_; int videoLoc_; int timeLoc_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index f159844697..602b659a90 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -387,23 +387,24 @@ void GPU_GLES::BuildReportingInfo() { void GPU_GLES::DeviceLost() { ILOG("GPU_GLES: DeviceLost"); - // Should only be executed on the GL thread. - // Simply drop all caches and textures. - // FBOs appear to survive? Or no? - // TransformDraw has registered as a GfxResourceHolder. shaderManagerGL_->ClearCache(false); textureCacheGL_->Clear(false); fragmentTestCache_.Clear(false); depalShaderCache_.Clear(); + drawEngine_.ClearTrackedVertexArrays(); framebufferManagerGL_->DeviceLost(); } void GPU_GLES::DeviceRestore() { + draw_ = (Draw::DrawContext *)PSP_CoreParameter().graphicsContext->GetDrawContext(); ILOG("GPU_GLES: DeviceRestore"); UpdateCmdInfo(); UpdateVsyncInterval(true); + + textureCacheGL_->DeviceRestore(draw_); + framebufferManagerGL_->DeviceRestore(draw_); } void GPU_GLES::Reinitialize() { diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 6660b58dad..ebdab10e9b 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -917,6 +917,11 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, w, h, components2, dstFmt, pixelData); } else { PROFILE_THIS_SCOPE("loadtex"); + // Avoid misleading errors in texture upload, these are common. + GLenum err = glGetError(); + if (err) { + WARN_LOG(G3D, "Got an error BEFORE texture upload: %08x (%s)", err, GLEnumToString(err).c_str()); + } if (IsFakeMipmapChange()) glTexImage2D(GL_TEXTURE_2D, 0, components, w, h, 0, components2, dstFmt, pixelData); else @@ -925,7 +930,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r // TODO: We really, really should avoid calling glGetError. GLenum err = glGetError(); if (err == GL_OUT_OF_MEMORY) { - WARN_LOG_REPORT(G3D, "Texture cache ran out of GPU memory; switching to low memory mode"); + WARN_LOG(G3D, "Texture cache ran out of GPU memory; switching to low memory mode"); lowMemoryMode_ = true; decimationCounter_ = 0; Decimate(); @@ -939,15 +944,9 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r host->NotifyUserMessage(err->T("Warning: Video memory FULL, switching to slow caching mode"), 2.0f); } } else if (err != GL_NO_ERROR) { - const char *str = "other"; - switch (err) { - case GL_OUT_OF_MEMORY: str = "out_of_memory"; break; - case GL_INVALID_ENUM: str = "invalid_enum"; break; - case GL_INVALID_VALUE: str = "invalid_value"; break; - } // We checked the err anyway, might as well log if there is one. WARN_LOG(G3D, "Got an error in texture upload: %08x (%s) (components=%s components2=%s dstFmt=%s w=%d h=%d level=%d)", - err, str, GLEnumToString(components).c_str(), GLEnumToString(components2).c_str(), GLEnumToString(dstFmt).c_str(), + err, GLEnumToString(err).c_str(), GLEnumToString(components).c_str(), GLEnumToString(components2).c_str(), GLEnumToString(dstFmt).c_str(), w, h, level); } } @@ -1066,3 +1065,7 @@ bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) return false; #endif } + +void TextureCacheGLES::DeviceRestore(Draw::DrawContext *draw) { + draw_ = draw; +} diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index e00a43afd6..87018b7197 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -69,6 +69,8 @@ public: void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight); bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override; + void DeviceRestore(Draw::DrawContext *draw); + protected: void BindTexture(TexCacheEntry *entry) override; void Unbind() override; diff --git a/Qt/Debugger/debugger_memorytex.cpp b/Qt/Debugger/debugger_memorytex.cpp index 82f1793057..51af9915c5 100644 --- a/Qt/Debugger/debugger_memorytex.cpp +++ b/Qt/Debugger/debugger_memorytex.cpp @@ -1,7 +1,6 @@ #include "debugger_memorytex.h" #include "gfx/GLStateCache.h" #include "gfx/gl_common.h" -#include "gfx/gl_lost_manager.h" #include "ui_debugger_memorytex.h" #include "Core/MemMap.h" #include diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index a28ddf9b2e..83944908ea 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1163,24 +1163,6 @@ void EmuScreen::renderUI() { screenManager()->getUIContext()->End(); } -void EmuScreen::deviceLost() { - ILOG("EmuScreen::deviceLost()"); - if (gpu) - gpu->DeviceLost(); - else - ILOG("No gpu to deviceLost!"); -} - -void EmuScreen::deviceRestore() { - ILOG("EmuScreen::deviceRestore()"); - if (gpu) - gpu->DeviceRestore(); - else - ILOG("No gpu to deviceRestore!"); - - RecreateViews(); -} - void EmuScreen::autoLoad() { //check if save state has save, if so, load int lastSlot = SaveState::GetNewestSlot(gamePath_); diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 17ddb9b9aa..6cf8384294 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -40,8 +40,6 @@ public: void render() override; void preRender() override; void postRender() override; - void deviceLost() override; - void deviceRestore() override; void dialogFinished(const Screen *dialog, DialogResult result) override; void sendMessage(const char *msg, const char *value) override; void resized() override; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 505ffa3d36..78918c57e2 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -52,7 +52,6 @@ #include "net/resolve.h" #include "gfx_es2/draw_text.h" #include "gfx_es2/gpu_features.h" -#include "gfx/gl_lost_manager.h" #include "i18n/i18n.h" #include "input/input_state.h" #include "math/fast/fast_math.h" @@ -559,9 +558,6 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch // We do this here, instead of in NativeInitGraphics, because the display may be reset. // When it's reset we don't want to forget all our managed things. SetGPUBackend((GPUBackend) g_Config.iGPUBackend); - if (GetGPUBackend() == GPUBackend::OPENGL) { - gl_lost_manager_init(); - } // Must be done restarting by now. restarting = false; @@ -694,12 +690,18 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) { g_gameInfoCache = new GameInfoCache(); + if (gpu) + gpu->DeviceRestore(); + g_graphicsInited = true; ILOG("NativeInitGraphics completed"); return true; } void NativeShutdownGraphics() { + if (gpu) + gpu->DeviceLost(); + g_graphicsInited = false; ILOG("NativeShutdownGraphics"); @@ -860,15 +862,17 @@ void NativeRender(GraphicsContext *graphicsContext) { #endif } + // Test lost/restore on PC +#if 0 + if (gpu) { + gpu->DeviceLost(); + gpu->DeviceRestore(); + } +#endif + graphicsContext->Resize(); screenManager->resized(); - // Do not enable unless you are testing device-loss on Windows -#if 0 - screenManager->deviceLost(); - screenManager->deviceRestore(); -#endif - // TODO: Move this to new GraphicsContext objects for each backend. #ifndef _WIN32 if (GetGPUBackend() == GPUBackend::OPENGL) { @@ -951,26 +955,6 @@ void NativeUpdate() { screenManager->update(); } -void NativeDeviceLost() { - ILOG("NativeDeviceLost"); - // We start by calling gl_lost - this lets objects zero their native GL objects - // so they then don't try to delete them as well. - if (GetGPUBackend() == GPUBackend::OPENGL) { - gl_lost(); - } - if (g_gameInfoCache) - g_gameInfoCache->Clear(); - screenManager->deviceLost(); -} - -void NativeDeviceRestore() { - ILOG("NativeDeviceRestore"); - if (GetGPUBackend() == GPUBackend::OPENGL) { - gl_restore(); - } - screenManager->deviceRestore(); -} - bool NativeIsAtTopLevel() { Screen *currentScreen = screenManager->topScreen(); if (currentScreen) { @@ -1127,9 +1111,6 @@ void NativeShutdown() { screenManager = nullptr; host->ShutdownGraphics(); - if (GetGPUBackend() == GPUBackend::OPENGL) { - gl_lost_manager_shutdown(); - } #if !PPSSPP_PLATFORM(UWP) delete host; diff --git a/UI/TextureUtil.h b/UI/TextureUtil.h index 180d764727..28a28b69d3 100644 --- a/UI/TextureUtil.h +++ b/UI/TextureUtil.h @@ -4,7 +4,6 @@ #include "thin3d/thin3d.h" #include "Core/Config.h" -#include "gfx/gl_lost_manager.h" enum ImageFileType { PNG, @@ -14,36 +13,14 @@ enum ImageFileType { TYPE_UNKNOWN, }; -class ManagedTexture : public GfxResourceHolder { +class ManagedTexture { public: ManagedTexture(Draw::DrawContext *draw) : draw_(draw) { - if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) - register_gl_resource_holder(this, "managed_texture", 0); } ~ManagedTexture() { - if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) - unregister_gl_resource_holder(this); if (texture_) texture_->Release(); } - void GLLost() override { - if (texture_) - texture_->Release(); - texture_ = nullptr; - } - void GLRestore() override { - if (!filename_.empty()) { - if (LoadFromFile(filename_.c_str())) { - ILOG("Reloaded lost texture %s", filename_.c_str()); - } - else { - ELOG("Failed to reload lost texture %s", filename_.c_str()); - } - } - else { - WLOG("Texture cannot be restored - has no filename"); - } - } bool LoadFromFile(const std::string &filename, ImageFileType type = ImageFileType::DETECT, bool generateMips = false); bool LoadFromFileData(const uint8_t *data, size_t dataSize, ImageFileType type = ImageFileType::DETECT, bool generateMips = false); diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 14b807f36b..5c44abb5a6 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -437,7 +437,6 @@ static float dp_xscale = 1.0f; static float dp_yscale = 1.0f; static bool renderer_inited = false; -static bool renderer_ever_inited = false; static bool sustainedPerfSupported = false; // See NativeQueryConfig("androidJavaGL") to change this value. @@ -609,7 +608,6 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init PROFILE_INIT(); renderer_inited = false; - renderer_ever_inited = false; androidVersion = jAndroidVersion; deviceType = jdeviceType; @@ -748,16 +746,16 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, if (renderer_inited) { ILOG("NativeApp.displayInit() restoring"); - NativeDeviceLost(); NativeShutdownGraphics(); - NativeDeviceRestore(); + delete graphicsContext; + + graphicsContext = new AndroidJavaEGLGraphicsContext(); NativeInitGraphics(graphicsContext); ILOG("Restored."); } else { ILOG("NativeApp.displayInit() first time"); NativeInitGraphics(graphicsContext); renderer_inited = true; - renderer_ever_inited = true; } NativeMessageReceived("recreateviews", ""); @@ -1150,13 +1148,9 @@ retry: return false; } - if (!exitRenderLoop && !renderer_inited) { + if (!exitRenderLoop) { NativeInitGraphics(graphicsContext); - if (renderer_ever_inited) { - NativeDeviceRestore(); - } renderer_inited = true; - renderer_ever_inited = true; } while (!exitRenderLoop) { @@ -1180,8 +1174,7 @@ retry: if (g_gameInfoCache) g_gameInfoCache->WorkQueue()->Flush(); - if (renderer_inited) - NativeDeviceLost(); + NativeShutdownGraphics(); renderer_inited = false; ILOG("Shutting down graphics context."); diff --git a/ext/native/Android.mk b/ext/native/Android.mk index 955fd84d87..5656512d81 100644 --- a/ext/native/Android.mk +++ b/ext/native/Android.mk @@ -77,7 +77,6 @@ LOCAL_SRC_FILES :=\ gfx_es2/draw_text_android.cpp.arm \ gfx/GLStateCache.cpp.arm \ gfx/gl_debug_log.cpp \ - gfx/gl_lost_manager.cpp \ gfx/texture_atlas.cpp \ image/zim_load.cpp \ image/zim_save.cpp \ diff --git a/ext/native/base/NativeApp.h b/ext/native/base/NativeApp.h index a4540dd869..69bdf90b91 100644 --- a/ext/native/base/NativeApp.h +++ b/ext/native/base/NativeApp.h @@ -51,13 +51,6 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch // Should not initialize anything screen-size-dependent - do that in NativeResized. bool NativeInitGraphics(GraphicsContext *graphicsContext); -// Signals that you need to forget all buffered OpenGL resources, -// like textures, vbo etc. -void NativeDeviceLost(); - -// Signals that it's time to recreate buffered OpenGL resources -void NativeDeviceRestore(); - // If you want to change DPI stuff (such as modifying dp_xres and dp_yres), this is the // place to do it. You should only read g_dpi_scale and pixel_xres and pixel_yres in this, // and only write dp_xres and dp_yres. diff --git a/ext/native/gfx/gl_lost_manager.cpp b/ext/native/gfx/gl_lost_manager.cpp deleted file mode 100644 index dd83c406e5..0000000000 --- a/ext/native/gfx/gl_lost_manager.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include - -#include "base/basictypes.h" -#include "base/logging.h" -#include "gfx/gl_lost_manager.h" - -struct Holder { - GfxResourceHolder *holder; - const char *desc; - int priority; -}; - -static std::mutex mutex; -std::vector *holders; - -static bool inLost; -static bool inRestore; -static int g_max_priority = 0; - -void register_gl_resource_holder(GfxResourceHolder *holder, const char *desc, int priority) { - std::lock_guard lock(mutex); - if (inLost || inRestore) { - FLOG("BAD: Should not call register_gl_resource_holder from lost/restore path"); - return; - } - if (holders) { - holders->push_back({ holder, desc, priority }); - if (g_max_priority < priority) - g_max_priority = priority; - } else { - WLOG("GL resource holder not initialized, cannot register resource"); - } -} - -void unregister_gl_resource_holder(GfxResourceHolder *holder) { - std::lock_guard lock(mutex); - if (inLost || inRestore) { - FLOG("BAD: Should not call unregister_gl_resource_holder from lost/restore path"); - return; - } - if (holders) { - bool erased = false; - for (size_t i = 0; i < holders->size(); i++) { - if ((*holders)[i].holder == holder) { - if (erased) { - ELOG("GL object double-registered!"); - } - holders->erase(holders->begin() + i); - erased = true; - } - } - if (!erased) { - WLOG("unregister_gl_resource_holder: Resource not registered"); - } - } else { - WLOG("GL resource holder not initialized or already shutdown, cannot unregister resource"); - } -} - -void gl_restore() { - std::lock_guard lock(mutex); - inRestore = true; - if (!holders) { - WLOG("GL resource holder not initialized, cannot process restore request"); - inRestore = false; - return; - } - - ILOG("gl_restore() restoring %d items:", (int)holders->size()); - for (int p = 0; p <= g_max_priority; p++) { - for (size_t i = 0; i < holders->size(); i++) { - if ((*holders)[i].priority == p) { - ILOG("GLRestore(%d / %d, %s, prio %d)", (int)(i + 1), (int)holders->size(), - (*holders)[i].desc, (*holders)[i].priority); - (*holders)[i].holder->GLRestore(); - } - } - } - ILOG("gl_restore() completed on %d items:", (int)holders->size()); - inRestore = false; -} - -void gl_lost() { - std::lock_guard lock(mutex); - inLost = true; - if (!holders) { - WLOG("GL resource holder not initialized, cannot process restore request"); - inLost = false; - return; - } - - ILOG("gl_lost() clearing %i items:", (int)holders->size()); - for (int p = g_max_priority; p >= 0; p--) { - for (size_t i = 0; i < holders->size(); i++) { - if ((*holders)[i].priority == p) { - ILOG("gl_lost(%d / %d, %s, prio %d)", (int) (i + 1), (int) holders->size(), - (*holders)[i].desc, (*holders)[i].priority); - (*holders)[i].holder->GLLost(); - } - } - } - ILOG("gl_lost() completed on %i items:", (int)holders->size()); - inLost = false; -} - -void gl_lost_manager_init() { - std::lock_guard lock(mutex); - if (holders) { - FLOG("Double GL lost manager init"); - // Dead here (FLOG), no need to delete holders - } - g_max_priority = 0; - holders = new std::vector(); -} - -void gl_lost_manager_shutdown() { - std::lock_guard lock(mutex); - if (!holders) { - FLOG("Lost manager already shutdown"); - } else if (holders->size() > 0) { - ELOG("Lost manager shutdown with %i objects still registered", (int)holders->size()); - for (size_t i = 0; i < holders->size(); i++) { - ELOG(" (%d / %d, %s, prio %d)", (int)(i + 1), (int)holders->size(), - (*holders)[i].desc, (*holders)[i].priority); - } - } - - delete holders; - holders = 0; -} \ No newline at end of file diff --git a/ext/native/gfx/gl_lost_manager.h b/ext/native/gfx/gl_lost_manager.h deleted file mode 100644 index 15a7704fb3..0000000000 --- a/ext/native/gfx/gl_lost_manager.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -// 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. - -// For code simplicity, it may be a good idea to manually tear down and recreate everything. Even in this case, -// it's important to use this to zero out resource handles in GLLost() - gl_lost should be called before you -// tear things down, so then you can check if handles are zero and avoid deleting resources that are already gone. - -class GfxResourceHolder { -public: - virtual ~GfxResourceHolder() {} - virtual void GLLost() = 0; - virtual void GLRestore() = 0; -}; - -void gl_lost_manager_init(); -void gl_lost_manager_shutdown(); - -// 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, int priority); -void unregister_gl_resource_holder(GfxResourceHolder *holder); - -// Notifies all objects it's time to forget / delete things. -void gl_lost(); - -// Notifies all objects that it's time to be restored. -void gl_restore(); diff --git a/ext/native/gfx_es2/draw_buffer.h b/ext/native/gfx_es2/draw_buffer.h index d31530fa35..2734d065b2 100644 --- a/ext/native/gfx_es2/draw_buffer.h +++ b/ext/native/gfx_es2/draw_buffer.h @@ -6,7 +6,6 @@ #include "base/basictypes.h" #include "base/colorutil.h" -#include "gfx/gl_lost_manager.h" #include "gfx/texture_atlas.h" #include "math/geom2d.h" #include "math/lin/matrix4x4.h" diff --git a/ext/native/gfx_es2/glsl_program.cpp b/ext/native/gfx_es2/glsl_program.cpp index a4e2088500..91ced3dad2 100644 --- a/ext/native/gfx_es2/glsl_program.cpp +++ b/ext/native/gfx_es2/glsl_program.cpp @@ -49,7 +49,6 @@ GLSLProgram *glsl_create(const char *vshader, const char *fshader, std::string * delete program; return 0; } - register_gl_resource_holder(program, "glsl_program", 0); return program; } @@ -70,7 +69,6 @@ GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src delete program; return 0; } - register_gl_resource_holder(program, "glsl_program_src", 0); return program; } @@ -220,23 +218,6 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) { return true; } -void GLSLProgram::GLLost() { - // Quoth http://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer.html: - // "Note that when the EGL context is lost, all OpenGL resources associated with that context will be automatically deleted. - // You do not need to call the corresponding "glDelete" methods such as glDeleteTextures to manually delete these lost resources." - program_ = 0; - vsh_ = 0; - fsh_ = 0; -} - -void GLSLProgram::GLRestore() { - ILOG("Restoring GLSL program %s/%s", - strlen(this->vshader_filename) > 0 ? this->vshader_filename : "(mem)", - strlen(this->fshader_filename) > 0 ? this->fshader_filename : "(mem)"); - glsl_recompile(this); - // Note that any shader uniforms are still lost, hopefully the client sets them every frame at a minimum... -} - int glsl_attrib_loc(const GLSLProgram *program, const char *name) { return glGetAttribLocation(program->program_, name); } @@ -247,7 +228,6 @@ int glsl_uniform_loc(const GLSLProgram *program, const char *name) { void glsl_destroy(GLSLProgram *program) { if (program) { - unregister_gl_resource_holder(program); glDeleteShader(program->vsh_); glDeleteShader(program->fsh_); glDeleteProgram(program->program_); diff --git a/ext/native/gfx_es2/glsl_program.h b/ext/native/gfx_es2/glsl_program.h index 5db3c37d3b..e2efd2a3d7 100644 --- a/ext/native/gfx_es2/glsl_program.h +++ b/ext/native/gfx_es2/glsl_program.h @@ -7,13 +7,12 @@ #include #include -#include "gfx/gl_lost_manager.h" #include "gfx/gl_common.h" // Represent a compiled and linked vshader/fshader pair. // A just-constructed object is valid but cannot be used as a shader program, meaning that // yes, you can declare these as globals if you like. -struct GLSLProgram : public GfxResourceHolder { +struct GLSLProgram { char name[16]; char vshader_filename[256]; char fshader_filename[256]; @@ -42,9 +41,6 @@ struct GLSLProgram : public GfxResourceHolder { GLuint vsh_; GLuint fsh_; GLuint program_; - - void GLLost() override; - void GLRestore() override; }; // C API, old skool. Not much point either... diff --git a/ext/native/native.vcxproj b/ext/native/native.vcxproj index 751ab22e99..ba0d1d399a 100644 --- a/ext/native/native.vcxproj +++ b/ext/native/native.vcxproj @@ -234,7 +234,6 @@ - @@ -693,7 +692,6 @@ - diff --git a/ext/native/native.vcxproj.filters b/ext/native/native.vcxproj.filters index 73e468f8d9..60c65f1746 100644 --- a/ext/native/native.vcxproj.filters +++ b/ext/native/native.vcxproj.filters @@ -74,9 +74,6 @@ base - - gfx - gfx @@ -370,9 +367,6 @@ file - - gfx - gfx diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index db6dac8138..033a787238 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -13,7 +13,6 @@ #include "gfx/gl_debug_log.h" #include "gfx/GLStateCache.h" #include "gfx_es2/gpu_features.h" -#include "gfx/gl_lost_manager.h" #ifdef IOS extern void bindDefaultFBO(); @@ -274,11 +273,10 @@ GLuint ShaderStageToOpenGL(ShaderStage stage) { } } -class OpenGLShaderModule : public ShaderModule, public GfxResourceHolder { +class OpenGLShaderModule : public ShaderModule { public: OpenGLShaderModule(ShaderStage stage) : stage_(stage) { ILOG("Shader module created (%p)", this); - register_gl_resource_holder(this, "drawcontext_shader_module", 0); glstage_ = ShaderStageToOpenGL(stage); } @@ -286,7 +284,6 @@ public: ILOG("Shader module destroyed (%p)", this); if (shader_) glDeleteShader(shader_); - unregister_gl_resource_holder(this); } bool Compile(ShaderLanguage language, const uint8_t *data, size_t dataSize); @@ -302,19 +299,6 @@ public: return stage_; } - void GLLost() override { - ILOG("Shader module lost"); - // Shader has been destroyed since the old context is gone, so let's zero it. - shader_ = 0; - } - - void GLRestore() override { - ILOG("Shader module being restored"); - if (!Compile(language_, (const uint8_t *)source_.data(), source_.size())) { - ELOG("Shader restore compilation failed: %s", source_.c_str()); - } - } - private: ShaderStage stage_; ShaderLanguage language_; @@ -355,15 +339,13 @@ bool OpenGLShaderModule::Compile(ShaderLanguage language, const uint8_t *data, s return ok_; } -class OpenGLInputLayout : public InputLayout, GfxResourceHolder { +class OpenGLInputLayout : public InputLayout { public: ~OpenGLInputLayout(); void Apply(const void *base = nullptr); void Unapply(); void Compile(); - void GLRestore() override; - void GLLost() override; bool RequiresBuffer() { return id_ != 0; } @@ -381,15 +363,12 @@ struct UniformInfo { int loc_; }; -class OpenGLPipeline : public Pipeline, GfxResourceHolder { +class OpenGLPipeline : public Pipeline { public: OpenGLPipeline() { program_ = 0; - // Priority 1 so this gets restored after the shaders. - register_gl_resource_holder(this, "drawcontext_pipeline", 1); } ~OpenGLPipeline() { - unregister_gl_resource_holder(this); for (auto &iter : shaders) { iter->Release(); } @@ -404,15 +383,6 @@ public: int GetUniformLoc(const char *name); - void GLLost() override { - program_ = 0; - } - - void GLRestore() override { - // Shaders will have been restored before the pipeline. - LinkShaders(); - } - bool RequiresBuffer() override { return inputLayout->RequiresBuffer(); } @@ -751,25 +721,11 @@ void OpenGLTexture::AutoGenMipmaps() { } } -class OpenGLFramebuffer : public Framebuffer, public GfxResourceHolder { +class OpenGLFramebuffer : public Framebuffer { public: - OpenGLFramebuffer() { - register_gl_resource_holder(this, "framebuffer", 0); - } + OpenGLFramebuffer() {} ~OpenGLFramebuffer(); - void GLLost() override { - handle = 0; - color_texture = 0; - z_stencil_buffer = 0; - z_buffer = 0; - stencil_buffer = 0; - } - - void GLRestore() override { - ELOG("Restoring framebuffers not yet implemented"); - } - GLuint handle = 0; GLuint color_texture = 0; GLuint z_stencil_buffer = 0; // Either this is set, or the two below. @@ -993,14 +949,6 @@ void OpenGLInputLayout::Compile() { lastBase_ = -1; } -void OpenGLInputLayout::GLLost() { - id_ = 0; -} - -void OpenGLInputLayout::GLRestore() { - Compile(); -} - DepthStencilState *OpenGLContext::CreateDepthStencilState(const DepthStencilStateDesc &desc) { OpenGLDepthStencilState *ds = new OpenGLDepthStencilState(); ds->depthTestEnabled = desc.depthTestEnabled; @@ -1077,7 +1025,7 @@ RasterState *OpenGLContext::CreateRasterState(const RasterStateDesc &desc) { return rs; } -class OpenGLBuffer : public Buffer, GfxResourceHolder { +class OpenGLBuffer : public Buffer { public: OpenGLBuffer(size_t size, uint32_t flags) { glGenBuffers(1, &buffer_); @@ -1090,10 +1038,8 @@ public: totalSize_ = size; glBindBuffer(target_, buffer_); glBufferData(target_, size, NULL, usage_); - register_gl_resource_holder(this, "drawcontext_buffer", 0); } ~OpenGLBuffer() override { - unregister_gl_resource_holder(this); glDeleteBuffers(1, &buffer_); } @@ -1102,16 +1048,6 @@ public: glBindBuffer(target_, buffer_); } - void GLLost() override { - buffer_ = 0; - } - - void GLRestore() override { - ILOG("Recreating vertex buffer after gl_restore"); - totalSize_ = 0; // Will cause a new glBufferData call. Should genBuffers again though? - glGenBuffers(1, &buffer_); - } - GLuint buffer_; GLuint target_; GLuint usage_; @@ -1847,7 +1783,6 @@ void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBCh } OpenGLFramebuffer::~OpenGLFramebuffer() { - unregister_gl_resource_holder(this); CHECK_GL_ERROR_IF_DEBUG(); if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { if (handle) { diff --git a/ext/native/ui/screen.cpp b/ext/native/ui/screen.cpp index c95c2b763f..f9cc2cf7eb 100644 --- a/ext/native/ui/screen.cpp +++ b/ext/native/ui/screen.cpp @@ -152,22 +152,6 @@ void ScreenManager::sendMessage(const char *msg, const char *value) { stack_.back().screen->sendMessage(msg, value); } -void ScreenManager::deviceLost() { - for (size_t i = 0; i < stack_.size(); i++) { - stack_[i].screen->deviceLost(); - } - // Dialogs too? Nah, they should only use the standard UI texture anyway. - // TODO: Change this when it becomes necessary. -} - -void ScreenManager::deviceRestore() { - for (size_t i = 0; i < stack_.size(); i++) { - stack_[i].screen->deviceRestore(); - } - // Dialogs too? Nah, they should only use the standard UI texture anyway. - // TODO: Change this when it becomes necessary. -} - Screen *ScreenManager::topScreen() const { if (!stack_.empty()) return stack_.back().screen; diff --git a/ext/native/ui/screen.h b/ext/native/ui/screen.h index db132c0dfa..7d09c23d80 100644 --- a/ext/native/ui/screen.h +++ b/ext/native/ui/screen.h @@ -52,8 +52,6 @@ public: virtual void preRender() {} virtual void render() {} virtual void postRender() {} - virtual void deviceLost() {} - virtual void deviceRestore() {} virtual void resized() {} virtual void dialogFinished(const Screen *dialog, DialogResult result) {} virtual bool touch(const TouchInput &touch) { return false; } @@ -115,8 +113,6 @@ public: void render(); void resized(); - void deviceLost(); - void deviceRestore(); void shutdown(); // Push a dialog box in front. Currently 1-level only. diff --git a/headless/SDLHeadlessHost.cpp b/headless/SDLHeadlessHost.cpp index 90c05dbc74..1176bef1e2 100644 --- a/headless/SDLHeadlessHost.cpp +++ b/headless/SDLHeadlessHost.cpp @@ -20,7 +20,6 @@ #include #include #include -#include "gfx/gl_lost_manager.h" #include "headless/SDLHeadlessHost.h" @@ -114,8 +113,6 @@ bool SDLHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext * } #endif - gl_lost_manager_init(); - GraphicsContext *graphicsContext = new GLDummyGraphicsContext(); *ctx = graphicsContext; gfx_ = graphicsContext; @@ -134,8 +131,6 @@ void SDLHeadlessHost::ShutdownGraphics() { glContext_ = nullptr; SDL_DestroyWindow(screen_); screen_ = nullptr; - - gl_lost_manager_shutdown(); } void SDLHeadlessHost::SwapBuffers() {