diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index c4a04f90bc..b785d48f3a 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -1261,7 +1261,8 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c if (pipeline != VK_NULL_HANDLE) { vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - pipelineLayout = c.pipeline.pipelineLayout; + pipelineLayout = c.graphics_pipeline.pipelineLayout; + _dbg_assert_(pipelineLayout != VK_NULL_HANDLE); lastGraphicsPipeline = graphicsPipeline; pipelineOK = true; } else { @@ -1283,7 +1284,8 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c VkPipeline pipeline = computePipeline->pipeline->BlockUntilReady(); if (pipeline != VK_NULL_HANDLE) { vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); - pipelineLayout = c.pipeline.pipelineLayout; + pipelineLayout = c.compute_pipeline.pipelineLayout; + _dbg_assert_(pipelineLayout != VK_NULL_HANDLE); lastComputePipeline = computePipeline; } } diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 4414af64f9..8b18b512c1 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -518,12 +518,14 @@ void VulkanRenderManager::CompileThreadFunc() { } void VulkanRenderManager::DrainAndBlockCompileQueue() { + EndCurRenderStep(); std::unique_lock lock(compileMutex_); compileBlocked_ = true; compileCond_.notify_all(); while (!compileQueue_.empty()) { queueRunner_.WaitForCompileNotification(); } + FlushSync(); } void VulkanRenderManager::ReleaseCompileQueue() { @@ -1518,6 +1520,8 @@ void VulkanRenderManager::Run(VKRRenderThreadTask &task) { // Called from main thread. void VulkanRenderManager::FlushSync() { + _dbg_assert_(!curRenderStep_); + if (invalidationCallback_) { invalidationCallback_(InvalidationCallbackFlags::COMMAND_BUFFER_STATE); } diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 10a46ca9ee..5f045f265d 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -167,6 +167,7 @@ void GPU_Vulkan::SaveCache(const Path &filename) { GPU_Vulkan::~GPU_Vulkan() { if (draw_) { VulkanRenderManager *rm = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + // This now also does a hard sync with the render thread, so that we can safely delete our pipeline layout below. rm->DrainAndBlockCompileQueue(); } @@ -427,6 +428,7 @@ void GPU_Vulkan::DeviceLost() { 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. + // So, we have to save it here to be able to call ReleaseCompileQueue(). Draw::DrawContext *draw = draw_; if (draw) { VulkanRenderManager *rm = (VulkanRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index d4851dbc87..dffc575022 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1174,7 +1174,7 @@ void EmuScreen::update() { } } -void EmuScreen::checkPowerDown() { +bool EmuScreen::checkPowerDown() { if (PSP_IsRebooting()) { bootPending_ = true; invalid_ = true; @@ -1188,7 +1188,9 @@ void EmuScreen::checkPowerDown() { screenManager()->switchScreen(new MainScreen()); bootPending_ = false; invalid_ = true; + return true; } + return false; } static const char *CPUCoreAsString(int core) { @@ -1451,6 +1453,7 @@ void EmuScreen::render() { Core_UpdateDebugStats((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS || g_Config.bLogFrameDrops); bool blockedExecution = Achievements::IsBlockingExecution(); + bool rebind = false; if (!blockedExecution) { PSP_BeginHostFrame(); PSP_RunLoopWhileState(); @@ -1487,7 +1490,7 @@ void EmuScreen::render() { // Didn't actually reach the end of the frame, ran out of the blockTicks cycles. // In this case we need to bind and wipe the backbuffer, at least. // It's possible we never ended up outputted anything - make sure we have the backbuffer cleared - thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR }, "EmuScreen_NoFrame"); + rebind = true; break; } @@ -1495,10 +1498,10 @@ void EmuScreen::render() { } // This must happen after PSP_EndHostFrame so that things like push buffers are end-frame'd before we start destroying stuff. - checkPowerDown(); - - if (invalid_) - return; + if (checkPowerDown() || rebind) { + // Shutting down can end up ending the current render pass + thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR }, "EmuScreen_NoFrame"); + } if (hasVisibleUI()) { // In most cases, this should already be bound and a no-op. diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 970844ba18..6dd30aa3ca 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -76,7 +76,7 @@ private: void onVKeyAnalog(int virtualKeyCode, float value); void autoLoad(); - void checkPowerDown(); + bool checkPowerDown(); UI::Event OnDevMenu; UI::Event OnChatMenu; diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 71af97e683..e0ae538222 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -335,6 +335,8 @@ shutdown: g_graphicsContext->Shutdown(); + delete g_graphicsContext; + UpdateConsolePosition(); NativeShutdown();