diff options
author | Jesse Talavera-Greenberg <jesse@jesse.tg> | 2023-09-15 09:31:05 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-15 15:31:05 +0200 |
commit | db963aa002cdf943c86d19f8abd3f4fd40be38ec (patch) | |
tree | bded72c0147f3749d3f346266ed4b1321e3b2979 /src | |
parent | 1aaf22d181e55abb8ad27be89ebae106b1c1cfcf (diff) |
Make the NDS teardown more robust (#1798)
* Make cleanup a little more robust to mitigate undefined behavior
- Add some null checks before cleaning up the GPU3D renderer
- Make sure that all deleted objects are null
- Move cleanup logic out of an assert call
- Note that deleting a null pointer is a no-op, so there's no need to check for null beforehand
- Use RAII for GLCompositor instead of Init/DeInit methods
* Replace a DeInit call that I missed
* Make ARMJIT_Memory less likely to generate errors
- Set FastMem7/9Start to nullptr at the end
- Only close and unmap the file if it's initialized
* Make Renderer3D manage its resources with RAII
* Don't try to deallocate frontend resources that aren't loaded
* Make ARMJIT_Memory::DeInit more robust on the Switch
* Reset MemoryFile on Windows to INVALID_HANDLE_VALUE, not nullptr
- There is a difference
* Don't explicitly store a Valid state in GLCompositor or the 3D renderers
- Instead, create them with static methods while making the actual constructors private
* Make initialization of OpenGL resources fail if OpenGL isn't loaded
* assert that OpenGL is loaded instead of returning failure
Diffstat (limited to 'src')
-rw-r--r-- | src/ARMJIT.cpp | 1 | ||||
-rw-r--r-- | src/ARMJIT_Memory.cpp | 49 | ||||
-rw-r--r-- | src/DSi.cpp | 12 | ||||
-rw-r--r-- | src/DSi_Camera.cpp | 3 | ||||
-rw-r--r-- | src/GPU.cpp | 28 | ||||
-rw-r--r-- | src/GPU3D.h | 7 | ||||
-rw-r--r-- | src/GPU3D_OpenGL.cpp | 204 | ||||
-rw-r--r-- | src/GPU3D_OpenGL.h | 61 | ||||
-rw-r--r-- | src/GPU3D_Soft.cpp | 11 | ||||
-rw-r--r-- | src/GPU3D_Soft.h | 6 | ||||
-rw-r--r-- | src/GPU_OpenGL.cpp | 61 | ||||
-rw-r--r-- | src/GPU_OpenGL.h | 15 | ||||
-rw-r--r-- | src/NDS.cpp | 6 | ||||
-rw-r--r-- | src/OpenGLSupport.cpp | 22 | ||||
-rw-r--r-- | src/SPI.cpp | 1 | ||||
-rw-r--r-- | src/SPU.cpp | 6 | ||||
-rw-r--r-- | src/frontend/qt_sdl/AudioInOut.cpp | 9 | ||||
-rw-r--r-- | src/frontend/qt_sdl/LocalMP.cpp | 21 |
18 files changed, 313 insertions, 210 deletions
diff --git a/src/ARMJIT.cpp b/src/ARMJIT.cpp index 7a4cdc6..77bb50d 100644 --- a/src/ARMJIT.cpp +++ b/src/ARMJIT.cpp @@ -330,6 +330,7 @@ void DeInit() ARMJIT_Memory::DeInit(); delete JITCompiler; + JITCompiler = nullptr; } void Reset() diff --git a/src/ARMJIT_Memory.cpp b/src/ARMJIT_Memory.cpp index 8e6a9f6..25652cb 100644 --- a/src/ARMJIT_Memory.cpp +++ b/src/ARMJIT_Memory.cpp @@ -308,7 +308,7 @@ HANDLE MemoryFile; LPVOID ExceptionHandlerHandle; #else u8* MemoryBase; -int MemoryFile; +int MemoryFile = -1; #endif bool MapIntoRange(u32 addr, u32 num, u32 offset, u32 size) @@ -811,25 +811,58 @@ void DeInit() { #if defined(__SWITCH__) virtmemLock(); - virtmemRemoveReservation(FastMem9Reservation); - virtmemRemoveReservation(FastMem7Reservation); + if (FastMem9Reservation) + virtmemRemoveReservation(FastMem9Reservation); + + if (FastMem7Reservation) + virtmemRemoveReservation(FastMem7Reservation); + + FastMem9Reservation = nullptr; + FastMem7Reservation = nullptr; virtmemUnlock(); svcUnmapProcessCodeMemory(envGetOwnProcessHandle(), (u64)MemoryBaseCodeMem, (u64)MemoryBase, MemoryTotalSize); free(MemoryBase); + MemoryBase = nullptr; #elif defined(_WIN32) - assert(UnmapViewOfFile(MemoryBase)); - CloseHandle(MemoryFile); + if (MemoryBase) + { + bool viewUnmapped = UnmapViewOfFile(MemoryBase); + assert(viewUnmapped); + MemoryBase = nullptr; + FastMem9Start = nullptr; + FastMem7Start = nullptr; + } + + if (MemoryFile) + { + CloseHandle(MemoryFile); + MemoryFile = INVALID_HANDLE_VALUE; + } - RemoveVectoredExceptionHandler(ExceptionHandlerHandle); + if (ExceptionHandlerHandle) + { + RemoveVectoredExceptionHandler(ExceptionHandlerHandle); + ExceptionHandlerHandle = nullptr; + } #else sigaction(SIGSEGV, &OldSaSegv, nullptr); #ifdef __APPLE__ sigaction(SIGBUS, &OldSaBus, nullptr); #endif + if (MemoryBase) + { + munmap(MemoryBase, MemoryTotalSize); + MemoryBase = nullptr; + FastMem9Start = nullptr; + FastMem7Start = nullptr; + } - munmap(MemoryBase, MemoryTotalSize); - close(MemoryFile); + if (MemoryFile >= 0) + { + close(MemoryFile); + MemoryFile = -1; + } #if defined(__ANDROID__) if (Libandroid) diff --git a/src/DSi.cpp b/src/DSi.cpp index dc066a7..5dd8ac9 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -128,6 +128,10 @@ void DeInit() delete[] NWRAM_A; delete[] NWRAM_B; delete[] NWRAM_C; + + NWRAM_A = nullptr; + NWRAM_B = nullptr; + NWRAM_C = nullptr; #endif DSi_I2C::DeInit(); @@ -135,10 +139,16 @@ void DeInit() DSi_AES::DeInit(); DSi_DSP::DeInit(); - for (int i = 0; i < 8; i++) delete NDMAs[i]; + for (int i = 0; i < 8; i++) + { + delete NDMAs[i]; + NDMAs[i] = nullptr; + } delete SDMMC; + SDMMC = nullptr; delete SDIO; + SDIO = nullptr; } void Reset() diff --git a/src/DSi_Camera.cpp b/src/DSi_Camera.cpp index 9f45a6a..c5fa29d 100644 --- a/src/DSi_Camera.cpp +++ b/src/DSi_Camera.cpp @@ -63,6 +63,9 @@ void DeInit() { delete Camera0; delete Camera1; + + Camera0 = nullptr; + Camera1 = nullptr; } void Reset() diff --git a/src/GPU.cpp b/src/GPU.cpp index f51748b..077fc8b 100644 --- a/src/GPU.cpp +++ b/src/GPU.cpp @@ -171,6 +171,11 @@ void DeInit() if (Framebuffer[0][1]) delete[] Framebuffer[0][1]; if (Framebuffer[1][0]) delete[] Framebuffer[1][0]; if (Framebuffer[1][1]) delete[] Framebuffer[1][1]; + + Framebuffer[0][0] = nullptr; + Framebuffer[0][1] = nullptr; + Framebuffer[1][0] = nullptr; + Framebuffer[1][1] = nullptr; } void ResetVRAMCache() @@ -388,20 +393,18 @@ void InitRenderer(int renderer) #ifdef OGLRENDERER_ENABLED if (renderer == 1) { - CurGLCompositor = std::make_unique<GLCompositor>(); - // Create opengl rendrerer - if (!CurGLCompositor->Init()) + CurGLCompositor = GLCompositor::New(); + // Create opengl renderer + if (!CurGLCompositor) { // Fallback on software renderer renderer = 0; GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>(); - GPU3D::CurrentRenderer->Init(); } - GPU3D::CurrentRenderer = std::make_unique<GPU3D::GLRenderer>(); - if (!GPU3D::CurrentRenderer->Init()) + GPU3D::CurrentRenderer = GPU3D::GLRenderer::New(); + if (!GPU3D::CurrentRenderer) { // Fallback on software renderer - CurGLCompositor->DeInit(); CurGLCompositor.reset(); renderer = 0; GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>(); @@ -411,7 +414,6 @@ void InitRenderer(int renderer) #endif { GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>(); - GPU3D::CurrentRenderer->Init(); } Renderer = renderer; @@ -419,12 +421,12 @@ void InitRenderer(int renderer) void DeInitRenderer() { - GPU3D::CurrentRenderer->DeInit(); + // Delete the 3D renderer, if it exists + GPU3D::CurrentRenderer.reset(); + #ifdef OGLRENDERER_ENABLED - if (Renderer == 1) - { - CurGLCompositor->DeInit(); - } + // Delete the compositor, if one exists + CurGLCompositor.reset(); #endif } diff --git a/src/GPU3D.h b/src/GPU3D.h index 4a7bfdc..44d422a 100644 --- a/src/GPU3D.h +++ b/src/GPU3D.h @@ -137,14 +137,11 @@ void Write32(u32 addr, u32 val); class Renderer3D { public: - Renderer3D(bool Accelerated); - virtual ~Renderer3D() {}; + virtual ~Renderer3D() = default; Renderer3D(const Renderer3D&) = delete; Renderer3D& operator=(const Renderer3D&) = delete; - virtual bool Init() = 0; - virtual void DeInit() = 0; virtual void Reset() = 0; // This "Accelerated" flag currently communicates if the framebuffer should @@ -159,6 +156,8 @@ public: virtual void RenderFrame() = 0; virtual void RestartFrame() {}; virtual u32* GetLine(int line) = 0; +protected: + Renderer3D(bool Accelerated); }; extern int Renderer; diff --git a/src/GPU3D_OpenGL.cpp b/src/GPU3D_OpenGL.cpp index ebabd51..9648be3 100644 --- a/src/GPU3D_OpenGL.cpp +++ b/src/GPU3D_OpenGL.cpp @@ -18,6 +18,7 @@ #include "GPU3D_OpenGL.h" +#include <assert.h> #include <stdio.h> #include <string.h> #include "NDS.h" @@ -96,14 +97,20 @@ void SetupDefaultTexParams(GLuint tex) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } -GLRenderer::GLRenderer() - : Renderer3D(true) +GLRenderer::GLRenderer() noexcept : Renderer3D(true) { + // GLRenderer::New() will be used to actually initialize the renderer; + // The various glDelete* functions silently ignore invalid IDs, + // so we can just let the destructor clean up a half-initialized renderer. } -bool GLRenderer::Init() +std::unique_ptr<GLRenderer> GLRenderer::New() noexcept { - GLint uni_id; + assert(glEnable != nullptr); + + // Will be returned if the initialization succeeds, + // or cleaned up via RAII if it fails. + std::unique_ptr<GLRenderer> result = std::unique_ptr<GLRenderer>(new GLRenderer()); glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); @@ -112,86 +119,93 @@ bool GLRenderer::Init() glClearDepth(1.0); - if (!OpenGL::BuildShaderProgram(kClearVS, kClearFS, ClearShaderPlain, "ClearShader")) - return false; + if (!OpenGL::BuildShaderProgram(kClearVS, kClearFS, result->ClearShaderPlain, "ClearShader")) + return nullptr; - glBindAttribLocation(ClearShaderPlain[2], 0, "vPosition"); - glBindFragDataLocation(ClearShaderPlain[2], 0, "oColor"); - glBindFragDataLocation(ClearShaderPlain[2], 1, "oAttr"); + glBindAttribLocation(result->ClearShaderPlain[2], 0, "vPosition"); + glBindFragDataLocation(result->ClearShaderPlain[2], 0, "oColor"); + glBindFragDataLocation(result->ClearShaderPlain[2], 1, "oAttr"); - if (!OpenGL::LinkShaderProgram(ClearShaderPlain)) - return false; + if (!OpenGL::LinkShaderProgram(result->ClearShaderPlain)) + return nullptr; - ClearUniformLoc[0] = glGetUniformLocation(ClearShaderPlain[2], "uColor"); - ClearUniformLoc[1] = glGetUniformLocation(ClearShaderPlain[2], "uDepth"); - ClearUniformLoc[2] = glGetUniformLocation(ClearShaderPlain[2], "uOpaquePolyID"); - ClearUniformLoc[3] = glGetUniformLocation(ClearShaderPlain[2], "uFogFlag"); - - memset(RenderShader, 0, sizeof(RenderShader)); - - if (!BuildRenderShader(0, - kRenderVS_Z, kRenderFS_ZO)) return false; - if (!BuildRenderShader(RenderFlag_WBuffer, - kRenderVS_W, kRenderFS_WO)) return false; - if (!BuildRenderShader(RenderFlag_Edge, - kRenderVS_Z, kRenderFS_ZE)) return false; - if (!BuildRenderShader(RenderFlag_Edge | RenderFlag_WBuffer, - kRenderVS_W, kRenderFS_WE)) return false; - if (!BuildRenderShader(RenderFlag_Trans, - kRenderVS_Z, kRenderFS_ZT)) return false; - if (!BuildRenderShader(RenderFlag_Trans | RenderFlag_WBuffer, - kRenderVS_W, kRenderFS_WT)) return false; - if (!BuildRenderShader(RenderFlag_ShadowMask, - kRenderVS_Z, kRenderFS_ZSM)) return false; - if (!BuildRenderShader(RenderFlag_ShadowMask | RenderFlag_WBuffer, - kRenderVS_W, kRenderFS_WSM)) return false; - - - if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassEdgeFS, FinalPassEdgeShader, "FinalPassEdgeShader")) - return false; - if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassFogFS, FinalPassFogShader, "FinalPassFogShader")) - return false; + result->ClearUniformLoc[0] = glGetUniformLocation(result->ClearShaderPlain[2], "uColor"); + result->ClearUniformLoc[1] = glGetUniformLocation(result->ClearShaderPlain[2], "uDepth"); + result->ClearUniformLoc[2] = glGetUniformLocation(result->ClearShaderPlain[2], "uOpaquePolyID"); + result->ClearUniformLoc[3] = glGetUniformLocation(result->ClearShaderPlain[2], "uFogFlag"); - glBindAttribLocation(FinalPassEdgeShader[2], 0, "vPosition"); - glBindFragDataLocation(FinalPassEdgeShader[2], 0, "oColor"); + memset(result->RenderShader, 0, sizeof(RenderShader)); - if (!OpenGL::LinkShaderProgram(FinalPassEdgeShader)) - return false; + if (!result->BuildRenderShader(0, kRenderVS_Z, kRenderFS_ZO)) + return nullptr; + + if (!result->BuildRenderShader(RenderFlag_WBuffer, kRenderVS_W, kRenderFS_WO)) + return nullptr; + + if (!result->BuildRenderShader(RenderFlag_Edge, kRenderVS_Z, kRenderFS_ZE)) + return nullptr; + + if (!result->BuildRenderShader(RenderFlag_Edge | RenderFlag_WBuffer, kRenderVS_W, kRenderFS_WE)) + return nullptr; + + if (!result->BuildRenderShader(RenderFlag_Trans, kRenderVS_Z, kRenderFS_ZT)) + return nullptr; + + if (!result->BuildRenderShader(RenderFlag_Trans | RenderFlag_WBuffer, kRenderVS_W, kRenderFS_WT)) + return nullptr; + + if (!result->BuildRenderShader(RenderFlag_ShadowMask, kRenderVS_Z, kRenderFS_ZSM)) + return nullptr; + + if (!result->BuildRenderShader(RenderFlag_ShadowMask | RenderFlag_WBuffer, kRenderVS_W, kRenderFS_WSM)) + return nullptr; - uni_id = glGetUniformBlockIndex(FinalPassEdgeShader[2], "uConfig"); - glUniformBlockBinding(FinalPassEdgeShader[2], uni_id, 0); + if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassEdgeFS, result->FinalPassEdgeShader, "FinalPassEdgeShader")) + return nullptr; - glUseProgram(FinalPassEdgeShader[2]); + if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassFogFS, result->FinalPassFogShader, "FinalPassFogShader")) + return nullptr; - uni_id = glGetUniformLocation(FinalPassEdgeShader[2], "DepthBuffer"); + glBindAttribLocation(result->FinalPassEdgeShader[2], 0, "vPosition"); + glBindFragDataLocation(result->FinalPassEdgeShader[2], 0, "oColor"); + + if (!OpenGL::LinkShaderProgram(result->FinalPassEdgeShader)) + return nullptr; + + GLint uni_id = glGetUniformBlockIndex(result->FinalPassEdgeShader[2], "uConfig"); + glUniformBlockBinding(result->FinalPassEdgeShader[2], uni_id, 0); + + glUseProgram(result->FinalPassEdgeShader[2]); + + uni_id = glGetUniformLocation(result->FinalPassEdgeShader[2], "DepthBuffer"); glUniform1i(uni_id, 0); - uni_id = glGetUniformLocation(FinalPassEdgeShader[2], "AttrBuffer"); + uni_id = glGetUniformLocation(result->FinalPassEdgeShader[2], "AttrBuffer"); glUniform1i(uni_id, 1); - glBindAttribLocation(FinalPassFogShader[2], 0, "vPosition"); - glBindFragDataLocation(FinalPassFogShader[2], 0, "oColor"); + glBindAttribLocation(result->FinalPassFogShader[2], 0, "vPosition"); + glBindFragDataLocation(result->FinalPassFogShader[2], 0, "oColor"); - if (!OpenGL::LinkShaderProgram(FinalPassFogShader)) - return false; + if (!OpenGL::LinkShaderProgram(result->FinalPassFogShader)) + return nullptr; - uni_id = glGetUniformBlockIndex(FinalPassFogShader[2], "uConfig"); - glUniformBlockBinding(FinalPassFogShader[2], uni_id, 0); + uni_id = glGetUniformBlockIndex(result->FinalPassFogShader[2], "uConfig"); + glUniformBlockBinding(result->FinalPassFogShader[2], uni_id, 0); - glUseProgram(FinalPassFogShader[2]); + glUseProgram(result->FinalPassFogShader[2]); - uni_id = glGetUniformLocation(FinalPassFogShader[2], "DepthBuffer"); + uni_id = glGetUniformLocation(result->FinalPassFogShader[2], "DepthBuffer"); glUniform1i(uni_id, 0); - uni_id = glGetUniformLocation(FinalPassFogShader[2], "AttrBuffer"); + uni_id = glGetUniformLocation(result->FinalPassFogShader[2], "AttrBuffer"); glUniform1i(uni_id, 1); - memset(&ShaderConfig, 0, sizeof(ShaderConfig)); + memset(&result->ShaderConfig, 0, sizeof(ShaderConfig)); - glGenBuffers(1, &ShaderConfigUBO); - glBindBuffer(GL_UNIFORM_BUFFER, ShaderConfigUBO); - static_assert((sizeof(ShaderConfig) & 15) == 0, ""); - glBufferData(GL_UNIFORM_BUFFER, sizeof(ShaderConfig), &ShaderConfig, GL_STATIC_DRAW); - glBindBufferBase(GL_UNIFORM_BUFFER, 0, ShaderConfigUBO); + glGenBuffers(1, &result->ShaderConfigUBO); + glBindBuffer(GL_UNIFORM_BUFFER, result->ShaderConfigUBO); + static_assert((sizeof(ShaderConfig) & 15) == 0); + glBufferData(GL_UNIFORM_BUFFER, sizeof(ShaderConfig), &result->ShaderConfig, GL_STATIC_DRAW); + glBindBufferBase(GL_UNIFORM_BUFFER, 0, result->ShaderConfigUBO); float clearvtx[6*2] = @@ -205,22 +219,22 @@ bool GLRenderer::Init() 1.0, 1.0 }; - glGenBuffers(1, &ClearVertexBufferID); - glBindBuffer(GL_ARRAY_BUFFER, ClearVertexBufferID); + glGenBuffers(1, &result->ClearVertexBufferID); + glBindBuffer(GL_ARRAY_BUFFER, result->ClearVertexBufferID); glBufferData(GL_ARRAY_BUFFER, sizeof(clearvtx), clearvtx, GL_STATIC_DRAW); - glGenVertexArrays(1, &ClearVertexArrayID); - glBindVertexArray(ClearVertexArrayID); + glGenVertexArrays(1, &result->ClearVertexArrayID); + glBindVertexArray(result->ClearVertexArrayID); glEnableVertexAttribArray(0); // position glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0)); - glGenBuffers(1, &VertexBufferID); - glBindBuffer(GL_ARRAY_BUFFER, VertexBufferID); - glBufferData(GL_ARRAY_BUFFER, sizeof(VertexBuffer), NULL, GL_DYNAMIC_DRAW); + glGenBuffers(1, &result->VertexBufferID); + glBindBuffer(GL_ARRAY_BUFFER, result->VertexBufferID); + glBufferData(GL_ARRAY_BUFFER, sizeof(VertexBuffer), nullptr, GL_DYNAMIC_DRAW); - glGenVertexArrays(1, &VertexArrayID); - glBindVertexArray(VertexArrayID); + glGenVertexArrays(1, &result->VertexArrayID); + glBindVertexArray(result->VertexArrayID); glEnableVertexAttribArray(0); // position glVertexAttribIPointer(0, 4, GL_UNSIGNED_SHORT, 7*4, (void*)(0)); glEnableVertexAttribArray(1); // color @@ -230,43 +244,43 @@ bool GLRenderer::Init() glEnableVertexAttribArray(3); // attrib glVertexAttribIPointer(3, 3, GL_UNSIGNED_INT, 7*4, (void*)(4*4)); - glGenBuffers(1, &IndexBufferID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferID); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(IndexBuffer), NULL, GL_DYNAMIC_DRAW); + glGenBuffers(1, &result->IndexBufferID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, result->IndexBufferID); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(IndexBuffer), nullptr, GL_DYNAMIC_DRAW); - glGenFramebuffers(4, &FramebufferID[0]); - glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[0]); + glGenFramebuffers(4, &result->FramebufferID[0]); + glBindFramebuffer(GL_FRAMEBUFFER, result->FramebufferID[0]); - glGenTextures(8, &FramebufferTex[0]); - FrontBuffer = 0; + glGenTextures(8, &result->FramebufferTex[0]); + result->FrontBuffer = 0; // color buffers - SetupDefaultTexParams(FramebufferTex[0]); - SetupDefaultTexParams(FramebufferTex[1]); + SetupDefaultTexParams(result->FramebufferTex[0]); + SetupDefaultTexParams(result->FramebufferTex[1]); // depth/stencil buffer - SetupDefaultTexParams(FramebufferTex[4]); - SetupDefaultTexParams(FramebufferTex[6]); + SetupDefaultTexParams(result->FramebufferTex[4]); + SetupDefaultTexParams(result->FramebufferTex[6]); // attribute buffer // R: opaque polyID (for edgemarking) // G: edge flag // B: fog flag - SetupDefaultTexParams(FramebufferTex[5]); - SetupDefaultTexParams(FramebufferTex[7]); + SetupDefaultTexParams(result->FramebufferTex[5]); + SetupDefaultTexParams(result->FramebufferTex[7]); // downscale framebuffer for display capture (always 256x192) - SetupDefaultTexParams(FramebufferTex[3]); + SetupDefaultTexParams(result->FramebufferTex[3]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glEnable(GL_BLEND); glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX); - glGenBuffers(1, &PixelbufferID); + glGenBuffers(1, &result->PixelbufferID); glActiveTexture(GL_TEXTURE0); - glGenTextures(1, &TexMemID); - glBindTexture(GL_TEXTURE_2D, TexMemID); + glGenTextures(1, &result->TexMemID); + glBindTexture(GL_TEXTURE_2D, result->TexMemID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -274,8 +288,8 @@ bool GLRenderer::Init() glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, 1024, 512, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL); glActiveTexture(GL_TEXTURE1); - glGenTextures(1, &TexPalMemID); - glBindTexture(GL_TEXTURE_2D, TexPalMemID); + glGenTextures(1, &result->TexPalMemID); + glBindTexture(GL_TEXTURE_2D, result->TexPalMemID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -284,11 +298,13 @@ bool GLRenderer::Init() glBindFramebuffer(GL_FRAMEBUFFER, 0); - return true; + return result; } -void GLRenderer::DeInit() +GLRenderer::~GLRenderer() { + assert(glDeleteTextures != nullptr); + glDeleteTextures(1, &TexMemID); glDeleteTextures(1, &TexPalMemID); diff --git a/src/GPU3D_OpenGL.h b/src/GPU3D_OpenGL.h index a9dd62c..597f13e 100644 --- a/src/GPU3D_OpenGL.h +++ b/src/GPU3D_OpenGL.h @@ -28,10 +28,7 @@ namespace GPU3D class GLRenderer : public Renderer3D { public: - GLRenderer(); - virtual ~GLRenderer() override {}; - virtual bool Init() override; - virtual void DeInit() override; + virtual ~GLRenderer() override; virtual void Reset() override; virtual void SetRenderSettings(GPU::RenderSettings& settings) override; @@ -42,7 +39,11 @@ public: void SetupAccelFrame(); void PrepareCaptureFrame(); + + static std::unique_ptr<GLRenderer> New() noexcept; private: + // Used by New() + GLRenderer() noexcept; // GL version requirements // * texelFetch: 3.0 (GLSL 1.30) (3.2/1.50 for MS) @@ -62,7 +63,7 @@ private: u32 RenderKey; }; - RendererPolygon PolygonList[2048]; + RendererPolygon PolygonList[2048] {}; bool BuildRenderShader(u32 flags, const char* vs, const char* fs); void UseRenderShader(u32 flags); @@ -83,13 +84,13 @@ private: }; - GLuint ClearShaderPlain[3]; + GLuint ClearShaderPlain[3] {}; - GLuint RenderShader[16][3]; + GLuint RenderShader[16][3] {}; GLuint CurShaderID = -1; - GLuint FinalPassEdgeShader[3]; - GLuint FinalPassFogShader[3]; + GLuint FinalPassEdgeShader[3] {}; + GLuint FinalPassFogShader[3] {}; // std140 compliant structure struct @@ -104,13 +105,13 @@ private: u32 uFogOffset; // int 304 / 1 u32 uFogShift; // int 305 / 1 u32 _pad1[2]; // int 306 / 2 - } ShaderConfig; + } ShaderConfig {}; - GLuint ShaderConfigUBO; - int NumFinalPolys, NumOpaqueFinalPolys; + GLuint ShaderConfigUBO {}; + int NumFinalPolys {}, NumOpaqueFinalPolys {}; - GLuint ClearVertexBufferID, ClearVertexArrayID; - GLint ClearUniformLoc[4]; + GLuint ClearVertexBufferID = 0, ClearVertexArrayID {}; + GLint ClearUniformLoc[4] {}; // vertex buffer // * XYZW: 4x16bit @@ -124,28 +125,28 @@ private: // * bit8: front-facing (?) // * bit9: W-buffering (?) - GLuint VertexBufferID; - u32 VertexBuffer[10240 * 7]; - u32 NumVertices; + GLuint VertexBufferID {}; + u32 VertexBuffer[10240 * 7] {}; + u32 NumVertices {}; - GLuint VertexArrayID; - GLuint IndexBufferID; - u16 IndexBuffer[2048 * 40]; - u32 NumIndices, NumEdgeIndices; + GLuint VertexArrayID {}; + GLuint IndexBufferID {}; + u16 IndexBuffer[2048 * 40] {}; + u32 NumIndices {}, NumEdgeIndices {}; const u32 EdgeIndicesOffset = 2048 * 30; - GLuint TexMemID; - GLuint TexPalMemID; + GLuint TexMemID {}; + GLuint TexPalMemID {}; - int ScaleFactor; - bool BetterPolygons; - int ScreenW, ScreenH; + int ScaleFactor {}; + bool BetterPolygons {}; + int ScreenW {}, ScreenH {}; - GLuint FramebufferTex[8]; - int FrontBuffer; - GLuint FramebufferID[4], PixelbufferID; - u32 Framebuffer[256*192]; + GLuint FramebufferTex[8] {}; + int FrontBuffer {}; + GLuint FramebufferID[4] {}, PixelbufferID {}; + u32 Framebuffer[256*192] {}; }; diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index 98514ab..f7078b5 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -71,14 +71,9 @@ void SoftRenderer::SetupRenderThread() } -SoftRenderer::SoftRenderer() +SoftRenderer::SoftRenderer() noexcept : Renderer3D(false) { - -} - -bool SoftRenderer::Init() -{ Sema_RenderStart = Platform::Semaphore_Create(); Sema_RenderDone = Platform::Semaphore_Create(); Sema_ScanlineCount = Platform::Semaphore_Create(); @@ -86,11 +81,9 @@ bool SoftRenderer::Init() Threaded = false; RenderThreadRunning = false; RenderThreadRendering = false; - - return true; } -void SoftRenderer::DeInit() +SoftRenderer::~SoftRenderer() { StopRenderThread(); diff --git a/src/GPU3D_Soft.h b/src/GPU3D_Soft.h index 0c6ca43..948832f 100644 --- a/src/GPU3D_Soft.h +++ b/src/GPU3D_Soft.h @@ -28,10 +28,8 @@ namespace GPU3D class SoftRenderer : public Renderer3D { public: - SoftRenderer(); - virtual ~SoftRenderer() override {}; - virtual bool Init() override; - virtual void DeInit() override; + SoftRenderer() noexcept; + virtual ~SoftRenderer() override; virtual void Reset() override; virtual void SetRenderSettings(GPU::RenderSettings& settings) override; diff --git a/src/GPU_OpenGL.cpp b/src/GPU_OpenGL.cpp index 837d224..47e04d2 100644 --- a/src/GPU_OpenGL.cpp +++ b/src/GPU_OpenGL.cpp @@ -18,6 +18,7 @@ #include "GPU_OpenGL.h" +#include <assert.h> #include <cstdio> #include <cstring> @@ -32,33 +33,36 @@ namespace GPU using namespace OpenGL; -bool GLCompositor::Init() +std::unique_ptr<GLCompositor> GLCompositor::New() noexcept { - if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Nearest, CompShader[0], "CompositorShader")) - //if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Linear, CompShader[0], "CompositorShader")) - //if (!OpenGL::BuildShaderProgram(kCompositorVS_xBRZ, kCompositorFS_xBRZ, CompShader[0], "CompositorShader")) - return false; + assert(glBindAttribLocation != nullptr); - for (int i = 0; i < 1; i++) - { - GLint uni_id; + std::array<GLuint, 3> CompShader {}; + if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Nearest, &CompShader[0], "CompositorShader")) + return nullptr; - glBindAttribLocation(CompShader[i][2], 0, "vPosition"); - glBindAttribLocation(CompShader[i][2], 1, "vTexcoord"); - glBindFragDataLocation(CompShader[i][2], 0, "oColor"); + glBindAttribLocation(CompShader[2], 0, "vPosition"); + glBindAttribLocation(CompShader[2], 1, "vTexcoord"); + glBindFragDataLocation(CompShader[2], 0, "oColor"); - if (!OpenGL::LinkShaderProgram(CompShader[i])) - return false; + if (!OpenGL::LinkShaderProgram(CompShader.data())) + // OpenGL::LinkShaderProgram already deletes the shader program object + // if linking the shaders together failed. + return nullptr; - CompScaleLoc[i] = glGetUniformLocation(CompShader[i][2], "u3DScale"); - Comp3DXPosLoc[i] = glGetUniformLocation(CompShader[i][2], "u3DXPos"); + return std::unique_ptr<GLCompositor>(new GLCompositor(CompShader)); +} - glUseProgram(CompShader[i][2]); - uni_id = glGetUniformLocation(CompShader[i][2], "ScreenTex"); - glUniform1i(uni_id, 0); - uni_id = glGetUniformLocation(CompShader[i][2], "_3DTex"); - glUniform1i(uni_id, 1); - } +GLCompositor::GLCompositor(std::array<GLuint, 3> compShader) noexcept : CompShader(compShader) +{ + CompScaleLoc = glGetUniformLocation(CompShader[2], "u3DScale"); + Comp3DXPosLoc = glGetUniformLocation(CompShader[2], "u3DXPos"); + + glUseProgram(CompShader[2]); + GLuint screenTextureUniform = glGetUniformLocation(CompShader[2], "ScreenTex"); + glUniform1i(screenTextureUniform, 0); + GLuint _3dTextureUniform = glGetUniformLocation(CompShader[2], "_3DTex"); + glUniform1i(_3dTextureUniform, 1); // all this mess is to prevent bleeding #define SETVERTEX(i, x, y, offset) \ @@ -119,12 +123,12 @@ bool GLCompositor::Init() } glBindFramebuffer(GL_FRAMEBUFFER, 0); - - return true; } -void GLCompositor::DeInit() +GLCompositor::~GLCompositor() { + assert(glDeleteFramebuffers != nullptr); + glDeleteFramebuffers(2, CompScreenOutputFB); glDeleteTextures(1, &CompScreenInputTex); glDeleteTextures(2, CompScreenOutputTex); @@ -132,8 +136,7 @@ void GLCompositor::DeInit() glDeleteVertexArrays(1, &CompVertexArrayID); glDeleteBuffers(1, &CompVertexBufferID); - for (int i = 0; i < 1; i++) - OpenGL::DeleteShaderProgram(CompShader[i]); + OpenGL::DeleteShaderProgram(CompShader.data()); } void GLCompositor::Reset() @@ -197,11 +200,11 @@ void GLCompositor::RenderFrame() glClear(GL_COLOR_BUFFER_BIT); // TODO: select more shaders (filtering, etc) - OpenGL::UseShaderProgram(CompShader[0]); - glUniform1ui(CompScaleLoc[0], Scale); + OpenGL::UseShaderProgram(CompShader.data()); + glUniform1ui(CompScaleLoc, Scale); // TODO: support setting this midframe, if ever needed - glUniform1i(Comp3DXPosLoc[0], ((int)GPU3D::RenderXPos << 23) >> 23); + glUniform1i(Comp3DXPosLoc, ((int)GPU3D::RenderXPos << 23) >> 23); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, CompScreenInputTex); diff --git a/src/GPU_OpenGL.h b/src/GPU_OpenGL.h index d27ae20..90c17ae 100644 --- a/src/GPU_OpenGL.h +++ b/src/GPU_OpenGL.h @@ -20,6 +20,9 @@ #include "OpenGLSupport.h" +#include <array> +#include <memory> + namespace GPU { @@ -28,12 +31,11 @@ struct RenderSettings; class GLCompositor { public: - GLCompositor() = default; + static std::unique_ptr<GLCompositor> New() noexcept; GLCompositor(const GLCompositor&) = delete; GLCompositor& operator=(const GLCompositor&) = delete; + ~GLCompositor(); - bool Init(); - void DeInit(); void Reset(); void SetRenderSettings(RenderSettings& settings); @@ -42,13 +44,14 @@ public: void RenderFrame(); void BindOutputTexture(int buf); private: + GLCompositor(std::array<GLuint, 3> CompShader) noexcept; int Scale; int ScreenH, ScreenW; - GLuint CompShader[1][3]; - GLuint CompScaleLoc[1]; - GLuint Comp3DXPosLoc[1]; + std::array<GLuint, 3> CompShader; + GLuint CompScaleLoc; + GLuint Comp3DXPosLoc; GLuint CompVertexBufferID; GLuint CompVertexArrayID; diff --git a/src/NDS.cpp b/src/NDS.cpp index 2f1759f..1e7321d 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -226,10 +226,16 @@ void DeInit() #endif delete ARM9; + ARM9 = nullptr; + delete ARM7; + ARM7 = nullptr; for (int i = 0; i < 8; i++) + { delete DMAs[i]; + DMAs[i] = nullptr; + } NDSCart::DeInit(); GBACart::DeInit(); diff --git a/src/OpenGLSupport.cpp b/src/OpenGLSupport.cpp index 958930d..f1914fc 100644 --- a/src/OpenGLSupport.cpp +++ b/src/OpenGLSupport.cpp @@ -29,6 +29,12 @@ bool BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* int len; int res; + if (!glCreateShader) + { + Log(LogLevel::Error, "OpenGL: Cannot build shader program, OpenGL hasn't been loaded\n"); + return false; + } + ids[0] = glCreateShader(GL_VERTEX_SHADER); len = strlen(vs); glShaderSource(ids[0], 1, &vs, &len); @@ -87,6 +93,12 @@ bool LinkShaderProgram(GLuint* ids) { int res; + if (!glLinkProgram) + { + Log(LogLevel::Error, "OpenGL: Cannot link shader program, OpenGL hasn't been loaded\n"); + return false; + } + glLinkProgram(ids[2]); glDetachShader(ids[2], ids[0]); @@ -115,12 +127,18 @@ bool LinkShaderProgram(GLuint* ids) void DeleteShaderProgram(GLuint* ids) { - glDeleteProgram(ids[2]); + if (glDeleteProgram) + { // If OpenGL isn't loaded, then there's no shader program to delete + glDeleteProgram(ids[2]); + } } void UseShaderProgram(GLuint* ids) { - glUseProgram(ids[2]); + if (glUseProgram) + { // If OpenGL isn't loaded, then there's no shader program to use + glUseProgram(ids[2]); + } } } diff --git a/src/SPI.cpp b/src/SPI.cpp index bbfacbf..3c44964 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -91,6 +91,7 @@ bool Init() void DeInit() { if (Firmware) delete[] Firmware; + Firmware = nullptr; } u32 FixFirmwareLength(u32 originalLength) diff --git a/src/SPU.cpp b/src/SPU.cpp index 734590e..e83a0c7 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -135,12 +135,18 @@ bool Init() void DeInit() { for (int i = 0; i < 16; i++) + { delete Channels[i]; + Channels[i] = nullptr; + } delete Capture[0]; delete Capture[1]; + Capture[0] = nullptr; + Capture[1] = nullptr; Platform::Mutex_Free(AudioLock); + AudioLock = nullptr; } void Reset() diff --git a/src/frontend/qt_sdl/AudioInOut.cpp b/src/frontend/qt_sdl/AudioInOut.cpp index d44e92d..48e8a86 100644 --- a/src/frontend/qt_sdl/AudioInOut.cpp +++ b/src/frontend/qt_sdl/AudioInOut.cpp @@ -334,12 +334,17 @@ void Init() void DeInit() { if (audioDevice) SDL_CloseAudioDevice(audioDevice); + audioDevice = 0; MicClose(); - SDL_DestroyCond(audioSync); - SDL_DestroyMutex(audioSyncLock); + if (audioSync) SDL_DestroyCond(audioSync); + audioSync = nullptr; + + if (audioSyncLock) SDL_DestroyMutex(audioSyncLock); + audioSyncLock = nullptr; if (micWavBuffer) delete[] micWavBuffer; + micWavBuffer = nullptr; } void AudioSync() diff --git a/src/frontend/qt_sdl/LocalMP.cpp b/src/frontend/qt_sdl/LocalMP.cpp index 31801b7..870ea8b 100644 --- a/src/frontend/qt_sdl/LocalMP.cpp +++ b/src/frontend/qt_sdl/LocalMP.cpp @@ -297,16 +297,21 @@ bool Init() void DeInit() { - MPQueue->lock(); - MPQueueHeader* header = (MPQueueHeader*)MPQueue->data(); - header->ConnectedBitmask &= ~(1 << InstanceID); - header->InstanceBitmask &= ~(1 << InstanceID); - header->NumInstances--; - MPQueue->unlock(); + if (MPQueue) + { + MPQueue->lock(); + MPQueueHeader* header = (MPQueueHeader*)MPQueue->data(); + header->ConnectedBitmask &= ~(1 << InstanceID); + header->InstanceBitmask &= ~(1 << InstanceID); + header->NumInstances--; + MPQueue->unlock(); - SemPoolDeinit(); + SemPoolDeinit(); + + MPQueue->detach(); + } - MPQueue->detach(); + MPQueue = nullptr; delete MPQueue; } |