diff --git a/lib/graphics_engine/include/ge_vulkan_driver.hpp b/lib/graphics_engine/include/ge_vulkan_driver.hpp index 086ccfcdc..d5d62dede 100644 --- a/lib/graphics_engine/include/ge_vulkan_driver.hpp +++ b/lib/graphics_engine/include/ge_vulkan_driver.hpp @@ -340,7 +340,7 @@ namespace GE unsigned getGraphicsQueueCount() const { return m_graphics_queue_count; } std::unique_lock getGraphicsQueue(VkQueue* queue) const; - void waitIdle(); + void waitIdle(bool flush_command_loader = false); void setDisableWaitIdle(bool val) { m_disable_wait_idle = val; } IrrlichtDevice* getIrrlichtDevice() const { return m_irrlicht_device; } GEVulkanDepthTexture* getDepthTexture() const { return m_depth_texture; } diff --git a/lib/graphics_engine/src/ge_vulkan_command_loader.cpp b/lib/graphics_engine/src/ge_vulkan_command_loader.cpp index 849c82d8b..358cf9ab6 100644 --- a/lib/graphics_engine/src/ge_vulkan_command_loader.cpp +++ b/lib/graphics_engine/src/ge_vulkan_command_loader.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,7 @@ std::atomic_uint g_loader_count(0); std::vector g_command_pools; std::vector g_command_fences; +std::vector > > g_thread_idle; } // GEVulkanCommandLoader // ============================================================================ @@ -84,6 +86,12 @@ void GEVulkanCommandLoader::init(GEVulkanDriver* vk) } } + for (unsigned i = 0; i < thread_count - 1; i++) + { + std::unique_ptr > idle; + idle.reset(new std::atomic(true)); + g_thread_idle.push_back(std::move(idle)); + } g_loader_count.store(thread_count); for (unsigned i = 0; i < thread_count - 1; i++) { @@ -93,6 +101,7 @@ void GEVulkanCommandLoader::init(GEVulkanDriver* vk) g_loader_id = i + 1; while (true) { + g_thread_idle[i]->store(true); std::unique_lock ul(g_loaders_mutex); g_loaders_cv.wait(ul, [] { @@ -101,6 +110,7 @@ void GEVulkanCommandLoader::init(GEVulkanDriver* vk) if (g_loader_count.load() == 0) return; + g_thread_idle[i]->store(false); std::function copied = g_threaded_commands.front(); g_threaded_commands.pop_front(); ul.unlock(); @@ -132,6 +142,7 @@ void GEVulkanCommandLoader::destroy() for (auto& f : g_threaded_commands) f(); g_threaded_commands.clear(); + g_thread_idle.clear(); for (VkCommandPool& pool : g_command_pools) vkDestroyCommandPool(g_vk->getDevice(), pool, NULL); @@ -231,4 +242,23 @@ void GEVulkanCommandLoader::endSingleTimeCommands(VkCommandBuffer command_buffer &command_buffer); } // endSingleTimeCommands +// ---------------------------------------------------------------------------- +void GEVulkanCommandLoader::waitIdle() +{ + while (true) + { + std::lock_guard lock(g_loaders_mutex); + if (g_threaded_commands.empty()) + break; + } + + unsigned i = 0; + while (i < g_thread_idle.size()) + { + if (g_thread_idle[i]->load() == false) + continue; + i++; + } +} // waitIdle + } diff --git a/lib/graphics_engine/src/ge_vulkan_command_loader.hpp b/lib/graphics_engine/src/ge_vulkan_command_loader.hpp index 6f647e798..6379a6848 100644 --- a/lib/graphics_engine/src/ge_vulkan_command_loader.hpp +++ b/lib/graphics_engine/src/ge_vulkan_command_loader.hpp @@ -33,6 +33,8 @@ VkCommandBuffer beginSingleTimeCommands(); // ---------------------------------------------------------------------------- void endSingleTimeCommands(VkCommandBuffer command_buffer, VkQueueFlagBits bit = VK_QUEUE_GRAPHICS_BIT); +// ---------------------------------------------------------------------------- +void waitIdle(); }; // GEVulkanCommandLoader } diff --git a/lib/graphics_engine/src/ge_vulkan_driver.cpp b/lib/graphics_engine/src/ge_vulkan_driver.cpp index 0711850fa..30d3c144e 100644 --- a/lib/graphics_engine/src/ge_vulkan_driver.cpp +++ b/lib/graphics_engine/src/ge_vulkan_driver.cpp @@ -2191,7 +2191,7 @@ void GEVulkanDriver::createSwapChainRelated(bool handle_surface) } // createSwapChainRelated // ---------------------------------------------------------------------------- -void GEVulkanDriver::waitIdle() +void GEVulkanDriver::waitIdle(bool flush_command_loader) { if (m_disable_wait_idle) return; @@ -2201,6 +2201,9 @@ void GEVulkanDriver::waitIdle() vkDeviceWaitIdle(m_vk->device); for (std::mutex* m : m_graphics_queue_mutexes) m->unlock(); + + if (flush_command_loader) + GEVulkanCommandLoader::waitIdle(); } // waitIdle // ---------------------------------------------------------------------------- diff --git a/src/graphics/stk_tex_manager.cpp b/src/graphics/stk_tex_manager.cpp index 4450fb11c..5467df63f 100644 --- a/src/graphics/stk_tex_manager.cpp +++ b/src/graphics/stk_tex_manager.cpp @@ -39,7 +39,7 @@ STKTexManager::~STKTexManager() GE::GEVulkanDriver* gevd = GE::getVKDriver(); if (gevd) { - gevd->waitIdle(); + gevd->waitIdle(/*flush_command_loader*/true); gevd->setDisableWaitIdle(true); } #endif