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 };