From 9b4bff21f0e6c061cb6b1ef69f0c91bf00852fd8 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Wed, 20 Feb 2019 15:50:36 +0300 Subject: [PATCH] [vulkan] Fixes --- drape/vulkan/vulkan_base_context.cpp | 90 +++++++++++-------- drape/vulkan/vulkan_mesh_object_impl.cpp | 28 +----- drape/vulkan/vulkan_object_manager.cpp | 17 ++-- drape/vulkan/vulkan_object_manager.hpp | 3 +- drape/vulkan/vulkan_pipeline.cpp | 6 +- .../vulkan_vertex_array_buffer_impl.cpp | 17 +--- 6 files changed, 74 insertions(+), 87 deletions(-) diff --git a/drape/vulkan/vulkan_base_context.cpp b/drape/vulkan/vulkan_base_context.cpp index 6aeac77cf3..cc04c38abc 100644 --- a/drape/vulkan/vulkan_base_context.cpp +++ b/drape/vulkan/vulkan_base_context.cpp @@ -111,6 +111,8 @@ void VulkanBaseContext::SetSurface(VkSurfaceKHR surface, VkSurfaceFormatKHR surf m_surface = surface; m_surfaceFormat = surfaceFormat; m_surfaceCapabilities = surfaceCapabilities; + + LOG(LINFO, ("RecreateSwapchainAndDependencies in SetSurface")); RecreateSwapchainAndDependencies(); } @@ -126,17 +128,16 @@ void VulkanBaseContext::ResetSurface(bool allowPipelineDump) void VulkanBaseContext::RecreateSwapchainAndDependencies() { + vkDeviceWaitIdle(m_device); ResetSwapchainAndDependencies(); CreateCommandBuffers(); RecreateDepthTexture(); RecreateSwapchain(); + vkDeviceWaitIdle(m_device); } void VulkanBaseContext::ResetSwapchainAndDependencies() { - if (m_pipeline) - m_pipeline->ResetCache(m_device); - DestroyFramebuffers(); m_depthTexture.reset(); @@ -151,17 +152,10 @@ void VulkanBaseContext::SetRenderingQueue(VkQueue queue) void VulkanBaseContext::Resize(int w, int h) { - if (m_surfaceCapabilities.currentExtent.width == w && - m_surfaceCapabilities.currentExtent.height == h) - { - return; - } - - vkDeviceWaitIdle(m_device); - m_surfaceCapabilities.currentExtent.width = static_cast(w); m_surfaceCapabilities.currentExtent.height = static_cast(h); + LOG(LINFO, ("RecreateSwapchainAndDependencies in Resize")); RecreateSwapchainAndDependencies(); } @@ -178,19 +172,24 @@ bool VulkanBaseContext::BeginRendering() CHECK_VK_CALL(vkResetFences(m_device, 1, &m_fence)); + res = vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX, m_presentComplete, + VK_NULL_HANDLE, &m_imageIndex); + if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR) + { + LOG(LINFO, ("RecreateSwapchainAndDependencies in BeginRendering")); + RecreateSwapchainAndDependencies(); + } + else + { + CHECK_RESULT_VK_CALL(vkAcquireNextImageKHR, res); + } + VkCommandBufferBeginInfo commandBufferBeginInfo = {}; commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; CHECK_VK_CALL(vkBeginCommandBuffer(m_memoryCommandBuffer, &commandBufferBeginInfo)); CHECK_VK_CALL(vkBeginCommandBuffer(m_renderingCommandBuffer, &commandBufferBeginInfo)); - res = vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX, m_presentComplete, - VK_NULL_HANDLE, &m_imageIndex); - if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR) - RecreateSwapchainAndDependencies(); - else - CHECK_RESULT_VK_CALL(vkAcquireNextImageKHR, res); - return true; } @@ -373,28 +372,37 @@ void VulkanBaseContext::Present() submitInfo.commandBufferCount = 2; submitInfo.pCommandBuffers = commandBuffers; - CHECK_VK_CALL(vkQueueSubmit(m_queue, 1, &submitInfo, m_fence)); - - VkPresentInfoKHR presentInfo = {}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - presentInfo.pNext = nullptr; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = &m_swapchain; - presentInfo.pImageIndices = &m_imageIndex; - presentInfo.pWaitSemaphores = &m_renderComplete; - presentInfo.waitSemaphoreCount = 1; - - VkResult res = vkQueuePresentKHR(m_queue, &presentInfo); - if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR) - { - if (res == VK_ERROR_OUT_OF_DATE_KHR) - RecreateSwapchainAndDependencies(); - else - CHECK_RESULT_VK_CALL(vkQueuePresentKHR, res); - } - // For commands that wait indefinitely for device execution // a return value of VK_ERROR_DEVICE_LOST is equivalent to VK_SUCCESS. + VkResult res = vkQueueSubmit(m_queue, 1, &submitInfo, m_fence); + if (res != VK_ERROR_DEVICE_LOST) + { + CHECK_RESULT_VK_CALL(vkQueueSubmit, res); + + VkPresentInfoKHR presentInfo = {}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.pNext = nullptr; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &m_swapchain; + presentInfo.pImageIndices = &m_imageIndex; + presentInfo.pWaitSemaphores = &m_renderComplete; + presentInfo.waitSemaphoreCount = 1; + + res = vkQueuePresentKHR(m_queue, &presentInfo); + if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR) + { + if (res == VK_ERROR_OUT_OF_DATE_KHR) + { + vkQueueWaitIdle(m_queue); + LOG(LINFO, ("RecreateSwapchainAndDependencies in Present")); + RecreateSwapchainAndDependencies(); + } + else + { + CHECK_RESULT_VK_CALL(vkQueuePresentKHR, res); + } + } + } res = vkQueueWaitIdle(m_queue); if (res != VK_SUCCESS && res != VK_ERROR_DEVICE_LOST) CHECK_RESULT_VK_CALL(vkQueueWaitIdle, res); @@ -406,11 +414,12 @@ void VulkanBaseContext::Present() // only after the finishing of rendering. It prevents data collisions. m_defaultStagingBuffer->Reset(); + m_objectManager->CollectObjectsSync(); static uint8_t framesCounter = 0; if (framesCounter % 10 == 0) { framesCounter = 0; - DrapeRoutine::Run([this]() { m_objectManager->CollectObjects(); }); + DrapeRoutine::Run([this]() { m_objectManager->CollectObjectsAsync(); }); } else { @@ -757,6 +766,9 @@ void VulkanBaseContext::DestroySwapchain() void VulkanBaseContext::DestroyFramebuffers() { + if (m_pipeline) + m_pipeline->ResetCache(m_device); + for (auto & fbData : m_framebuffersData) { for (auto & framebuffer : fbData.second.m_framebuffers) diff --git a/drape/vulkan/vulkan_mesh_object_impl.cpp b/drape/vulkan/vulkan_mesh_object_impl.cpp index 67187c0186..52c4ac9bbc 100644 --- a/drape/vulkan/vulkan_mesh_object_impl.cpp +++ b/drape/vulkan/vulkan_mesh_object_impl.cpp @@ -42,8 +42,6 @@ public: ref_ptr vulkanContext = context; m_objectManager = vulkanContext->GetObjectManager(); - ResetDescriptorSetGroup(); - m_geometryBuffers.resize(m_mesh->m_buffers.size()); m_bindingInfoCount = static_cast(m_mesh->m_buffers.size()); CHECK_LESS_OR_EQUAL(m_bindingInfoCount, kMaxBindingInfo, ()); @@ -75,8 +73,6 @@ public: void Reset() override { - ResetDescriptorSetGroup(); - for (auto const & b : m_geometryBuffers) m_objectManager->DestroyObject(b); m_geometryBuffers.clear(); @@ -84,12 +80,6 @@ public: void ResetCache(dp::RenderState const & state) override { - auto newTex = state.GetColorTexture()->GetHardwareTexture(); - if (newTex != m_lastColorTexture) - { - m_lastColorTexture = newTex; - ResetDescriptorSetGroup(); - } } void UpdateBuffer(ref_ptr context, uint32_t bufferInd) override @@ -163,13 +153,12 @@ public: vulkanContext->SetPrimitiveTopology(GetPrimitiveType(m_mesh->m_drawPrimitive)); vulkanContext->SetBindingInfo(m_bindingInfo, m_bindingInfoCount); - if (!m_descriptorSetGroup) - m_descriptorSetGroup = vulkanContext->GetCurrentDescriptorSetGroup(); + auto descriptorSetGroup = vulkanContext->GetCurrentDescriptorSetGroup(); uint32_t dynamicOffset = vulkanContext->GetCurrentDynamicBufferOffset(); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkanContext->GetCurrentPipelineLayout(), 0, 1, - &m_descriptorSetGroup.m_descriptorSet, 1, &dynamicOffset); + &descriptorSetGroup.m_descriptorSet, 1, &dynamicOffset); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkanContext->GetCurrentPipeline()); @@ -179,28 +168,19 @@ public: vkCmdBindVertexBuffers(commandBuffer, i, 1, &m_geometryBuffers[i].m_buffer, offsets); vkCmdDraw(commandBuffer, verticesCount, 1, 0, 0); + + m_objectManager->DestroyDescriptorSetGroup(descriptorSetGroup); } void Bind(ref_ptr program) override {} void Unbind() override {} private: - void ResetDescriptorSetGroup() - { - if (!m_descriptorSetGroup) - return; - - m_objectManager->DestroyDescriptorSetGroup(m_descriptorSetGroup); - m_descriptorSetGroup = {}; - } - ref_ptr m_mesh; ref_ptr m_objectManager; std::vector m_geometryBuffers; BindingInfoArray m_bindingInfo; uint8_t m_bindingInfoCount = 0; - DescriptorSetGroup m_descriptorSetGroup; - ref_ptr m_lastColorTexture; }; } // namespace vulkan diff --git a/drape/vulkan/vulkan_object_manager.cpp b/drape/vulkan/vulkan_object_manager.cpp index 1a5247baf7..f0f7b9e6e8 100644 --- a/drape/vulkan/vulkan_object_manager.cpp +++ b/drape/vulkan/vulkan_object_manager.cpp @@ -46,7 +46,8 @@ VulkanObjectManager::VulkanObjectManager(VkDevice device, VkPhysicalDeviceLimits VulkanObjectManager::~VulkanObjectManager() { - CollectObjects(); + CollectObjectsSync(); + CollectObjectsAsync(); for (auto const & s : m_samplers) vkDestroySampler(m_device, s.second, nullptr); @@ -234,21 +235,27 @@ void VulkanObjectManager::DestroyDescriptorSetGroup(DescriptorSetGroup group) m_descriptorsToDestroy.push_back(std::move(group)); } -void VulkanObjectManager::CollectObjects() +void VulkanObjectManager::CollectObjectsSync() { - std::vector queueToDestroy; std::vector descriptorsToDestroy; { std::lock_guard lock(m_destroyMutex); - std::swap(m_queueToDestroy, queueToDestroy); std::swap(m_descriptorsToDestroy, descriptorsToDestroy); } - for (auto const & d : descriptorsToDestroy) { CHECK_VK_CALL(vkFreeDescriptorSets(m_device, d.m_descriptorPool, 1 /* count */, &d.m_descriptorSet)); } +} + +void VulkanObjectManager::CollectObjectsAsync() +{ + std::vector queueToDestroy; + { + std::lock_guard lock(m_destroyMutex); + std::swap(m_queueToDestroy, queueToDestroy); + } if (!queueToDestroy.empty()) { diff --git a/drape/vulkan/vulkan_object_manager.hpp b/drape/vulkan/vulkan_object_manager.hpp index 66ae2148f1..20a2fe41a1 100644 --- a/drape/vulkan/vulkan_object_manager.hpp +++ b/drape/vulkan/vulkan_object_manager.hpp @@ -73,7 +73,8 @@ public: void DestroyObject(VulkanObject object); void DestroyDescriptorSetGroup(DescriptorSetGroup group); - void CollectObjects(); + void CollectObjectsSync(); + void CollectObjectsAsync(); VkDevice GetDevice() const { return m_device; } VulkanMemoryManager const & GetMemoryManager() const { return m_memoryManager; }; diff --git a/drape/vulkan/vulkan_pipeline.cpp b/drape/vulkan/vulkan_pipeline.cpp index 532901bb4b..24bce8fcbf 100644 --- a/drape/vulkan/vulkan_pipeline.cpp +++ b/drape/vulkan/vulkan_pipeline.cpp @@ -238,11 +238,7 @@ void VulkanPipeline::ResetCache(VkDevice device) void VulkanPipeline::Destroy(VkDevice device) { Dump(device); - - for (auto const & p : m_pipelineCache) - vkDestroyPipeline(device, p.second, nullptr); - m_pipelineCache.clear(); - + ResetCache(device); vkDestroyPipelineCache(device, m_vulkanPipelineCache, nullptr); } diff --git a/drape/vulkan/vulkan_vertex_array_buffer_impl.cpp b/drape/vulkan/vulkan_vertex_array_buffer_impl.cpp index 229b3486dd..2cbe1e3110 100644 --- a/drape/vulkan/vulkan_vertex_array_buffer_impl.cpp +++ b/drape/vulkan/vulkan_vertex_array_buffer_impl.cpp @@ -32,15 +32,6 @@ public: , m_bindingInfoCount(bindingInfoCount) {} - ~VulkanVertexArrayBufferImpl() override - { - if (m_descriptorSetGroup) - { - m_objectManager->DestroyDescriptorSetGroup(m_descriptorSetGroup); - m_descriptorSetGroup = {}; - } - } - bool Build(ref_ptr program) override { UNUSED_VALUE(program); @@ -62,13 +53,12 @@ public: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); vulkanContext->SetBindingInfo(m_bindingInfo, m_bindingInfoCount); - if (!m_descriptorSetGroup) - m_descriptorSetGroup = vulkanContext->GetCurrentDescriptorSetGroup(); + auto descriptorSetGroup = vulkanContext->GetCurrentDescriptorSetGroup(); uint32_t dynamicOffset = vulkanContext->GetCurrentDynamicBufferOffset(); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkanContext->GetCurrentPipelineLayout(), 0, 1, - &m_descriptorSetGroup.m_descriptorSet, 1, &dynamicOffset); + &descriptorSetGroup.m_descriptorSet, 1, &dynamicOffset); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkanContext->GetCurrentPipeline()); @@ -96,6 +86,8 @@ public: vkCmdBindIndexBuffer(commandBuffer, vulkanIndexBuffer, 0, indexType); vkCmdDrawIndexed(commandBuffer, range.m_idxCount, 1, range.m_idxStart, 0, 0); + + m_objectManager->DestroyDescriptorSetGroup(descriptorSetGroup); } private: @@ -103,7 +95,6 @@ private: ref_ptr m_objectManager; BindingInfoArray m_bindingInfo; uint8_t m_bindingInfoCount = 0; - DescriptorSetGroup m_descriptorSetGroup; }; } // namespace vulkan