From ec504756e03bbe5e68a83ccdbb857b39d75dfe7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Nov 2017 16:02:05 +0100 Subject: [PATCH 01/12] Vulkan: Improve init/shutdown logging on Android. Fix a bug where we'd not run InitDeviceObjects on GPU_Vulkan sometimes. --- Common/Vulkan/VulkanContext.cpp | 6 ++++ Common/Vulkan/VulkanContext.h | 3 +- GPU/Vulkan/GPU_Vulkan.cpp | 5 ++++ UI/EmuScreen.cpp | 4 +++ Windows/GPU/WindowsVulkanContext.cpp | 2 ++ android/jni/app-android.cpp | 29 +++++++++++++------ .../src/org/ppsspp/ppsspp/NativeActivity.java | 4 +-- 7 files changed, 41 insertions(+), 12 deletions(-) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index d2c04172b7..e89cf7ea0e 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -165,8 +165,13 @@ VkResult VulkanContext::CreateInstance(const char *app_name, int app_ver, uint32 } VulkanContext::~VulkanContext() { + assert(instance_ == VK_NULL_HANDLE); +} + +void VulkanContext::DestroyInstance() { vkDestroyInstance(instance_, nullptr); VulkanFree(); + instance_ = VK_NULL_HANDLE; } void VulkanContext::BeginFrame() { @@ -797,6 +802,7 @@ VkFence VulkanContext::CreateFence(bool presignalled) { } void VulkanContext::DestroyDevice() { + ILOG("VulkanContext::DestroyDevice (performing deletes)"); // If there happen to be any pending deletes, now is a good time. for (int i = 0; i < ARRAY_SIZE(frame_); i++) { frame_[i].deleteList.PerformDeletes(device_); diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index 8b1044c093..6be9c6809d 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -214,7 +214,8 @@ public: ~VulkanContext(); VkResult CreateInstance(const char *app_name, int app_ver, uint32_t flags); - + void DestroyInstance(); + int GetBestPhysicalDevice(); void ChooseDevice(int physical_device); bool EnableDeviceExtension(const char *extension); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 659762c5bf..e2c2b6eae1 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -781,13 +781,16 @@ void GPU_Vulkan::FastLoadBoneMatrix(u32 target) { } void GPU_Vulkan::InitDeviceObjects() { + ILOG("GPU_Vulkan::InitDeviceObjects"); // Initialize framedata for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { + assert(!frameData_[i].push_); frameData_[i].push_ = new VulkanPushBuffer(vulkan_, 64 * 1024); } } void GPU_Vulkan::DestroyDeviceObjects() { + ILOG("GPU_Vulkan::DestroyDeviceObjects"); for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { if (frameData_[i].push_) { frameData_[i].push_->Destroy(vulkan_); @@ -810,6 +813,8 @@ void GPU_Vulkan::DeviceLost() { void GPU_Vulkan::DeviceRestore() { vulkan_ = (VulkanContext *)PSP_CoreParameter().graphicsContext->GetAPIContext(); + InitDeviceObjects(); + CheckGPUFeatures(); BuildReportingInfo(); UpdateCmdInfo(); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index bbeb5c9b6d..de5abdf55d 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1104,12 +1104,16 @@ 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(); } diff --git a/Windows/GPU/WindowsVulkanContext.cpp b/Windows/GPU/WindowsVulkanContext.cpp index 4d8e8f152f..0a240afeb4 100644 --- a/Windows/GPU/WindowsVulkanContext.cpp +++ b/Windows/GPU/WindowsVulkanContext.cpp @@ -218,6 +218,8 @@ void WindowsVulkanContext::Shutdown() { g_Vulkan->DestroyObjects(); g_Vulkan->DestroyDevice(); g_Vulkan->DestroyDebugMsgCallback(); + g_Vulkan->DestroyInstance(); + delete g_Vulkan; g_Vulkan = nullptr; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 8517e5bdf1..288b3e9368 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -189,6 +189,11 @@ static VulkanContext *g_Vulkan; class AndroidVulkanContext : public AndroidGraphicsContext { public: AndroidVulkanContext() : draw_(nullptr) {} + ~AndroidVulkanContext() { + delete g_Vulkan; + g_Vulkan = nullptr; + } + bool Init(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) override; void Shutdown() override; void SwapInterval(int interval) override; @@ -270,10 +275,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, } bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) { - if (g_Vulkan) { - return false; - } - + ILOG("AndroidVulkanContext::Init"); init_glslang(); g_LogOptions.breakOnError = true; @@ -282,7 +284,10 @@ bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX, ILOG("Creating vulkan context"); Version gitVer(PPSSPP_GIT_VERSION); - g_Vulkan = new VulkanContext(); + + if (!g_Vulkan) { + g_Vulkan = new VulkanContext(); + } if (VK_SUCCESS != g_Vulkan->CreateInstance("PPSSPP", gitVer.ToInteger(), VULKAN_FLAG_PRESENT_MAILBOX | VULKAN_FLAG_PRESENT_FIFO_RELAXED)) { ELOG("Failed to create vulkan context: %s", g_Vulkan->InitError().c_str()); delete g_Vulkan; @@ -326,6 +331,7 @@ bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX, bool success = draw_->CreatePresets(); // Doesn't fail, we ship the compiler. assert(success); draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); + ILOG("AndroidVulkanContext::Init completed"); return true; } @@ -337,19 +343,23 @@ void AndroidVulkanContext::Shutdown() { NativeShutdownGraphics(); g_Vulkan->WaitUntilQueueIdle(); g_Vulkan->DestroyObjects(); - g_Vulkan->DestroyDebugMsgCallback(); g_Vulkan->DestroyDevice(); + g_Vulkan->DestroyDebugMsgCallback(); - delete g_Vulkan; - g_Vulkan = nullptr; + g_Vulkan->DestroyInstance(); + + // We keep the g_Vulkan context around to avoid invalidating a ton of pointers around the app. finalize_glslang(); + ILOG("AndroidVulkanContext::Shutdown completed"); } void AndroidVulkanContext::SwapBuffers() { } void AndroidVulkanContext::Resize() { + ILOG("AndroidVulkanContext::Resize begin"); + draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); g_Vulkan->DestroyObjects(); @@ -357,6 +367,7 @@ void AndroidVulkanContext::Resize() { g_Vulkan->ReinitSurfaceAndroid(pixel_xres, pixel_yres); g_Vulkan->InitObjects(); draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); + ILOG("AndroidVulkanContext::Resize end"); } void AndroidVulkanContext::SwapInterval(int interval) { @@ -1124,7 +1135,7 @@ retry: ProcessFrameCommands(env); } - ILOG("After render loop."); + ILOG("Leaving EGL/Vulkan render loop."); g_gameInfoCache->WorkQueue()->Flush(); NativeDeviceLost(); diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index b48cfae5c1..59738c8418 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -647,10 +647,10 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C loseAudioFocus(this.audioManager, this.audioFocusChangeListener); NativeApp.pause(); if (!javaGL) { - Log.i(TAG, "Pausing surface view"); mSurfaceView.onPause(); - Log.i(TAG, "Joining render thread"); + Log.i(TAG, "Joining render thread..."); joinRenderLoopThread(); + Log.i(TAG, "Joined render thread"); } else { if (mGLSurfaceView != null) { mGLSurfaceView.onPause(); From 6eb58b12524ecc7aa19533f11939fe8e8542ceb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Nov 2017 16:28:22 +0100 Subject: [PATCH 02/12] Keep the draw context up to date in a bunch of places. More logging. --- GPU/Vulkan/DepalettizeShaderVulkan.cpp | 5 +++++ GPU/Vulkan/DepalettizeShaderVulkan.h | 1 + GPU/Vulkan/DrawEngineVulkan.cpp | 3 ++- GPU/Vulkan/DrawEngineVulkan.h | 2 +- GPU/Vulkan/FramebufferVulkan.cpp | 3 ++- GPU/Vulkan/FramebufferVulkan.h | 2 +- GPU/Vulkan/GPU_Vulkan.cpp | 8 +++++--- GPU/Vulkan/TextureCacheVulkan.cpp | 3 ++- GPU/Vulkan/TextureCacheVulkan.h | 2 +- android/jni/app-android.cpp | 1 + ext/native/thin3d/VulkanQueueRunner.cpp | 6 ++++++ ext/native/thin3d/VulkanRenderManager.cpp | 7 ++++--- ext/native/thin3d/VulkanRenderManager.h | 2 +- 13 files changed, 32 insertions(+), 13 deletions(-) diff --git a/GPU/Vulkan/DepalettizeShaderVulkan.cpp b/GPU/Vulkan/DepalettizeShaderVulkan.cpp index ce71a9babd..513252c4c1 100644 --- a/GPU/Vulkan/DepalettizeShaderVulkan.cpp +++ b/GPU/Vulkan/DepalettizeShaderVulkan.cpp @@ -70,6 +70,11 @@ DepalShaderCacheVulkan::~DepalShaderCacheVulkan() { vulkan_->Delete().QueueDeleteShaderModule(vshader_); } +void DepalShaderCacheVulkan::DeviceRestore(Draw::DrawContext *draw, VulkanContext *vulkan) { + draw_ = draw; + vulkan_ = vulkan; +} + DepalShaderVulkan *DepalShaderCacheVulkan::GetDepalettizeShader(uint32_t clutMode, GEBufferFormat pixelFormat) { u32 id = GenerateShaderID(clutMode, pixelFormat); diff --git a/GPU/Vulkan/DepalettizeShaderVulkan.h b/GPU/Vulkan/DepalettizeShaderVulkan.h index bba40a2c09..76e6d48f81 100644 --- a/GPU/Vulkan/DepalettizeShaderVulkan.h +++ b/GPU/Vulkan/DepalettizeShaderVulkan.h @@ -52,6 +52,7 @@ class DepalShaderCacheVulkan : public DepalShaderCacheCommon { public: DepalShaderCacheVulkan(Draw::DrawContext *draw, VulkanContext *vulkan); ~DepalShaderCacheVulkan(); + void DeviceRestore(Draw::DrawContext *draw, VulkanContext *vulkan); // This also uploads the palette and binds the correct texture. DepalShaderVulkan *GetDepalettizeShader(uint32_t clutMode, GEBufferFormat pixelFormat); diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 580c5bef20..6d48626a08 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -269,8 +269,9 @@ void DrawEngineVulkan::DeviceLost() { DirtyAllUBOs(); } -void DrawEngineVulkan::DeviceRestore(VulkanContext *vulkan) { +void DrawEngineVulkan::DeviceRestore(VulkanContext *vulkan, Draw::DrawContext *draw) { vulkan_ = vulkan; + draw_ = draw; InitDeviceObjects(); } diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index 2322dfdc45..de4c5e04ef 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -137,7 +137,7 @@ public: } void DeviceLost(); - void DeviceRestore(VulkanContext *vulkan); + void DeviceRestore(VulkanContext *vulkan, Draw::DrawContext *draw); void SetupVertexDecoder(u32 vertType); void SetupVertexDecoderInternal(u32 vertType); diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index 6abc89637b..3de17428f0 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -593,8 +593,9 @@ void FramebufferManagerVulkan::DeviceLost() { DestroyDeviceObjects(); } -void FramebufferManagerVulkan::DeviceRestore(VulkanContext *vulkan) { +void FramebufferManagerVulkan::DeviceRestore(VulkanContext *vulkan, Draw::DrawContext *draw) { vulkan_ = vulkan; + draw_ = draw; vulkan2D_->DeviceRestore(vulkan_); InitDeviceObjects(); diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index 9c37034842..2269283919 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -70,7 +70,7 @@ public: void Resized() override; void DeviceLost(); - void DeviceRestore(VulkanContext *vulkan); + void DeviceRestore(VulkanContext *vulkan, Draw::DrawContext *draw); int GetLineWidth(); void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) override; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index e2c2b6eae1..f2e16024c6 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -813,17 +813,19 @@ void GPU_Vulkan::DeviceLost() { void GPU_Vulkan::DeviceRestore() { vulkan_ = (VulkanContext *)PSP_CoreParameter().graphicsContext->GetAPIContext(); + draw_ = (Draw::DrawContext *)PSP_CoreParameter().graphicsContext->GetDrawContext(); InitDeviceObjects(); CheckGPUFeatures(); BuildReportingInfo(); UpdateCmdInfo(); - framebufferManagerVulkan_->DeviceRestore(vulkan_); - drawEngine_.DeviceRestore(vulkan_); + framebufferManagerVulkan_->DeviceRestore(vulkan_, draw_); + drawEngine_.DeviceRestore(vulkan_, draw_); pipelineManager_->DeviceRestore(vulkan_); - textureCacheVulkan_->DeviceRestore(vulkan_); + textureCacheVulkan_->DeviceRestore(vulkan_, draw_); shaderManagerVulkan_->DeviceRestore(vulkan_); + depalShaderCache_.DeviceRestore(draw_, vulkan_); } void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) { diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 20664c7831..dfbf2e64cf 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -187,8 +187,9 @@ void TextureCacheVulkan::DeviceLost() { nextTexture_ = nullptr; } -void TextureCacheVulkan::DeviceRestore(VulkanContext *vulkan) { +void TextureCacheVulkan::DeviceRestore(VulkanContext *vulkan, Draw::DrawContext *draw) { vulkan_ = vulkan; + draw_ = draw; assert(!allocator_); diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 1b168fd0f5..52d8055bb6 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -72,7 +72,7 @@ public: void EndFrame(); void DeviceLost(); - void DeviceRestore(VulkanContext *vulkan); + void DeviceRestore(VulkanContext *vulkan, Draw::DrawContext *draw); void SetFramebufferManager(FramebufferManagerVulkan *fbManager); void SetDepalShaderCache(DepalShaderCacheVulkan *dpCache) { diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 288b3e9368..5e0f183d65 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -340,6 +340,7 @@ void AndroidVulkanContext::Shutdown() { draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); delete draw_; draw_ = nullptr; + ILOG("Calling NativeShutdownGraphics"); NativeShutdownGraphics(); g_Vulkan->WaitUntilQueueIdle(); g_Vulkan->DestroyObjects(); diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index df43465603..82be5de2a3 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -9,6 +9,7 @@ const uint32_t readbackBufferSize = 2048 * 2048 * 4; void VulkanQueueRunner::CreateDeviceObjects() { + ILOG("VulkanQueueRuner::CreateDeviceObjects"); InitBackbufferRenderPass(); InitRenderpasses(); @@ -36,16 +37,21 @@ void VulkanQueueRunner::CreateDeviceObjects() { } void VulkanQueueRunner::DestroyDeviceObjects() { + ILOG("VulkanQueueRuner::DestroyDeviceObjects"); VkDevice device = vulkan_->GetDevice(); vkFreeMemory(device, readbackMemory_, nullptr); + readbackMemory_ = VK_NULL_HANDLE; vulkan_->Delete().QueueDeleteBuffer(readbackBuffer_); + readbackBuffer_ = VK_NULL_HANDLE; for (int i = 0; i < ARRAY_SIZE(renderPasses_); i++) { assert(renderPasses_[i] != VK_NULL_HANDLE); vkDestroyRenderPass(device, renderPasses_[i], nullptr); + renderPasses_[i] = VK_NULL_HANDLE; } assert(backbufferRenderPass_ != VK_NULL_HANDLE); vkDestroyRenderPass(device, backbufferRenderPass_, nullptr); + backbufferRenderPass_ = VK_NULL_HANDLE; } void VulkanQueueRunner::InitBackbufferRenderPass() { diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index 03d1d3b0ce..4683807bb0 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -199,7 +199,7 @@ void VulkanRenderManager::CreateBackbuffers() { } } -void VulkanRenderManager::StopThread(bool shutdown) { +void VulkanRenderManager::StopThread() { if (useThread && run_) { run_ = false; // Stop the thread. @@ -232,7 +232,7 @@ void VulkanRenderManager::StopThread(bool shutdown) { } void VulkanRenderManager::DestroyBackbuffers() { - StopThread(false); + StopThread(); vulkan_->WaitUntilQueueIdle(); VkDevice device = vulkan_->GetDevice(); @@ -253,7 +253,8 @@ void VulkanRenderManager::DestroyBackbuffers() { } VulkanRenderManager::~VulkanRenderManager() { - StopThread(true); + ILOG("VulkanRenderManager destructor"); + StopThread(); vulkan_->WaitUntilQueueIdle(); VkDevice device = vulkan_->GetDevice(); diff --git a/ext/native/thin3d/VulkanRenderManager.h b/ext/native/thin3d/VulkanRenderManager.h index a9faf1ccdd..5a47111226 100644 --- a/ext/native/thin3d/VulkanRenderManager.h +++ b/ext/native/thin3d/VulkanRenderManager.h @@ -222,7 +222,7 @@ private: void FlushSync(); void EndSyncFrame(int frame); - void StopThread(bool shutdown); + void StopThread(); // Permanent objects VkSemaphore acquireSemaphore_; From 8b42d8312373b6ae19a04b1630ece769fd6ed50d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Nov 2017 16:58:59 +0100 Subject: [PATCH 03/12] Vulkan: Remove duplicate depalShaderCache, fix a number of instances where we didn't use the deleter properly. Plus more logging, of course. --- Common/Vulkan/VulkanContext.cpp | 2 ++ Common/Vulkan/VulkanContext.h | 2 ++ Common/Vulkan/VulkanMemory.cpp | 1 - GPU/Vulkan/DepalettizeShaderVulkan.cpp | 14 +++++++++++--- GPU/Vulkan/DepalettizeShaderVulkan.h | 1 + GPU/Vulkan/DrawEngineVulkan.cpp | 4 ++-- GPU/Vulkan/FramebufferVulkan.cpp | 3 +-- GPU/Vulkan/FramebufferVulkan.h | 1 - GPU/Vulkan/GPU_Vulkan.cpp | 2 +- GPU/Vulkan/VulkanUtil.cpp | 4 ++-- ext/native/thin3d/VulkanQueueRunner.cpp | 11 ++++++----- ext/native/thin3d/VulkanRenderManager.cpp | 9 +++++++-- ext/native/thin3d/thin3d_vulkan.cpp | 8 ++++---- ext/native/thread/prioritizedworkqueue.cpp | 4 +++- 14 files changed, 42 insertions(+), 24 deletions(-) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index e89cf7ea0e..acc0cbff90 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -219,6 +219,7 @@ bool VulkanContext::InitObjects() { } void VulkanContext::DestroyObjects() { + ILOG("VulkanContext::DestroyObjects (including swapchain)"); if (swapchain_ != VK_NULL_HANDLE) vkDestroySwapchainKHR(device_, swapchain_, nullptr); swapchain_ = VK_NULL_HANDLE; @@ -584,6 +585,7 @@ void VulkanContext::InitSurfaceAndroid(ANativeWindow *wnd, int width, int height } void VulkanContext::ReinitSurfaceAndroid(int width, int height) { + ILOG("Destroying and reiniting Android Vulkan surface"); if (surface_ != VK_NULL_HANDLE) { vkDestroySurfaceKHR(instance_, surface_, nullptr); surface_ = VK_NULL_HANDLE; diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index 6be9c6809d..4b195ad1de 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -71,6 +71,7 @@ class VulkanDeleteList { }; public: + // NOTE: These all take reference handles so they can zero the input value. void QueueDeleteCommandPool(VkCommandPool &pool) { cmdPools_.push_back(pool); pool = VK_NULL_HANDLE; } void QueueDeleteDescriptorPool(VkDescriptorPool &pool) { descPools_.push_back(pool); pool = VK_NULL_HANDLE; } void QueueDeleteShaderModule(VkShaderModule &module) { modules_.push_back(module); module = VK_NULL_HANDLE; } @@ -122,6 +123,7 @@ public: } void PerformDeletes(VkDevice device) { + ILOG("PerformDeletes"); for (auto &cmdPool : cmdPools_) { vkDestroyCommandPool(device, cmdPool, nullptr); } diff --git a/Common/Vulkan/VulkanMemory.cpp b/Common/Vulkan/VulkanMemory.cpp index 260be7d9d6..57b219b472 100644 --- a/Common/Vulkan/VulkanMemory.cpp +++ b/Common/Vulkan/VulkanMemory.cpp @@ -78,7 +78,6 @@ void VulkanPushBuffer::Destroy(VulkanContext *vulkan) { vulkan->Delete().QueueDeleteBuffer(info.buffer); vulkan->Delete().QueueDeleteDeviceMemory(info.deviceMemory); } - buffers_.clear(); } diff --git a/GPU/Vulkan/DepalettizeShaderVulkan.cpp b/GPU/Vulkan/DepalettizeShaderVulkan.cpp index 513252c4c1..d4022f86ca 100644 --- a/GPU/Vulkan/DepalettizeShaderVulkan.cpp +++ b/GPU/Vulkan/DepalettizeShaderVulkan.cpp @@ -60,19 +60,27 @@ static VkFormat GetClutDestFormat(GEPaletteFormat format, VkComponentMapping *co DepalShaderCacheVulkan::DepalShaderCacheVulkan(Draw::DrawContext *draw, VulkanContext *vulkan) : draw_(draw), vulkan_(vulkan) { - std::string errors; - vshader_ = CompileShaderModule(vulkan_, VK_SHADER_STAGE_VERTEX_BIT, depal_vs, &errors); - assert(vshader_ != VK_NULL_HANDLE); + DeviceRestore(draw, vulkan); } DepalShaderCacheVulkan::~DepalShaderCacheVulkan() { + DeviceLost(); +} + +void DepalShaderCacheVulkan::DeviceLost() { Clear(); vulkan_->Delete().QueueDeleteShaderModule(vshader_); + vshader_ = nullptr; + draw_ = nullptr; + vulkan_ = nullptr; } void DepalShaderCacheVulkan::DeviceRestore(Draw::DrawContext *draw, VulkanContext *vulkan) { draw_ = draw; vulkan_ = vulkan; + std::string errors; + vshader_ = CompileShaderModule(vulkan_, VK_SHADER_STAGE_VERTEX_BIT, depal_vs, &errors); + assert(vshader_ != VK_NULL_HANDLE); } DepalShaderVulkan *DepalShaderCacheVulkan::GetDepalettizeShader(uint32_t clutMode, GEBufferFormat pixelFormat) { diff --git a/GPU/Vulkan/DepalettizeShaderVulkan.h b/GPU/Vulkan/DepalettizeShaderVulkan.h index 76e6d48f81..f06057e0c1 100644 --- a/GPU/Vulkan/DepalettizeShaderVulkan.h +++ b/GPU/Vulkan/DepalettizeShaderVulkan.h @@ -52,6 +52,7 @@ class DepalShaderCacheVulkan : public DepalShaderCacheCommon { public: DepalShaderCacheVulkan(Draw::DrawContext *draw, VulkanContext *vulkan); ~DepalShaderCacheVulkan(); + void DeviceLost(); void DeviceRestore(Draw::DrawContext *draw, VulkanContext *vulkan); // This also uploads the palette and binds the correct texture. diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 6d48626a08..22ff3d91b7 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -249,10 +249,10 @@ void DrawEngineVulkan::DestroyDeviceObjects() { if (nullSampler_ != VK_NULL_HANDLE) vulkan_->Delete().QueueDeleteSampler(nullSampler_); if (pipelineLayout_ != VK_NULL_HANDLE) - vkDestroyPipelineLayout(vulkan_->GetDevice(), pipelineLayout_, nullptr); + vulkan_->Delete().QueueDeletePipelineLayout(pipelineLayout_); pipelineLayout_ = VK_NULL_HANDLE; if (descriptorSetLayout_ != VK_NULL_HANDLE) - vkDestroyDescriptorSetLayout(vulkan_->GetDevice(), descriptorSetLayout_, nullptr); + vulkan_->Delete().QueueDeleteDescriptorSetLayout(descriptorSetLayout_); descriptorSetLayout_ = VK_NULL_HANDLE; if (nullTexture_) { nullTexture_->Destroy(); diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index 3de17428f0..9cb3019553 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -88,8 +88,7 @@ FramebufferManagerVulkan::FramebufferManagerVulkan(Draw::DrawContext *draw, Vulk convBufSize_(0), textureCacheVulkan_(nullptr), shaderManagerVulkan_(nullptr), - pipelinePostShader_(VK_NULL_HANDLE), - depalVulkan_(draw, vulkan) { + pipelinePostShader_(VK_NULL_HANDLE) { InitDeviceObjects(); diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index 2269283919..98ac4d9e25 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -120,7 +120,6 @@ private: DrawEngineVulkan *drawEngineVulkan_; VulkanPushBuffer *push_; - DepalShaderCacheVulkan depalVulkan_; enum { MAX_COMMAND_BUFFERS = 32, }; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index f2e16024c6..ecb4c340c3 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -807,7 +807,7 @@ void GPU_Vulkan::DeviceLost() { drawEngine_.DeviceLost(); pipelineManager_->DeviceLost(); textureCacheVulkan_->DeviceLost(); - depalShaderCache_.Clear(); + depalShaderCache_.DeviceLost(); shaderManagerVulkan_->ClearShaders(); } diff --git a/GPU/Vulkan/VulkanUtil.cpp b/GPU/Vulkan/VulkanUtil.cpp index 01d001a0e3..662f5196c1 100644 --- a/GPU/Vulkan/VulkanUtil.cpp +++ b/GPU/Vulkan/VulkanUtil.cpp @@ -46,11 +46,11 @@ void Vulkan2D::DestroyDeviceObjects() { VkDevice device = vulkan_->GetDevice(); if (descriptorSetLayout_ != VK_NULL_HANDLE) { - vkDestroyDescriptorSetLayout(device, descriptorSetLayout_, nullptr); + vulkan_->Delete().QueueDeleteDescriptorSetLayout(descriptorSetLayout_); descriptorSetLayout_ = VK_NULL_HANDLE; } if (pipelineLayout_ != VK_NULL_HANDLE) { - vkDestroyPipelineLayout(device, pipelineLayout_, nullptr); + vulkan_->Delete().QueueDeletePipelineLayout(pipelineLayout_); pipelineLayout_ = VK_NULL_HANDLE; } diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 82be5de2a3..4b566d12e6 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -39,6 +39,7 @@ void VulkanQueueRunner::CreateDeviceObjects() { void VulkanQueueRunner::DestroyDeviceObjects() { ILOG("VulkanQueueRuner::DestroyDeviceObjects"); VkDevice device = vulkan_->GetDevice(); + vulkan_->Delete().QueueDeleteDeviceMemory(readbackMemory_); vkFreeMemory(device, readbackMemory_, nullptr); readbackMemory_ = VK_NULL_HANDLE; vulkan_->Delete().QueueDeleteBuffer(readbackBuffer_); @@ -46,11 +47,11 @@ void VulkanQueueRunner::DestroyDeviceObjects() { for (int i = 0; i < ARRAY_SIZE(renderPasses_); i++) { assert(renderPasses_[i] != VK_NULL_HANDLE); - vkDestroyRenderPass(device, renderPasses_[i], nullptr); + vulkan_->Delete().QueueDeleteRenderPass(renderPasses_[i]); renderPasses_[i] = VK_NULL_HANDLE; } assert(backbufferRenderPass_ != VK_NULL_HANDLE); - vkDestroyRenderPass(device, backbufferRenderPass_, nullptr); + vulkan_->Delete().QueueDeleteRenderPass(backbufferRenderPass_); backbufferRenderPass_ = VK_NULL_HANDLE; } @@ -425,8 +426,8 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c VkClearRect rc{}; rc.baseArrayLayer = 0; rc.layerCount = 1; - rc.rect.extent.width = curWidth; - rc.rect.extent.height = curHeight; + rc.rect.extent.width = (uint32_t)curWidth; + rc.rect.extent.height = (uint32_t)curHeight; VkClearAttachment attachments[2]; if (c.clear.clearMask & VK_IMAGE_ASPECT_COLOR_BIT) { VkClearAttachment &attachment = attachments[numAttachments++]; @@ -442,7 +443,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c attachment.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; } if (c.clear.clearMask & VK_IMAGE_ASPECT_STENCIL_BIT) { - attachment.clearValue.depthStencil.stencil = c.clear.clearStencil; + attachment.clearValue.depthStencil.stencil = (uint32_t)c.clear.clearStencil; attachment.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; } } diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index 4683807bb0..253627888d 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -194,7 +194,7 @@ void VulkanRenderManager::CreateBackbuffers() { run_ = true; // Won't necessarily be 0. threadInitFrame_ = vulkan_->GetCurFrame(); - VLOG("starting thread"); + ILOG("Starting Vulkan submission thread"); thread_ = std::thread(&VulkanRenderManager::ThreadFunc, this); } } @@ -215,7 +215,7 @@ void VulkanRenderManager::StopThread() { } } thread_.join(); - VLOG("thread joined."); + ILOG("Vulkan submission thread joined."); // Wait for any fences to finish and be resignaled, so we don't have sync issues. for (int i = 0; i < vulkan_->GetInflightFrames(); i++) { @@ -228,6 +228,8 @@ void VulkanRenderManager::StopThread() { frameData.push_condVar.wait(lock); } } + } else { + ILOG("Vulkan submission thread was already stopped."); } } @@ -331,6 +333,9 @@ void VulkanRenderManager::BeginFrame() { // Must be after the fence - this performs deletes. VLOG("PUSH: BeginFrame %d", curFrame); + if (!run_) { + WLOG("BeginFrame while !run_!"); + } vulkan_->BeginFrame(); insideFrame_ = true; diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 1925f057c3..fffc1f7a1b 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -193,7 +193,7 @@ public: const std::string &GetSource() const { return source_; } ~VKShaderModule() { if (module_) { - vkDestroyShaderModule(device_, module_, nullptr); + vulkan_->Delete().QueueDeleteShaderModule(module_); } } VkShaderModule Get() const { return module_; } @@ -202,7 +202,7 @@ public: } private: - VkDevice device_; + VulkanContext *vulkan_; VkShaderModule module_; VkShaderStageFlagBits vkstage_; bool ok_; @@ -211,9 +211,9 @@ private: }; bool VKShaderModule::Compile(VulkanContext *vulkan, ShaderLanguage language, const uint8_t *data, size_t size) { + vulkan_ = vulkan; // We'll need this to free it later. - device_ = vulkan->GetDevice(); - this->source_ = (const char *)data; + source_ = (const char *)data; std::vector spirv; if (!GLSLtoSPV(vkstage_, source_.c_str(), spirv)) { return false; diff --git a/ext/native/thread/prioritizedworkqueue.cpp b/ext/native/thread/prioritizedworkqueue.cpp index f3b6d3f0e7..1583738f40 100644 --- a/ext/native/thread/prioritizedworkqueue.cpp +++ b/ext/native/thread/prioritizedworkqueue.cpp @@ -31,7 +31,9 @@ void PrioritizedWorkQueue::Flush() { flush_count++; } queue_.clear(); - ILOG("Flushed %d un-executed tasks", flush_count); + if (flush_count > 0) { + ILOG("PrioritizedWorkQueue: Flushed %d un-executed tasks", flush_count); + } } bool PrioritizedWorkQueue::WaitUntilDone(bool all) { From 0a2b20bf59542db8e489ee54d701bb7cb571a290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Nov 2017 17:40:32 +0100 Subject: [PATCH 04/12] More logging and tweaking --- Common/Vulkan/VulkanContext.cpp | 104 ++++++++++++++++++++++- Common/Vulkan/VulkanContext.h | 102 +--------------------- android/jni/app-android.cpp | 4 +- ext/native/gfx_es2/draw_text_android.cpp | 2 +- 4 files changed, 108 insertions(+), 104 deletions(-) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index acc0cbff90..c31ee34647 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -585,14 +585,16 @@ void VulkanContext::InitSurfaceAndroid(ANativeWindow *wnd, int width, int height } void VulkanContext::ReinitSurfaceAndroid(int width, int height) { - ILOG("Destroying and reiniting Android Vulkan surface"); if (surface_ != VK_NULL_HANDLE) { + ILOG("Destroying Android Vulkan surface (%d, %d)", width_, height_); vkDestroySurfaceKHR(instance_, surface_, nullptr); surface_ = VK_NULL_HANDLE; } VkResult U_ASSERT_ONLY res; + ILOG("Creating Android Vulkan surface (%d, %d)", width, height); + VkAndroidSurfaceCreateInfoKHR android = { VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR }; android.flags = 0; android.window = native_window; @@ -970,3 +972,103 @@ const char *VulkanResultToString(VkResult res) { return "VK_ERROR_...(unknown)"; } } + +void VulkanDeleteList::Take(VulkanDeleteList &del) { + assert(cmdPools_.size() == 0); + assert(descPools_.size() == 0); + assert(modules_.size() == 0); + assert(buffers_.size() == 0); + assert(bufferViews_.size() == 0); + assert(images_.size() == 0); + assert(imageViews_.size() == 0); + assert(deviceMemory_.size() == 0); + assert(samplers_.size() == 0); + assert(pipelines_.size() == 0); + assert(pipelineCaches_.size() == 0); + assert(renderPasses_.size() == 0); + assert(framebuffers_.size() == 0); + assert(callbacks_.size() == 0); + cmdPools_ = std::move(del.cmdPools_); + descPools_ = std::move(del.descPools_); + modules_ = std::move(del.modules_); + buffers_ = std::move(del.buffers_); + bufferViews_ = std::move(del.bufferViews_); + images_ = std::move(del.images_); + imageViews_ = std::move(del.imageViews_); + deviceMemory_ = std::move(del.deviceMemory_); + samplers_ = std::move(del.samplers_); + pipelines_ = std::move(del.pipelines_); + pipelineCaches_ = std::move(del.pipelineCaches_); + renderPasses_ = std::move(del.renderPasses_); + framebuffers_ = std::move(del.framebuffers_); + pipelineLayouts_ = std::move(del.pipelineLayouts_); + descSetLayouts_ = std::move(del.descSetLayouts_); + callbacks_ = std::move(del.callbacks_); +} + +void VulkanDeleteList::PerformDeletes(VkDevice device) { + for (auto &cmdPool : cmdPools_) { + vkDestroyCommandPool(device, cmdPool, nullptr); + } + cmdPools_.clear(); + for (auto &descPool : descPools_) { + vkDestroyDescriptorPool(device, descPool, nullptr); + } + descPools_.clear(); + for (auto &module : modules_) { + vkDestroyShaderModule(device, module, nullptr); + } + modules_.clear(); + for (auto &buf : buffers_) { + vkDestroyBuffer(device, buf, nullptr); + } + buffers_.clear(); + for (auto &bufView : bufferViews_) { + vkDestroyBufferView(device, bufView, nullptr); + } + bufferViews_.clear(); + for (auto &image : images_) { + vkDestroyImage(device, image, nullptr); + } + images_.clear(); + for (auto &imageView : imageViews_) { + vkDestroyImageView(device, imageView, nullptr); + } + imageViews_.clear(); + for (auto &mem : deviceMemory_) { + vkFreeMemory(device, mem, nullptr); + } + deviceMemory_.clear(); + for (auto &sampler : samplers_) { + vkDestroySampler(device, sampler, nullptr); + } + samplers_.clear(); + for (auto &pipeline : pipelines_) { + vkDestroyPipeline(device, pipeline, nullptr); + } + pipelines_.clear(); + for (auto &pcache : pipelineCaches_) { + vkDestroyPipelineCache(device, pcache, nullptr); + } + pipelineCaches_.clear(); + for (auto &renderPass : renderPasses_) { + vkDestroyRenderPass(device, renderPass, nullptr); + } + renderPasses_.clear(); + for (auto &framebuffer : framebuffers_) { + vkDestroyFramebuffer(device, framebuffer, nullptr); + } + framebuffers_.clear(); + for (auto &pipeLayout : pipelineLayouts_) { + vkDestroyPipelineLayout(device, pipeLayout, nullptr); + } + pipelineLayouts_.clear(); + for (auto &descSetLayout : descSetLayouts_) { + vkDestroyDescriptorSetLayout(device, descSetLayout, nullptr); + } + descSetLayouts_.clear(); + for (auto &callback : callbacks_) { + callback.func(callback.userdata); + } + callbacks_.clear(); +} diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index 4b195ad1de..07f82ead75 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -89,106 +89,8 @@ public: void QueueDeleteDescriptorSetLayout(VkDescriptorSetLayout &descSetLayout) { descSetLayouts_.push_back(descSetLayout); descSetLayout = VK_NULL_HANDLE; } void QueueCallback(void(*func)(void *userdata), void *userdata) { callbacks_.push_back(Callback(func, userdata)); } - void Take(VulkanDeleteList &del) { - assert(cmdPools_.size() == 0); - assert(descPools_.size() == 0); - assert(modules_.size() == 0); - assert(buffers_.size() == 0); - assert(bufferViews_.size() == 0); - assert(images_.size() == 0); - assert(imageViews_.size() == 0); - assert(deviceMemory_.size() == 0); - assert(samplers_.size() == 0); - assert(pipelines_.size() == 0); - assert(pipelineCaches_.size() == 0); - assert(renderPasses_.size() == 0); - assert(framebuffers_.size() == 0); - assert(callbacks_.size() == 0); - cmdPools_ = std::move(del.cmdPools_); - descPools_ = std::move(del.descPools_); - modules_ = std::move(del.modules_); - buffers_ = std::move(del.buffers_); - bufferViews_ = std::move(del.bufferViews_); - images_ = std::move(del.images_); - imageViews_ = std::move(del.imageViews_); - deviceMemory_ = std::move(del.deviceMemory_); - samplers_ = std::move(del.samplers_); - pipelines_ = std::move(del.pipelines_); - pipelineCaches_ = std::move(del.pipelineCaches_); - renderPasses_ = std::move(del.renderPasses_); - framebuffers_ = std::move(del.framebuffers_); - pipelineLayouts_ = std::move(del.pipelineLayouts_); - descSetLayouts_ = std::move(del.descSetLayouts_); - callbacks_ = std::move(del.callbacks_); - } - - void PerformDeletes(VkDevice device) { - ILOG("PerformDeletes"); - for (auto &cmdPool : cmdPools_) { - vkDestroyCommandPool(device, cmdPool, nullptr); - } - cmdPools_.clear(); - for (auto &descPool : descPools_) { - vkDestroyDescriptorPool(device, descPool, nullptr); - } - descPools_.clear(); - for (auto &module : modules_) { - vkDestroyShaderModule(device, module, nullptr); - } - modules_.clear(); - for (auto &buf : buffers_) { - vkDestroyBuffer(device, buf, nullptr); - } - buffers_.clear(); - for (auto &bufView : bufferViews_) { - vkDestroyBufferView(device, bufView, nullptr); - } - bufferViews_.clear(); - for (auto &image : images_) { - vkDestroyImage(device, image, nullptr); - } - images_.clear(); - for (auto &imageView : imageViews_) { - vkDestroyImageView(device, imageView, nullptr); - } - imageViews_.clear(); - for (auto &mem : deviceMemory_) { - vkFreeMemory(device, mem, nullptr); - } - deviceMemory_.clear(); - for (auto &sampler : samplers_) { - vkDestroySampler(device, sampler, nullptr); - } - samplers_.clear(); - for (auto &pipeline : pipelines_) { - vkDestroyPipeline(device, pipeline, nullptr); - } - pipelines_.clear(); - for (auto &pcache : pipelineCaches_) { - vkDestroyPipelineCache(device, pcache, nullptr); - } - pipelineCaches_.clear(); - for (auto &renderPass : renderPasses_) { - vkDestroyRenderPass(device, renderPass, nullptr); - } - renderPasses_.clear(); - for (auto &framebuffer : framebuffers_) { - vkDestroyFramebuffer(device, framebuffer, nullptr); - } - framebuffers_.clear(); - for (auto &pipeLayout : pipelineLayouts_) { - vkDestroyPipelineLayout(device, pipeLayout, nullptr); - } - pipelineLayouts_.clear(); - for (auto &descSetLayout : descSetLayouts_) { - vkDestroyDescriptorSetLayout(device, descSetLayout, nullptr); - } - descSetLayouts_.clear(); - for (auto &callback : callbacks_) { - callback.func(callback.userdata); - } - callbacks_.clear(); - } + void Take(VulkanDeleteList &del); + void PerformDeletes(VkDevice device); private: std::vector cmdPools_; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 5e0f183d65..4ce9411e71 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -359,7 +359,7 @@ void AndroidVulkanContext::SwapBuffers() { } void AndroidVulkanContext::Resize() { - ILOG("AndroidVulkanContext::Resize begin"); + ILOG("AndroidVulkanContext::Resize begin (%d, %d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); g_Vulkan->DestroyObjects(); @@ -368,7 +368,7 @@ void AndroidVulkanContext::Resize() { g_Vulkan->ReinitSurfaceAndroid(pixel_xres, pixel_yres); g_Vulkan->InitObjects(); draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); - ILOG("AndroidVulkanContext::Resize end"); + ILOG("AndroidVulkanContext::Resize end (%d, %d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); } void AndroidVulkanContext::SwapInterval(int interval) { diff --git a/ext/native/gfx_es2/draw_text_android.cpp b/ext/native/gfx_es2/draw_text_android.cpp index cb5ab910a2..b5628872cd 100644 --- a/ext/native/gfx_es2/draw_text_android.cpp +++ b/ext/native/gfx_es2/draw_text_android.cpp @@ -269,7 +269,7 @@ void TextDrawerAndroid::OncePerFrame() { // If DPI changed (small-mode, future proper monitor DPI support), drop everything. float newDpiScale = CalculateDPIScale(); if (newDpiScale != dpiScale_) { - ILOG("Scale changed - wiping cache"); + ILOG("DPI Scale changed (%f to %f) - wiping font cache", dpiScale_, newDpiScale); dpiScale_ = newDpiScale; ClearCache(); fontMap_.clear(); // size is precomputed using dpiScale_. From f3eeafc728cbf5207127bdd1963effd4c244b08e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Nov 2017 12:37:54 +0100 Subject: [PATCH 05/12] Change Android logging ID from "NativeApp" to "PPSSPP" --- ext/native/base/logging.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/native/base/logging.h b/ext/native/base/logging.h index 6650d865b9..3bbff36204 100644 --- a/ext/native/base/logging.h +++ b/ext/native/base/logging.h @@ -53,7 +53,7 @@ void OutputDebugStringUTF8(const char *p); // Must only be used for logging #ifndef APP_NAME -#define APP_NAME "NativeApp" +#define APP_NAME "PPSSPP" #endif #ifdef _DEBUG From 3cc5d8f40a9753767273a0858faa1c005f5d94c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Nov 2017 12:40:51 +0100 Subject: [PATCH 06/12] More minor vulkan fixes and cleanups. Don't actually call "Resized" if the size stays the same. --- GPU/Vulkan/DrawEngineVulkan.cpp | 9 +++--- GPU/Vulkan/TextureCacheVulkan.cpp | 38 ++++++++---------------- GPU/Vulkan/TextureCacheVulkan.h | 14 ++++----- android/jni/app-android.cpp | 7 ++++- ext/native/gfx_es2/draw_text_android.cpp | 3 +- 5 files changed, 33 insertions(+), 38 deletions(-) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 22ff3d91b7..d63eb72c91 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -93,8 +93,6 @@ DrawEngineVulkan::DrawEngineVulkan(VulkanContext *vulkan, Draw::DrawContext *dra indexGen.Setup(decIndex); InitDeviceObjects(); - - tessDataTransfer = new TessellationDataTransferVulkan(vulkan, draw); } void DrawEngineVulkan::InitDeviceObjects() { @@ -206,6 +204,8 @@ void DrawEngineVulkan::InitDeviceObjects() { assert(VK_SUCCESS == res); vertexCache_ = new VulkanPushBuffer(vulkan_, VERTEX_CACHE_SIZE); + + tessDataTransfer = new TessellationDataTransferVulkan(vulkan_, draw_); } DrawEngineVulkan::~DrawEngineVulkan() { @@ -214,8 +214,6 @@ DrawEngineVulkan::~DrawEngineVulkan() { FreeMemoryPages(splineBuffer, SPLINE_BUFFER_SIZE); DestroyDeviceObjects(); - - delete tessDataTransfer; } void DrawEngineVulkan::FrameData::Destroy(VulkanContext *vulkan) { @@ -241,6 +239,9 @@ void DrawEngineVulkan::FrameData::Destroy(VulkanContext *vulkan) { } void DrawEngineVulkan::DestroyDeviceObjects() { + delete tessDataTransfer; + tessDataTransfer = nullptr; + for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { frame_[i].Destroy(vulkan_); } diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index dfbf2e64cf..c5ec5d708e 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -126,36 +126,14 @@ void SamplerCache::DeviceRestore(VulkanContext *vulkan) { TextureCacheVulkan::TextureCacheVulkan(Draw::DrawContext *draw, VulkanContext *vulkan) : TextureCacheCommon(draw), vulkan_(vulkan), - samplerCache_(vulkan), - texelsScaledThisFrame_(0) { + samplerCache_(vulkan) { timesInvalidatedAllThisFrame_ = 0; - lastBoundTexture = nullptr; - allocator_ = new VulkanDeviceAllocator(vulkan_, TEXCACHE_MIN_SLAB_SIZE, TEXCACHE_MAX_SLAB_SIZE); - - VkSamplerCreateInfo samp{ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; - samp.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samp.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samp.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samp.magFilter = VK_FILTER_NEAREST; - samp.minFilter = VK_FILTER_NEAREST; - samp.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; - vkCreateSampler(vulkan_->GetDevice(), &samp, nullptr, &samplerNearest_); + DeviceRestore(vulkan, draw); SetupTextureDecoder(); } TextureCacheVulkan::~TextureCacheVulkan() { - vulkan_->Delete().QueueDeleteSampler(samplerNearest_); - Clear(true); - - if (allocator_) { - allocator_->Destroy(); - - // We have to delete on queue, so this can free its queued deletions. - vulkan_->Delete().QueueCallback([](void *ptr) { - auto allocator = static_cast(ptr); - delete allocator; - }, allocator_); - } + DeviceLost(); } void TextureCacheVulkan::SetFramebufferManager(FramebufferManagerVulkan *fbManager) { @@ -183,6 +161,7 @@ void TextureCacheVulkan::DeviceLost() { } samplerCache_.DeviceLost(); + vulkan_->Delete().QueueDeleteSampler(samplerNearest_); nextTexture_ = nullptr; } @@ -195,6 +174,15 @@ void TextureCacheVulkan::DeviceRestore(VulkanContext *vulkan, Draw::DrawContext allocator_ = new VulkanDeviceAllocator(vulkan_, TEXCACHE_MIN_SLAB_SIZE, TEXCACHE_MAX_SLAB_SIZE); samplerCache_.DeviceRestore(vulkan); + + VkSamplerCreateInfo samp{ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; + samp.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samp.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samp.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samp.magFilter = VK_FILTER_NEAREST; + samp.minFilter = VK_FILTER_NEAREST; + samp.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + vkCreateSampler(vulkan_->GetDevice(), &samp, nullptr, &samplerNearest_); } void TextureCacheVulkan::ReleaseTexture(TexCacheEntry *entry, bool delete_them) { diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 52d8055bb6..fa2b070bfe 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -122,19 +122,19 @@ private: void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; - VulkanContext *vulkan_; - VulkanDeviceAllocator *allocator_; - VulkanPushBuffer *push_; + VulkanContext *vulkan_ = nullptr; + VulkanDeviceAllocator *allocator_ = nullptr; + VulkanPushBuffer *push_ = nullptr; SamplerCache samplerCache_; TextureScalerVulkan scaler; - CachedTextureVulkan *lastBoundTexture; + CachedTextureVulkan *lastBoundTexture = nullptr; - int decimationCounter_; - int texelsScaledThisFrame_; - int timesInvalidatedAllThisFrame_; + int decimationCounter_ = 0; + int texelsScaledThisFrame_ = 0; + int timesInvalidatedAllThisFrame_ = 0; FramebufferManagerVulkan *framebufferManagerVulkan_; DepalShaderCacheVulkan *depalShaderCache_; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 4ce9411e71..27637ecf3d 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -741,6 +741,8 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv *, jclass, jint bufw, jint bufh, jint format) { ILOG("NativeApp.backbufferResize(%d x %d)", bufw, bufh); + bool new_size = pixel_xres != bufw || pixel_yres != bufh; + // pixel_*res is the backbuffer resolution. pixel_xres = bufw; pixel_yres = bufh; @@ -767,7 +769,10 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv ILOG("dp_xres=%d dp_yres=%d", dp_xres, dp_yres); ILOG("pixel_xres=%d pixel_yres=%d", pixel_xres, pixel_yres); - NativeResized(); + if (new_size) { + ILOG("Size change detected - calling NativeResized()"); + NativeResized(); + } } diff --git a/ext/native/gfx_es2/draw_text_android.cpp b/ext/native/gfx_es2/draw_text_android.cpp index b5628872cd..4ed14cbc55 100644 --- a/ext/native/gfx_es2/draw_text_android.cpp +++ b/ext/native/gfx_es2/draw_text_android.cpp @@ -269,7 +269,8 @@ void TextDrawerAndroid::OncePerFrame() { // If DPI changed (small-mode, future proper monitor DPI support), drop everything. float newDpiScale = CalculateDPIScale(); if (newDpiScale != dpiScale_) { - ILOG("DPI Scale changed (%f to %f) - wiping font cache", dpiScale_, newDpiScale); + // TODO: Don't bother if it's a no-op (cache already empty) + ILOG("DPI Scale changed (%f to %f) - wiping font cache (%d items, %d fonts)", dpiScale_, newDpiScale, (int)cache_.size(), (int)fontMap_.size()); dpiScale_ = newDpiScale; ClearCache(); fontMap_.clear(); // size is precomputed using dpiScale_. From ee768ca9494f5d2a3b969d47862e544d60591d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Nov 2017 13:02:24 +0100 Subject: [PATCH 07/12] Logging improvements, avoid resetting the Android text drawer unnecessarily --- Common/Vulkan/VulkanContext.cpp | 14 ++++++++++++-- android/jni/app-android.cpp | 5 +++-- android/src/org/ppsspp/ppsspp/NativeActivity.java | 2 +- ext/native/gfx_es2/draw_text_android.cpp | 3 ++- ext/native/thin3d/VulkanQueueRunner.cpp | 6 +++--- 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index c31ee34647..a0f17daaf2 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -65,6 +65,16 @@ std::string VulkanVendorString(uint32_t vendorId) { } } +const char *PresentModeString(VkPresentModeKHR presentMode) { + switch (presentMode) { + case VK_PRESENT_MODE_IMMEDIATE_KHR: return "IMMEDIATE"; + case VK_PRESENT_MODE_MAILBOX_KHR: return "MAILBOX"; + case VK_PRESENT_MODE_FIFO_KHR: return "FIFO"; + case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return "FIFO_RELAXED"; + default: return "UNKNOWN"; + } +} + VulkanContext::VulkanContext() { if (!VulkanLoad()) { init_error_ = "Failed to load Vulkan driver library"; @@ -719,7 +729,7 @@ bool VulkanContext::InitSwapchain() { // to fall back in a sensible way. VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR; for (size_t i = 0; i < presentModeCount; i++) { - ILOG("Supported present mode: %d", presentModes[i]); + ILOG("Supported present mode: %d (%s)", presentModes[i], PresentModeString(presentModes[i])); } for (size_t i = 0; i < presentModeCount; i++) { if (swapchainPresentMode == VK_PRESENT_MODE_MAX_ENUM_KHR) { @@ -743,7 +753,7 @@ bool VulkanContext::InitSwapchain() { // HACK swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; #endif - ILOG("Chosen present mode: %d", swapchainPresentMode); + ILOG("Chosen present mode: %d (%s)", swapchainPresentMode, PresentModeString(swapchainPresentMode)); delete[] presentModes; // Determine the number of VkImage's to use in the swap chain (we desire to // own only 1 image at a time, besides the images being displayed and diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 27637ecf3d..15adb0a638 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -742,7 +742,8 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv ILOG("NativeApp.backbufferResize(%d x %d)", bufw, bufh); bool new_size = pixel_xres != bufw || pixel_yres != bufh; - + int old_w = pixel_xres; + int old_h = pixel_yres; // pixel_*res is the backbuffer resolution. pixel_xres = bufw; pixel_yres = bufh; @@ -770,7 +771,7 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv ILOG("pixel_xres=%d pixel_yres=%d", pixel_xres, pixel_yres); if (new_size) { - ILOG("Size change detected - calling NativeResized()"); + ILOG("Size change detected (previously %d,%d) - calling NativeResized()", old_w, old_h); NativeResized(); } } diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 59738c8418..ac68259a45 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -58,7 +58,7 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C // Remember to loadLibrary your JNI .so in a static {} block // Adjust these as necessary - private static String TAG = "NativeActivity"; + private static String TAG = "PPSSPPNativeActivity"; // Allows us to skip a lot of initialization on secondary calls to onCreate. private static boolean initialized = false; diff --git a/ext/native/gfx_es2/draw_text_android.cpp b/ext/native/gfx_es2/draw_text_android.cpp index 4ed14cbc55..c8e7ed1925 100644 --- a/ext/native/gfx_es2/draw_text_android.cpp +++ b/ext/native/gfx_es2/draw_text_android.cpp @@ -29,7 +29,8 @@ TextDrawerAndroid::TextDrawerAndroid(Draw::DrawContext *draw) : TextDrawer(draw) } else { ELOG("Failed to find class: '%s'", textRendererClassName); } - dpiScale_ = 1.0f; + dpiScale_ = CalculateDPIScale(); + ILOG("Initializing TextDrawerAndroid with DPI scale %f", dpiScale_); } TextDrawerAndroid::~TextDrawerAndroid() { diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 4b566d12e6..bcaaf086a3 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -2,14 +2,14 @@ #include "VulkanQueueRunner.h" #include "VulkanRenderManager.h" -// Debug help: adb logcat -s DEBUG NativeActivity NativeApp PPSSPP +// Debug help: adb logcat -s DEBUG PPSSPPNativeActivity PPSSPP // TODO: This is only enough for 4x render resolution / 4x texture upscale for debugger. // Maybe we should use a dynamically allocated one for larger? const uint32_t readbackBufferSize = 2048 * 2048 * 4; void VulkanQueueRunner::CreateDeviceObjects() { - ILOG("VulkanQueueRuner::CreateDeviceObjects"); + ILOG("VulkanQueueRunner::CreateDeviceObjects"); InitBackbufferRenderPass(); InitRenderpasses(); @@ -37,7 +37,7 @@ void VulkanQueueRunner::CreateDeviceObjects() { } void VulkanQueueRunner::DestroyDeviceObjects() { - ILOG("VulkanQueueRuner::DestroyDeviceObjects"); + ILOG("VulkanQueueRunner::DestroyDeviceObjects"); VkDevice device = vulkan_->GetDevice(); vulkan_->Delete().QueueDeleteDeviceMemory(readbackMemory_); vkFreeMemory(device, readbackMemory_, nullptr); From 1c76d288431173460db7df5232cdf3ef7874d609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Nov 2017 13:13:56 +0100 Subject: [PATCH 08/12] Avoid double-initializing the Vulkan backbuffer on startup. --- Core/Core.cpp | 2 +- UI/NativeApp.cpp | 12 +++++++++++- android/jni/app-android.cpp | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Core/Core.cpp b/Core/Core.cpp index 55783375a8..73696842f6 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -172,7 +172,7 @@ bool UpdateScreenScale(int width, int height) { dp_yres = new_dp_yres; pixel_xres = width; pixel_yres = height; - INFO_LOG(SYSTEM, "pixel_res: %dx%d", pixel_xres, pixel_yres); + INFO_LOG(SYSTEM, "pixel_res: %dx%d. Calling NativeResized()", pixel_xres, pixel_yres); NativeResized(); return true; } diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index b97edf440d..d4fa2c65ee 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -127,6 +127,8 @@ std::unique_ptr uiTexture; ScreenManager *screenManager; std::string config_filename; +bool g_graphicsInited; + #ifdef IOS bool iosCanUseJit; bool targetIsJailbroken; @@ -675,10 +677,13 @@ void NativeInitGraphics(GraphicsContext *graphicsContext) { #endif g_gameInfoCache = new GameInfoCache(); + + g_graphicsInited = true; ILOG("NativeInitGraphics completed"); } void NativeShutdownGraphics() { + g_graphicsInited = false; ILOG("NativeShutdownGraphics"); #ifdef _WIN32 @@ -817,6 +822,7 @@ void NativeRender(GraphicsContext *graphicsContext) { } if (resized) { + ILOG("resized was set to true - resizing"); resized = false; if (uiContext) { @@ -1072,7 +1078,11 @@ void NativeMessageReceived(const char *message, const char *value) { void NativeResized() { // NativeResized can come from any thread so we just set a flag, then process it later. - resized = true; + if (g_graphicsInited) { + resized = true; + } else { + ILOG("NativeResized ignored, not initialized"); + } } void NativeSetRestarting() { diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 15adb0a638..d1260fce3c 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -773,6 +773,8 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv if (new_size) { ILOG("Size change detected (previously %d,%d) - calling NativeResized()", old_w, old_h); NativeResized(); + } else { + ILOG("Size didn't change."); } } From 378e01625c9abb05149d33439d047afbe7974e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Nov 2017 15:10:36 +0100 Subject: [PATCH 09/12] Fix a few more device-loss bugs. --- GPU/Vulkan/DrawEngineVulkan.cpp | 3 +-- GPU/Vulkan/GPU_Vulkan.h | 2 -- UI/NativeApp.cpp | 6 ++++++ ext/native/thin3d/VulkanRenderManager.cpp | 26 ++++++++++++++++++----- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index d63eb72c91..c4d2b9400a 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -251,10 +251,8 @@ void DrawEngineVulkan::DestroyDeviceObjects() { vulkan_->Delete().QueueDeleteSampler(nullSampler_); if (pipelineLayout_ != VK_NULL_HANDLE) vulkan_->Delete().QueueDeletePipelineLayout(pipelineLayout_); - pipelineLayout_ = VK_NULL_HANDLE; if (descriptorSetLayout_ != VK_NULL_HANDLE) vulkan_->Delete().QueueDeleteDescriptorSetLayout(descriptorSetLayout_); - descriptorSetLayout_ = VK_NULL_HANDLE; if (nullTexture_) { nullTexture_->Destroy(); delete nullTexture_; @@ -263,6 +261,7 @@ void DrawEngineVulkan::DestroyDeviceObjects() { vertexCache_->Destroy(vulkan_); delete vertexCache_; vertexCache_ = nullptr; + vai_.Clear(); // Need to clear this to get rid of all remaining references to the dead buffers. } void DrawEngineVulkan::DeviceLost() { diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 289a8463f1..d94c4ee768 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -119,8 +119,6 @@ private: // Manages state and pipeline objects PipelineManagerVulkan *pipelineManager_; - int lastVsync_; - VkCommandBuffer curCmd_; int vertexCost_ = 0; std::string reportingPrimaryInfo_; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index d4fa2c65ee..3c54be8a3c 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -845,6 +845,12 @@ void NativeRender(GraphicsContext *graphicsContext) { 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) { diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index 253627888d..c2fce09b6f 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -194,7 +194,7 @@ void VulkanRenderManager::CreateBackbuffers() { run_ = true; // Won't necessarily be 0. threadInitFrame_ = vulkan_->GetCurFrame(); - ILOG("Starting Vulkan submission thread"); + ILOG("Starting Vulkan submission thread (threadInitFrame_ = %d)", vulkan_->GetCurFrame()); thread_ = std::thread(&VulkanRenderManager::ThreadFunc, this); } } @@ -215,12 +215,21 @@ void VulkanRenderManager::StopThread() { } } thread_.join(); - ILOG("Vulkan submission thread joined."); + ILOG("Vulkan submission thread joined. Frame=%d", vulkan_->GetCurFrame()); + + // Eat whatever has been queued up for this frame if anything. + Wipe(); // Wait for any fences to finish and be resignaled, so we don't have sync issues. + // Also clean out any queued data, which might refer to things that might not be valid + // when we restart... for (int i = 0; i < vulkan_->GetInflightFrames(); i++) { auto &frameData = frameData_[i]; + if (frameData.readyForRun || frameData.hasInitCommands || frameData.steps.size() != 0) { + Crash(); + } frameData.readyForRun = false; + frameData.steps.clear(); std::unique_lock lock(frameData.push_mutex); while (!frameData.readyForFence) { @@ -277,6 +286,7 @@ void VulkanRenderManager::ThreadFunc() { setCurrentThreadName("RenderMan"); int threadFrame = threadInitFrame_; bool nextFrame = false; + bool firstFrame = true; while (true) { { if (nextFrame) { @@ -304,9 +314,17 @@ void VulkanRenderManager::ThreadFunc() { assert(frameData.type == VKRRunType::END || frameData.type == VKRRunType::SYNC); } VLOG("PULL: Running frame %d", threadFrame); + if (firstFrame) { + ILOG("Running first frame (%d)", threadFrame); + firstFrame = false; + } Run(threadFrame); VLOG("PULL: Finished frame %d", threadFrame); } + + // Wait for the device to be done with everything, before tearing stuff down. + vkDeviceWaitIdle(vulkan_->GetDevice()); + VLOG("PULL: Quitting"); } @@ -374,9 +392,7 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR curRenderStep_ = nullptr; } if (curRenderStep_ && curRenderStep_->commands.size() == 0) { -#ifdef _DEBUG - ILOG("Empty render step. Usually happens after uploading pixels.."); -#endif + VLOG("Empty render step. Usually happens after uploading pixels.."); } VKRStep *step = new VKRStep{ VKRStepType::RENDER }; From c32f505b58831b9ca4fa21cb67037316ed761680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Nov 2017 15:45:14 +0100 Subject: [PATCH 10/12] Fix race condition. --- android/src/org/ppsspp/ppsspp/NativeActivity.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index ac68259a45..984ec4ff13 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -518,24 +518,29 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C } } + Point desiredSize = new Point(); + @Override public void surfaceCreated(SurfaceHolder holder) { pixelWidth = holder.getSurfaceFrame().width(); pixelHeight = holder.getSurfaceFrame().height(); Log.d(TAG, "Surface created. pixelWidth=" + pixelWidth + ", pixelHeight=" + pixelHeight); NativeApp.setDisplayParameters(pixelWidth, pixelHeight, (int)densityDpi, refreshRate); - Point sz = new Point(); - getDesiredBackbufferSize(sz); - Log.d(TAG, "Setting fixed size " + sz.x + " x " + sz.y); + getDesiredBackbufferSize(desiredSize); + Log.d(TAG, "Setting fixed size " + desiredSize.x + " x " + desiredSize.y); if (mGLSurfaceView != null) { - mGLSurfaceView.getHolder().setFixedSize(sz.x, sz.y); + mGLSurfaceView.getHolder().setFixedSize(desiredSize.x, desiredSize.y); } else { - mSurfaceView.getHolder().setFixedSize(sz.x, sz.y); + mSurfaceView.getHolder().setFixedSize(desiredSize.x, desiredSize.y); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + if (width != desiredSize.x || height != desiredSize.y) { + Log.w(TAG, "Surface changed but not to desired size. Ignoring."); + return; + } Log.w(TAG, "Surface changed. Resolution: " + width + "x" + height + " Format: " + format); NativeApp.backbufferResize(width, height, format); mSurface = holder.getSurface(); From 17d624d311c217e9b0a113ec315709a0101ecb38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Nov 2017 15:59:36 +0100 Subject: [PATCH 11/12] Ditch a silly vertex count limit that only makes sense for GLES, so move it there. --- GPU/Common/SoftwareTransformCommon.cpp | 7 ------- GPU/GLES/DrawEngineGLES.cpp | 9 ++++++++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index f55c793c47..fa34e321d5 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -137,13 +137,6 @@ void SoftwareTransform( bool throughmode = (vertType & GE_VTYPE_THROUGH_MASK) != 0; bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled(); - // TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts. - -#if defined(MOBILE_DEVICE) - if (vertexCount > 0x10000/3) - vertexCount = 0x10000/3; -#endif - float uscale = 1.0f; float vscale = 1.0f; if (throughmode) { diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index d917437b83..fe1f1e0653 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -701,8 +701,15 @@ rotateVBO: params.allowSeparateAlphaClear = true; int maxIndex = indexGen.MaxIndex(); + int vertexCount = indexGen.VertexCount(); + + // TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts. +#if defined(MOBILE_DEVICE) + if (vertexCount > 0x10000 / 3) + vertexCount = 0x10000 / 3; +#endif SoftwareTransform( - prim, indexGen.VertexCount(), + prim, vertexCount, dec_->VertexType(), inds, GE_VTYPE_IDX_16BIT, dec_->GetDecVtxFmt(), maxIndex, drawBuffer, numTrans, drawIndexed, ¶ms, &result); ApplyDrawStateLate(); From 3e7d913967e1c9baf8aa8f078cdae4bae756fc75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Nov 2017 16:11:23 +0100 Subject: [PATCH 12/12] Buildfix 32-bit --- GPU/Vulkan/DepalettizeShaderVulkan.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/GPU/Vulkan/DepalettizeShaderVulkan.cpp b/GPU/Vulkan/DepalettizeShaderVulkan.cpp index d4022f86ca..a080b27416 100644 --- a/GPU/Vulkan/DepalettizeShaderVulkan.cpp +++ b/GPU/Vulkan/DepalettizeShaderVulkan.cpp @@ -70,7 +70,6 @@ DepalShaderCacheVulkan::~DepalShaderCacheVulkan() { void DepalShaderCacheVulkan::DeviceLost() { Clear(); vulkan_->Delete().QueueDeleteShaderModule(vshader_); - vshader_ = nullptr; draw_ = nullptr; vulkan_ = nullptr; }