diff --git a/Common/GPU/OpenGL/GLFrameData.cpp b/Common/GPU/OpenGL/GLFrameData.cpp index fa5a051d3055..a82669dc8ad5 100644 --- a/Common/GPU/OpenGL/GLFrameData.cpp +++ b/Common/GPU/OpenGL/GLFrameData.cpp @@ -32,25 +32,25 @@ void GLDeleter::Perform(GLRenderManager *renderManager, bool skipGLCalls) { } pushBuffers.clear(); for (auto shader : shaders) { - if (skipGLCalls) + if (skipGLCalls && shader) shader->shader = 0; // prevent the glDeleteShader delete shader; } shaders.clear(); for (auto program : programs) { - if (skipGLCalls) + if (skipGLCalls && program) program->program = 0; // prevent the glDeleteProgram delete program; } programs.clear(); for (auto buffer : buffers) { - if (skipGLCalls) + if (skipGLCalls && buffer) buffer->buffer_ = 0; delete buffer; } buffers.clear(); for (auto texture : textures) { - if (skipGLCalls) + if (skipGLCalls && texture) texture->texture = 0; delete texture; } diff --git a/Common/GPU/OpenGL/GLRenderManager.h b/Common/GPU/OpenGL/GLRenderManager.h index 1fb5c8247390..8aed292758cf 100644 --- a/Common/GPU/OpenGL/GLRenderManager.h +++ b/Common/GPU/OpenGL/GLRenderManager.h @@ -349,24 +349,31 @@ class GLRenderManager { } void DeleteShader(GLRShader *shader) { + _dbg_assert_(shader != nullptr); deleter_.shaders.push_back(shader); } void DeleteProgram(GLRProgram *program) { + _dbg_assert_(program != nullptr); deleter_.programs.push_back(program); } void DeleteBuffer(GLRBuffer *buffer) { + _dbg_assert_(buffer != nullptr); deleter_.buffers.push_back(buffer); } void DeleteTexture(GLRTexture *texture) { + _dbg_assert_(texture != nullptr); deleter_.textures.push_back(texture); } void DeleteInputLayout(GLRInputLayout *inputLayout) { + _dbg_assert_(inputLayout != nullptr); deleter_.inputLayouts.push_back(inputLayout); } void DeleteFramebuffer(GLRFramebuffer *framebuffer) { + _dbg_assert_(framebuffer != nullptr); deleter_.framebuffers.push_back(framebuffer); } void DeletePushBuffer(GLPushBuffer *pushbuffer) { + _dbg_assert_(pushbuffer != nullptr); deleter_.pushBuffers.push_back(pushbuffer); } diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 66c408f95375..59cd3eba3c6a 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -934,7 +934,7 @@ void OpenGLTexture::UpdateTextureLevels(GLRenderManager *render, const uint8_t * OpenGLTexture::~OpenGLTexture() { if (tex_) { render_->DeleteTexture(tex_); - tex_ = 0; + tex_ = nullptr; generatedMips_ = false; } } diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index fff194adc256..4414af64f9c0 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -288,7 +288,6 @@ bool VulkanRenderManager::CreateBackbuffers() { return false; } - VkCommandBuffer cmdInit = GetInitCmd(); if (!queueRunner_.CreateSwapchain(cmdInit)) { @@ -310,6 +309,11 @@ bool VulkanRenderManager::CreateBackbuffers() { outOfDateFrames_ = 0; + for (int i = 0; i < vulkan_->GetInflightFrames(); i++) { + auto &frameData = frameData_[i]; + frameData.readyForFence = true; // Just in case. + } + // Start the thread(s). if (HasBackbuffers()) { run_ = true; // For controlling the compiler thread's exit diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index e4d5bbac31be..3d90fe9e7753 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -521,7 +521,7 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p if (prevSizeU < size_u || prevSizeV < size_v) { prevSizeU = size_u; prevSizeV = size_v; - if (!data_tex[0]) + if (data_tex[0]) renderManager_->DeleteTexture(data_tex[0]); data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D, size_u * 3, size_v, 1, 1); renderManager_->TextureImage(data_tex[0], 0, size_u * 3, size_v, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false); @@ -540,7 +540,7 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p // Weight U if (prevSizeWU < weights.size_u) { prevSizeWU = weights.size_u; - if (!data_tex[1]) + if (data_tex[1]) renderManager_->DeleteTexture(data_tex[1]); data_tex[1] = renderManager_->CreateTexture(GL_TEXTURE_2D, weights.size_u * 2, 1, 1, 1); renderManager_->TextureImage(data_tex[1], 0, weights.size_u * 2, 1, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false); @@ -552,7 +552,7 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p // Weight V if (prevSizeWV < weights.size_v) { prevSizeWV = weights.size_v; - if (!data_tex[2]) + if (data_tex[2]) renderManager_->DeleteTexture(data_tex[2]); data_tex[2] = renderManager_->CreateTexture(GL_TEXTURE_2D, weights.size_v * 2, 1, 1, 1); renderManager_->TextureImage(data_tex[2], 0, weights.size_v * 2, 1, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 129cdf056d09..10a46ca9ee64 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -182,7 +182,6 @@ GPU_Vulkan::~GPU_Vulkan() { shaderManager_->ClearShaders(); // other managers are deleted in ~GPUCommonHW. - if (draw_) { VulkanRenderManager *rm = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); rm->ReleaseCompileQueue(); @@ -427,6 +426,13 @@ void GPU_Vulkan::DeviceLost() { while (!IsReady()) { sleep_ms(10); } + // draw_ is normally actually still valid here in Vulkan. But we null it out in GPUCommonHW::DeviceLost so we don't try to use it again. + Draw::DrawContext *draw = draw_; + if (draw) { + VulkanRenderManager *rm = (VulkanRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + rm->DrainAndBlockCompileQueue(); + } + if (shaderCachePath_.Valid()) { SaveCache(shaderCachePath_); } @@ -434,6 +440,11 @@ void GPU_Vulkan::DeviceLost() { pipelineManager_->DeviceLost(); GPUCommonHW::DeviceLost(); + + if (draw) { + VulkanRenderManager *rm = (VulkanRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + rm->ReleaseCompileQueue(); + } } void GPU_Vulkan::DeviceRestore(Draw::DrawContext *draw) { diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index ffe7e411b61b..8433de74426e 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -1310,9 +1310,7 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeActivity_requestExitVulkanR return; } exitRenderLoop = true; - while (renderLoopRunning) { - sleep_ms(5); - } + // The caller joins the thread anyway, so no point in doing a wait loop here, only leads to misleading hang diagnostics. } void correctRatio(int &sz_x, int &sz_y, float scale) { diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 4f6cc7835359..21ac0553e7c1 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -767,8 +767,10 @@ protected void onDestroy() { nativeRenderer = null; } } - mGLSurfaceView.onDestroy(); - mGLSurfaceView = null; + if (mGLSurfaceView != null) { + mGLSurfaceView.onDestroy(); + mGLSurfaceView = null; + } } else { if (mSurfaceView != null) { mSurfaceView.onDestroy();