From d35de81a76ac2ef38729b0c67589ee0be1345dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 26 May 2018 17:50:37 +0200 Subject: [PATCH 1/6] Check for a valid screen manager in NativeIsAtTopLevel --- UI/NativeApp.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index c822702b49..1f7ee8509e 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1004,6 +1004,11 @@ void NativeUpdate() { } bool NativeIsAtTopLevel() { + // This might need some synchronization? + if (!screenManager) { + ELOG("No screen manager active"); + return false; + } Screen *currentScreen = screenManager->topScreen(); if (currentScreen) { bool top = currentScreen->isTopLevel(); From d7770307f3074fcac7558856fdb949142548b652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 27 May 2018 21:53:13 +0200 Subject: [PATCH 2/6] Change some log levels to verbose --- Core/HLE/sceIo.cpp | 2 +- Core/HLE/sceUmd.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index f2f5eebf6b..77e1a24113 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -2086,7 +2086,7 @@ static u32 sceIoPollAsync(int id, u32 address) { FileNode *f = __IoGetFd(id, error); if (f) { if (f->pendingAsyncResult) { - DEBUG_LOG(SCEIO, "%lli = sceIoPollAsync(%i, %08x): not ready", f->asyncResult, id, address); + VERBOSE_LOG(SCEIO, "%lli = sceIoPollAsync(%i, %08x): not ready", f->asyncResult, id, address); return 1; } else if (f->hasAsyncResult) { DEBUG_LOG(SCEIO, "%lli = sceIoPollAsync(%i, %08x)", f->asyncResult, id, address); diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index f293a72d2b..bd4cb56d7b 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -342,7 +342,8 @@ static u32 sceUmdGetDriveStat() } //u32 retVal = PSP_UMD_INITED | PSP_UMD_READY | PSP_UMD_PRESENT; u32 retVal = __KernelUmdGetState(); - DEBUG_LOG(SCEIO,"0x%02x=sceUmdGetDriveStat()", retVal); + // This one can be very spammy. + VERBOSE_LOG(SCEIO,"0x%02x=sceUmdGetDriveStat()", retVal); return retVal; } From b730d187e8e1417b86bde56435540fe1f67f49b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 27 May 2018 21:54:07 +0200 Subject: [PATCH 3/6] Add some paranoid checks guided by stack traces from Google Play --- GPU/GLES/DrawEngineGLES.cpp | 9 ++++++--- UI/EmuScreen.cpp | 17 +++++++++++------ android/jni/app-android.cpp | 3 ++- ext/native/thin3d/VulkanQueueRunner.cpp | 4 ++-- ext/native/thin3d/thin3d_vulkan.cpp | 9 +++++++-- 5 files changed, 28 insertions(+), 14 deletions(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 2241a18dd3..a9769383b9 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -108,10 +108,11 @@ void DrawEngineGLES::DeviceRestore() { } void DrawEngineGLES::InitDeviceObjects() { + _assert_msg_(G3D, render_ != nullptr, "Render manager must be set"); + for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { frameData_[i].pushVertex = render_->CreatePushBuffer(i, GL_ARRAY_BUFFER, 1024 * 1024); frameData_[i].pushIndex = render_->CreatePushBuffer(i, GL_ELEMENT_ARRAY_BUFFER, 256 * 1024); - } int vertexSize = sizeof(TransformedVertex); @@ -129,8 +130,10 @@ void DrawEngineGLES::DestroyDeviceObjects() { if (!frameData_[i].pushVertex && !frameData_[i].pushIndex) continue; - render_->DeletePushBuffer(frameData_[i].pushVertex); - render_->DeletePushBuffer(frameData_[i].pushIndex); + if (frameData_[i].pushVertex) + render_->DeletePushBuffer(frameData_[i].pushVertex); + if (frameData_[i].pushIndex) + render_->DeletePushBuffer(frameData_[i].pushIndex); frameData_[i].pushVertex = nullptr; frameData_[i].pushIndex = nullptr; } diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index ffef7dd59f..3e1b322e0d 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -856,13 +856,16 @@ public: // PIC1 is the loading image, so let's only draw if it's available. if (ginfo && ginfo->pic1.texture) { - dc.GetDrawContext()->BindTexture(0, ginfo->pic1.texture->GetTexture()); + Draw::Texture *texture = ginfo->pic1.texture->GetTexture(); + if (texture) { + dc.GetDrawContext()->BindTexture(0, texture); - double loadTime = ginfo->pic1.timeLoaded; - uint32_t color = alphaMul(color_, ease((time_now_d() - loadTime) * 3)); - dc.Draw()->DrawTexRect(dc.GetBounds(), 0, 0, 1, 1, color); - dc.Flush(); - dc.RebindTexture(); + double loadTime = ginfo->pic1.timeLoaded; + uint32_t color = alphaMul(color_, ease((time_now_d() - loadTime) * 3)); + dc.Draw()->DrawTexRect(dc.GetBounds(), 0, 0, 1, 1, color); + dc.Flush(); + dc.RebindTexture(); + } } } @@ -1154,6 +1157,8 @@ void EmuScreen::render() { using namespace Draw; DrawContext *thin3d = screenManager()->getDrawContext(); + if (!thin3d) + return; // shouldn't really happen but I've seen a suspicious stack trace.. if (invalid_) { // Loading, or after shutdown? diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 3043425f61..8ca63aab67 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -650,7 +650,8 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, if (useCPUThread) { // This is the "GPU thread". - graphicsContext->ThreadFrame(); + if (graphicsContext) + graphicsContext->ThreadFrame(); } else { UpdateRunLoopAndroid(env); } diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 6623112428..f22fa7d340 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -353,8 +353,6 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector &st // * Create copies of render target that are rendered to multiple times and textured from in sequence, and push those render passes // as early as possible in the frame (Wipeout billboards). - // Push down empty "Clear/Store" renderpasses, and merge them with the first "Load/Store" to the same framebuffer. - // Actually let's just bother with the first one for now. This affects Wipeout Pure. for (int j = 0; j < (int)steps.size() - 1; j++) { if (steps[j]->stepType == VKRStepType::RENDER && steps[j]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) { @@ -362,6 +360,8 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector &st steps[j]->render.finalColorLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } + // Push down empty "Clear/Store" renderpasses, and merge them with the first "Load/Store" to the same framebuffer. + // Actually let's just bother with the first one for now. This affects Wipeout Pure. if (steps.size() > 1 && steps[j]->stepType == VKRStepType::RENDER && steps[j]->render.numDraws == 0 && steps[j]->render.color == VKRRenderPassAction::CLEAR && diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 6f6a7dc735..ab9b828def 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -312,8 +312,13 @@ public: } VkImageView GetImageView() { - vkTex_->Touch(); - return vkTex_->GetImageView(); + if (vkTex_) { + vkTex_->Touch(); + return vkTex_->GetImageView(); + } else { + // This would be bad. + return VK_NULL_HANDLE; + } } private: From 343763cf5a2d66c718538a5ac056ad2c9af5c6a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 27 May 2018 22:16:36 +0200 Subject: [PATCH 4/6] More paranoia from Google Play --- android/jni/app-android.cpp | 6 +++++- android/src/org/ppsspp/ppsspp/NativeActivity.java | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 8ca63aab67..9675eba147 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -323,6 +323,8 @@ bool System_GetPropertyBool(SystemProperty prop) { } std::string GetJavaString(JNIEnv *env, jstring jstr) { + if (!jstr) + return ""; const char *str = env->GetStringUTFChars(jstr, 0); std::string cpp_string = std::string(str); env->ReleaseStringUTFChars(jstr, str); @@ -397,7 +399,9 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init langRegion = GetJavaString(env, jlangRegion); std::string externalDir = GetJavaString(env, jexternalDir); - std::string user_data_path = GetJavaString(env, jdataDir) + "/"; + std::string user_data_path = GetJavaString(env, jdataDir); + if (user_data_path.size() > 0) + user_data_path += "/"; library_path = GetJavaString(env, jlibraryDir) + "/"; std::string shortcut_param = GetJavaString(env, jshortcutParam); std::string cacheDir = GetJavaString(env, jcacheDir); diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 7f301c992c..9888a9fa11 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -296,7 +296,12 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C File sdcard = Environment.getExternalStorageDirectory(); String externalStorageDir = sdcard.getAbsolutePath(); - String dataDir = this.getFilesDir().getAbsolutePath(); + File filesDir = this.getFilesDir(); + String dataDir = null; + if (filesDir != null) { + // Null has been seen in Google Play stacktraces + dataDir = this.getFilesDir().getAbsolutePath(); + } String apkFilePath = appInfo.sourceDir; String cacheDir = getCacheDir().getAbsolutePath(); From 0d6be3a4768453eb36570b154cc1a9d5dd97dd2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 27 May 2018 22:19:03 +0200 Subject: [PATCH 5/6] GLES: Refresh the draw context in DrawEngineGLES on DeviceRestore. How did we miss this? --- GPU/GLES/DrawEngineGLES.cpp | 3 ++- GPU/GLES/DrawEngineGLES.h | 2 +- GPU/GLES/GPU_GLES.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index a9769383b9..72861b4023 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -103,7 +103,8 @@ void DrawEngineGLES::DeviceLost() { DestroyDeviceObjects(); } -void DrawEngineGLES::DeviceRestore() { +void DrawEngineGLES::DeviceRestore(Draw::DrawContext *draw) { + draw_ = draw; InitDeviceObjects(); } diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index 535535d42e..2901a1c384 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -130,7 +130,7 @@ public: } void DeviceLost(); - void DeviceRestore(); + void DeviceRestore(Draw::DrawContext *draw); void ClearTrackedVertexArrays() override; void DecimateTrackedVertexArrays(); diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index b1505cfacd..0b3e14489d 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -351,7 +351,7 @@ void GPU_GLES::DeviceRestore() { textureCacheGL_->DeviceRestore(draw_); framebufferManagerGL_->DeviceRestore(draw_); - drawEngine_.DeviceRestore(); + drawEngine_.DeviceRestore(draw_); } void GPU_GLES::Reinitialize() { From 14d17419b1f170ea3e2ab10bbb15671af93461e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 27 May 2018 22:51:00 +0200 Subject: [PATCH 6/6] Minor cleanup --- android/src/org/ppsspp/ppsspp/NativeActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 9888a9fa11..44760b8869 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -300,7 +300,7 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C String dataDir = null; if (filesDir != null) { // Null has been seen in Google Play stacktraces - dataDir = this.getFilesDir().getAbsolutePath(); + dataDir = filesDir.getAbsolutePath(); } String apkFilePath = appInfo.sourceDir; String cacheDir = getCacheDir().getAbsolutePath();