From aa0b82955012fd7a5ba25f1e2365049e6716f33e Mon Sep 17 00:00:00 2001 From: CodingJellyfish Date: Mon, 15 Apr 2024 01:34:27 +0800 Subject: [PATCH 1/2] Add multiple queue type support --- .../include/ge_vulkan_driver.hpp | 30 +- .../src/ge_vulkan_array_texture.cpp | 4 +- .../src/ge_vulkan_command_loader.cpp | 93 +++--- .../src/ge_vulkan_command_loader.hpp | 8 +- lib/graphics_engine/src/ge_vulkan_driver.cpp | 265 +++++++++++------- .../src/ge_vulkan_features.cpp | 2 +- .../src/ge_vulkan_scene_manager.cpp | 4 +- lib/graphics_engine/src/ge_vulkan_texture.cpp | 12 +- 8 files changed, 256 insertions(+), 162 deletions(-) diff --git a/lib/graphics_engine/include/ge_vulkan_driver.hpp b/lib/graphics_engine/include/ge_vulkan_driver.hpp index ca618da1d65..e890af9a714 100644 --- a/lib/graphics_engine/include/ge_vulkan_driver.hpp +++ b/lib/graphics_engine/include/ge_vulkan_driver.hpp @@ -42,6 +42,14 @@ namespace GE GVS_2D_RENDER, GVS_COUNT, }; + enum GEVulkanQueueIndices + { + GVQI_MIN = 0, + GVQI_GRAPHICS = GVQI_MIN, + GVQI_COMPUTE, + GVQI_TRANSFER, + GVQI_COUNT + }; class GEVulkanDriver : public video::CNullDriver { public: @@ -342,10 +350,9 @@ namespace GE createSwapChainRelated(false/*handle_surface*/); } void updateDriver(bool reload_shaders = false); - uint32_t getGraphicsFamily() const { return m_graphics_family; } - unsigned getGraphicsQueueCount() const - { return m_graphics_queue_count; } - std::unique_lock getGraphicsQueue(VkQueue* queue) const; + uint32_t getQueueFamily(uint32_t queue_index) const; + uint32_t getQueueCount(uint32_t queue_index) const; + std::unique_lock getQueue(VkQueue* queue, uint32_t index) const; void waitIdle(bool flush_command_loader = false); void setDisableWaitIdle(bool val) { m_disable_wait_idle = val; } IrrlichtDevice* getIrrlichtDevice() const { return m_irrlicht_device; } @@ -483,13 +490,15 @@ namespace GE VkSurfaceCapabilitiesKHR m_surface_capabilities; std::vector m_surface_formats; std::vector m_present_modes; - std::vector m_graphics_queue; - VkQueue m_present_queue; - mutable std::vector m_graphics_queue_mutexes; - uint32_t m_graphics_family; + std::vector m_queues[GVQI_COUNT]; + uint32_t m_queue_count[GVQI_COUNT]; + mutable std::vector m_queue_mutexes[GVQI_COUNT]; + uint32_t m_queue_family[GVQI_COUNT]; + uint32_t m_queue_family_count; + VkQueue m_present_queue; uint32_t m_present_family; - unsigned m_graphics_queue_count; + VkPhysicalDeviceProperties m_properties; VkPhysicalDeviceFeatures m_features; @@ -522,7 +531,8 @@ namespace GE void createInstance(SDL_Window* window); void findPhysicalDevice(); bool checkDeviceExtensions(VkPhysicalDevice device); - bool findQueueFamilies(VkPhysicalDevice device, uint32_t* graphics_family, unsigned* graphics_queue_count, uint32_t* present_family); + bool findQueueFamilies(VkPhysicalDevice device, VkQueueFlags required_queue_flags, VkQueueFlags ignored_queue_flags, + uint32_t* family, unsigned* queue_count, uint32_t* present_family = NULL); bool updateSurfaceInformation(VkPhysicalDevice device, VkSurfaceCapabilitiesKHR* surface_capabilities, std::vector* surface_formats, diff --git a/lib/graphics_engine/src/ge_vulkan_array_texture.cpp b/lib/graphics_engine/src/ge_vulkan_array_texture.cpp index 0f817dc40fd..1fd3e91e653 100644 --- a/lib/graphics_engine/src/ge_vulkan_array_texture.cpp +++ b/lib/graphics_engine/src/ge_vulkan_array_texture.cpp @@ -220,7 +220,7 @@ void GEVulkanArrayTexture::reloadInternal(const std::vector& list, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)) goto destroy; - command_buffer = GEVulkanCommandLoader::beginSingleTimeCommands(); + command_buffer = GEVulkanCommandLoader::beginSingleTimeCommands(GVQI_TRANSFER); transitionImageLayout(command_buffer, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); @@ -239,7 +239,7 @@ void GEVulkanArrayTexture::reloadInternal(const std::vector& list, transitionImageLayout(command_buffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - GEVulkanCommandLoader::endSingleTimeCommands(command_buffer); + GEVulkanCommandLoader::endSingleTimeCommands(command_buffer, GVQI_TRANSFER); createImageView(VK_IMAGE_ASPECT_COLOR_BIT); diff --git a/lib/graphics_engine/src/ge_vulkan_command_loader.cpp b/lib/graphics_engine/src/ge_vulkan_command_loader.cpp index 13cadd63daf..34a5e200464 100644 --- a/lib/graphics_engine/src/ge_vulkan_command_loader.cpp +++ b/lib/graphics_engine/src/ge_vulkan_command_loader.cpp @@ -47,8 +47,8 @@ std::deque > g_threaded_commands; thread_local int g_loader_id = 0; std::atomic_uint g_loader_count(0); -std::vector g_command_pools; -std::vector g_command_fences; +std::vector g_command_pools[GVQI_COUNT]; +std::vector g_command_fences[GVQI_COUNT]; std::vector > > g_thread_idle; } // GEVulkanCommandLoader @@ -62,29 +62,32 @@ void GEVulkanCommandLoader::init(GEVulkanDriver* vk) else thread_count += 3; - g_command_pools.resize(thread_count); - g_command_fences.resize(thread_count); - for (unsigned i = 0; i < thread_count; i++) + for (int i = GVQI_MIN; i < GVQI_COUNT; i++) { - VkCommandPoolCreateInfo pool_info = {}; - pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_info.queueFamilyIndex = g_vk->getGraphicsFamily(); - pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VkResult result = vkCreateCommandPool(g_vk->getDevice(), &pool_info, - NULL, &g_command_pools[i]); - if (result != VK_SUCCESS) + g_command_pools[i].resize(thread_count); + g_command_fences[i].resize(thread_count); + for (unsigned j = 0; j < thread_count; j++) { - throw std::runtime_error( - "GEVulkanCommandLoader: vkCreateCommandPool failed"); - } - VkFenceCreateInfo fence_info = {}; - fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - result = vkCreateFence(g_vk->getDevice(), &fence_info, NULL, - &g_command_fences[i]); - if (result != VK_SUCCESS) - { - throw std::runtime_error( - "GEVulkanCommandLoader: vkCreateFence failed"); + VkCommandPoolCreateInfo pool_info = {}; + pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + pool_info.queueFamilyIndex = g_vk->getQueueFamily(i); + pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + VkResult result = vkCreateCommandPool(g_vk->getDevice(), &pool_info, + NULL, &g_command_pools[i][j]); + if (result != VK_SUCCESS) + { + throw std::runtime_error( + "GEVulkanCommandLoader: vkCreateCommandPool failed"); + } + VkFenceCreateInfo fence_info = {}; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + result = vkCreateFence(g_vk->getDevice(), &fence_info, NULL, + &g_command_fences[i][j]); + if (result != VK_SUCCESS) + { + throw std::runtime_error( + "GEVulkanCommandLoader: vkCreateFence failed"); + } } } @@ -123,7 +126,7 @@ void GEVulkanCommandLoader::init(GEVulkanDriver* vk) char thread_count_str[40] = {}; snprintf(thread_count_str, 40, "%d threads used, %d graphics queue(s)", - thread_count - 1, vk->getGraphicsQueueCount()); + thread_count - 1, vk->getQueueCount(GVQI_GRAPHICS)); os::Printer::log("Vulkan command loader", thread_count_str); } // init @@ -146,12 +149,18 @@ void GEVulkanCommandLoader::destroy() g_threaded_commands.clear(); g_thread_idle.clear(); - for (VkCommandPool& pool : g_command_pools) - vkDestroyCommandPool(g_vk->getDevice(), pool, NULL); - g_command_pools.clear(); - for (VkFence& fence : g_command_fences) - vkDestroyFence(g_vk->getDevice(), fence, NULL); - g_command_fences.clear(); + for (int i = GVQI_MIN; i < GVQI_COUNT; i++) + { + for (VkCommandPool& pool : g_command_pools[i]) + vkDestroyCommandPool(g_vk->getDevice(), pool, NULL); + g_command_pools[i].clear(); + } + for (int i = GVQI_MIN; i < GVQI_COUNT; i++) + { + for (VkFence& fence : g_command_fences[i]) + vkDestroyFence(g_vk->getDevice(), fence, NULL); + g_command_fences[i].clear(); + } } // destroy // ---------------------------------------------------------------------------- @@ -179,15 +188,15 @@ int GEVulkanCommandLoader::getLoaderId() } // getLoaderId // ---------------------------------------------------------------------------- -VkCommandPool GEVulkanCommandLoader::getCurrentCommandPool() +VkCommandPool GEVulkanCommandLoader::getCurrentCommandPool(uint32_t index) { - return g_command_pools[g_loader_id]; + return g_command_pools[index][g_loader_id]; } // getCurrentCommandPool // ---------------------------------------------------------------------------- -VkFence GEVulkanCommandLoader::getCurrentFence() +VkFence GEVulkanCommandLoader::getCurrentFence(uint32_t index) { - return g_command_fences[g_loader_id]; + return g_command_fences[index][g_loader_id]; } // getCurrentFence // ---------------------------------------------------------------------------- @@ -201,12 +210,12 @@ void GEVulkanCommandLoader::addMultiThreadingCommand(std::function cmd) } // addMultiThreadingCommand // ---------------------------------------------------------------------------- -VkCommandBuffer GEVulkanCommandLoader::beginSingleTimeCommands() +VkCommandBuffer GEVulkanCommandLoader::beginSingleTimeCommands(uint32_t index) { VkCommandBufferAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - alloc_info.commandPool = g_command_pools[g_loader_id]; + alloc_info.commandPool = g_command_pools[index][g_loader_id]; alloc_info.commandBufferCount = 1; VkCommandBuffer command_buffer; @@ -222,7 +231,7 @@ VkCommandBuffer GEVulkanCommandLoader::beginSingleTimeCommands() // ---------------------------------------------------------------------------- void GEVulkanCommandLoader::endSingleTimeCommands(VkCommandBuffer command_buffer, - VkQueueFlagBits bit) + uint32_t index) { vkEndCommandBuffer(command_buffer); @@ -233,14 +242,14 @@ void GEVulkanCommandLoader::endSingleTimeCommands(VkCommandBuffer command_buffer const int loader_id = g_loader_id; VkQueue queue = VK_NULL_HANDLE; - std::unique_lock lock = g_vk->getGraphicsQueue(&queue); - vkQueueSubmit(queue, 1, &submit_info, g_command_fences[loader_id]); + std::unique_lock lock = g_vk->getQueue(&queue, GVQI_GRAPHICS); + vkQueueSubmit(queue, 1, &submit_info, g_command_fences[index][loader_id]); lock.unlock(); - vkWaitForFences(g_vk->getDevice(), 1, &g_command_fences[loader_id], + vkWaitForFences(g_vk->getDevice(), 1, &g_command_fences[index][loader_id], VK_TRUE, std::numeric_limits::max()); - vkResetFences(g_vk->getDevice(), 1, &g_command_fences[loader_id]); - vkFreeCommandBuffers(g_vk->getDevice(), g_command_pools[loader_id], 1, + vkResetFences(g_vk->getDevice(), 1, &g_command_fences[index][loader_id]); + vkFreeCommandBuffers(g_vk->getDevice(), g_command_pools[index][loader_id], 1, &command_buffer); } // endSingleTimeCommands diff --git a/lib/graphics_engine/src/ge_vulkan_command_loader.hpp b/lib/graphics_engine/src/ge_vulkan_command_loader.hpp index 6379a684834..decc57cfe1b 100644 --- a/lib/graphics_engine/src/ge_vulkan_command_loader.hpp +++ b/lib/graphics_engine/src/ge_vulkan_command_loader.hpp @@ -23,16 +23,16 @@ unsigned getLoaderCount(); // ---------------------------------------------------------------------------- int getLoaderId(); // ---------------------------------------------------------------------------- -VkCommandPool getCurrentCommandPool(); +VkCommandPool getCurrentCommandPool(uint32_t index); // ---------------------------------------------------------------------------- -VkFence getCurrentFence(); +VkFence getCurrentFence(uint32_t index); // ---------------------------------------------------------------------------- void addMultiThreadingCommand(std::function cmd); // ---------------------------------------------------------------------------- -VkCommandBuffer beginSingleTimeCommands(); +VkCommandBuffer beginSingleTimeCommands(uint32_t index); // ---------------------------------------------------------------------------- void endSingleTimeCommands(VkCommandBuffer command_buffer, - VkQueueFlagBits bit = VK_QUEUE_GRAPHICS_BIT); + uint32_t index); // ---------------------------------------------------------------------------- void waitIdle(); }; // GEVulkanCommandLoader diff --git a/lib/graphics_engine/src/ge_vulkan_driver.cpp b/lib/graphics_engine/src/ge_vulkan_driver.cpp index 6ae8f7202d8..ad0e4e32ded 100644 --- a/lib/graphics_engine/src/ge_vulkan_driver.cpp +++ b/lib/graphics_engine/src/ge_vulkan_driver.cpp @@ -510,8 +510,10 @@ GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params, m_vk.reset(new VK()); m_physical_device = VK_NULL_HANDLE; m_present_queue = VK_NULL_HANDLE; - m_graphics_family = m_present_family = 0; - m_graphics_queue_count = 0; + memset(m_queue_family, (uint8_t)-1, sizeof(m_queue_family)); + memset(m_queue_count, (uint8_t)-1, sizeof(m_queue_count)); + m_present_family = (uint32_t)-1; + m_queue_family_count = 0; m_properties = {}; m_features = {}; @@ -706,10 +708,12 @@ void GEVulkanDriver::destroyVulkan() GEVulkanShaderManager::destroy(); GEVulkanCommandLoader::destroy(); - for (std::mutex* m : m_graphics_queue_mutexes) - delete m; - m_graphics_queue_mutexes.clear(); - + for (int i = GVQI_MIN; i < GVQI_COUNT; i++) + { + for (std::mutex* m : m_queue_mutexes[i]) + delete m; + m_queue_mutexes[i].clear(); + } delete m_vk.get(); m_vk.release(); } // destroyVulkan @@ -835,17 +839,71 @@ void GEVulkanDriver::findPhysicalDevice() throw std::runtime_error("findPhysicalDevice has < 1 device_count"); std::vector devices(device_count); - vkEnumeratePhysicalDevices(m_vk->instance, &device_count, &devices[0]); + vkEnumeratePhysicalDevices(m_vk->instance, &device_count, devices.data()); for (VkPhysicalDevice& device : devices) { - uint32_t graphics_family = 0; - uint32_t present_family = 0; - unsigned graphics_queue_count = 0; + memset(m_queue_family, 0, sizeof(m_queue_family)); + memset(m_queue_count, 0, sizeof(m_queue_count)); + m_present_family = 0; + m_queue_family_count = 0; + + uint32_t queue_family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, NULL); + if (queue_family_count == 0) + continue; - bool success = findQueueFamilies(device, &graphics_family, - &graphics_queue_count, &present_family); + std::vector queue_families(queue_family_count); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, + queue_families.data()); + bool find_present_family = false; + + for (unsigned int i = 0; i < queue_families.size(); i++) + { + VkBool32 present_support = false; + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, m_vk->surface, &present_support); + + if (queue_families[i].queueCount > 0 && present_support) + { + find_present_family = true; + m_present_family = i; + break; + } + } + + for (unsigned int i = 0; i < queue_families.size(); i++) + { + if (queue_families[i].queueCount == 0) + continue; + + if (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT + && m_queue_count[GVQI_GRAPHICS] == 0) + { + m_queue_family[GVQI_GRAPHICS] = i; + m_queue_count[GVQI_GRAPHICS] = queue_families[i].queueCount; + m_queue_family_count++; + } + else if (queue_families[i].queueFlags & VK_QUEUE_COMPUTE_BIT + && i != m_present_family + && m_queue_count[GVQI_COMPUTE] == 0) + { + m_queue_family[GVQI_COMPUTE] = i; + m_queue_count[GVQI_COMPUTE] = queue_families[i].queueCount; + m_queue_family_count++; + } + else if (queue_families[i].queueFlags & VK_QUEUE_TRANSFER_BIT + && i != m_present_family + && m_queue_count[GVQI_TRANSFER] == 0) + { + m_queue_family[GVQI_TRANSFER] = i; + m_queue_count[GVQI_TRANSFER] = queue_families[i].queueCount; + m_queue_family_count++; + } + } + + bool success = m_queue_count[GVQI_GRAPHICS] != 0 && find_present_family; + if (!success) continue; @@ -865,9 +923,6 @@ void GEVulkanDriver::findPhysicalDevice() continue; vkGetPhysicalDeviceFeatures(device, &m_features); - m_graphics_family = graphics_family; - m_graphics_queue_count = graphics_queue_count; - m_present_family = present_family; m_surface_capabilities = surface_capabilities; m_surface_formats = surface_formats; m_present_modes = present_modes; @@ -951,8 +1006,10 @@ bool GEVulkanDriver::updateSurfaceInformation(VkPhysicalDevice device, // ---------------------------------------------------------------------------- bool GEVulkanDriver::findQueueFamilies(VkPhysicalDevice device, - uint32_t* graphics_family, - unsigned* graphics_queue_count, + VkQueueFlags required_queue_flags, + VkQueueFlags ignored_queue_flags, + uint32_t* family, + unsigned* queue_count, uint32_t* present_family) { uint32_t queue_family_count = 0; @@ -962,54 +1019,85 @@ bool GEVulkanDriver::findQueueFamilies(VkPhysicalDevice device, std::vector queue_families(queue_family_count); vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, - &queue_families[0]); + queue_families.data()); bool found_graphics_family = false; - bool found_present_family = false; + bool found_present_family = true; for (unsigned int i = 0; i < queue_families.size(); i++) { if (queue_families[i].queueCount > 0 && - queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) + !(~queue_families[i].queueFlags & required_queue_flags) && // All required flags + !(queue_families[i].queueFlags & ignored_queue_flags)) // No ignored flags { - *graphics_family = i; - *graphics_queue_count = queue_families[i].queueCount; + *family = i; + *queue_count = queue_families[i].queueCount; found_graphics_family = true; break; } } - - for (unsigned int i = 0; i < queue_families.size(); i++) + if (present_family) { - VkBool32 present_support = false; - vkGetPhysicalDeviceSurfaceSupportKHR(device, i, m_vk->surface, &present_support); + found_present_family = false; - if (queue_families[i].queueCount > 0 && present_support) + for (unsigned int i = 0; i < queue_families.size(); i++) { - *present_family = i; - found_present_family = true; - break; + VkBool32 present_support = false; + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, m_vk->surface, &present_support); + + if (queue_families[i].queueCount > 0 && present_support) + { + *present_family = i; + found_present_family = true; + break; + } } } - return found_graphics_family && found_present_family; } // findQueueFamilies +// ---------------------------------------------------------------------------- +uint32_t GEVulkanDriver::getQueueFamily(uint32_t queue_index) const +{ + if (queue_index == GVQI_TRANSFER && m_queue_count[queue_index] == 0) + queue_index = GVQI_COMPUTE; + if (queue_index == GVQI_COMPUTE && m_queue_count[queue_index] == 0) + queue_index = GVQI_GRAPHICS; + return m_queue_family[queue_index]; +} + +// ---------------------------------------------------------------------------- +uint32_t GEVulkanDriver::getQueueCount(uint32_t queue_index) const +{ + if (queue_index == GVQI_TRANSFER && m_queue_count[queue_index] == 0) + queue_index = GVQI_COMPUTE; + if (queue_index == GVQI_COMPUTE && m_queue_count[queue_index] == 0) + queue_index = GVQI_GRAPHICS; + return m_queue_count[queue_index]; +} + // ---------------------------------------------------------------------------- void GEVulkanDriver::createDevice() { std::vector queue_create_infos; - std::vector queue_priority; - queue_priority.resize(m_graphics_queue_count, 1.0f); - + std::vector queue_priority[GVQI_COUNT]; VkDeviceQueueCreateInfo queue_create_info = {}; - queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_info.queueFamilyIndex = m_graphics_family; - queue_create_info.queueCount = m_graphics_queue_count; - queue_create_info.pQueuePriorities = queue_priority.data(); - queue_create_infos.push_back(queue_create_info); - if (m_present_family != m_graphics_family) + for (int i = GVQI_MIN; i < GVQI_COUNT; i++) + { + if (m_queue_count[i] == 0) + { + continue; + } + queue_priority[i].resize(m_queue_count[i], 1.0f); + queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_info.queueFamilyIndex = m_queue_family[i]; + queue_create_info.queueCount = m_queue_count[i]; + queue_create_info.pQueuePriorities = queue_priority[i].data(); + queue_create_infos.push_back(queue_create_info); + } + + if (m_present_family != m_queue_family[GVQI_GRAPHICS]) { queue_create_info.queueFamilyIndex = m_present_family; queue_create_info.queueCount = 1; @@ -1045,10 +1133,10 @@ void GEVulkanDriver::createDevice() VkDeviceCreateInfo create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; create_info.queueCreateInfoCount = queue_create_infos.size(); - create_info.pQueueCreateInfos = &queue_create_infos[0]; + create_info.pQueueCreateInfos = queue_create_infos.data(); create_info.pEnabledFeatures = &device_features; create_info.enabledExtensionCount = m_device_extensions.size(); - create_info.ppEnabledExtensionNames = &m_device_extensions[0]; + create_info.ppEnabledExtensionNames = m_device_extensions.data(); create_info.enabledLayerCount = 0; create_info.pNext = &descriptor_indexing_features; @@ -1057,40 +1145,49 @@ void GEVulkanDriver::createDevice() if (result != VK_SUCCESS) throw std::runtime_error("vkCreateDevice failed"); - m_graphics_queue.resize(m_graphics_queue_count); - for (unsigned i = 0; i < m_graphics_queue_count; i++) + for (unsigned i = GVQI_MIN; i < GVQI_COUNT; i++) { - vkGetDeviceQueue(m_vk->device, m_graphics_family, i, - &m_graphics_queue[i]); - m_graphics_queue_mutexes.push_back(new std::mutex()); + for (unsigned j = 0; j < m_queue_count[i]; j++) + { + VkQueue queue; + vkGetDeviceQueue(m_vk->device, m_queue_family[i], j, + &queue); + m_queues[i].push_back(queue); + m_queue_mutexes[i].push_back(new std::mutex()); + } } - if (m_present_family != m_graphics_family) + if (m_present_family != m_queue_family[GVQI_GRAPHICS]) vkGetDeviceQueue(m_vk->device, m_present_family, 0, &m_present_queue); } // createDevice // ---------------------------------------------------------------------------- -std::unique_lock GEVulkanDriver::getGraphicsQueue(VkQueue* queue) const +std::unique_lock GEVulkanDriver::getQueue(VkQueue* queue, uint32_t index) const { - if (m_graphics_queue_count == 0) - throw std::runtime_error("No graphics queue created"); - if (m_graphics_queue_count == 1) - { - *queue = m_graphics_queue[0]; - return std::unique_lock(*m_graphics_queue_mutexes[0]); - } + if (index == GVQI_TRANSFER && m_queue_count[index] == 0) + index = GVQI_COMPUTE; + if (index == GVQI_COMPUTE && m_queue_count[index] == 0) + index = GVQI_GRAPHICS; + while (true) { - for (unsigned i = 0; i < m_graphics_queue_count; i++) + bool has_queue = false; + int offset = 0; + + for (unsigned j = 0; j < m_queue_count[index]; j++) { - std::unique_lock lock(*m_graphics_queue_mutexes[i], + has_queue = true; + std::unique_lock lock(*m_queue_mutexes[index][j], std::defer_lock); if (lock.try_lock()) { - *queue = m_graphics_queue[i]; + *queue = m_queues[index][j]; return lock; } } + + if (!has_queue) + throw std::runtime_error("GEVulkanDriver::getQueue: Cannot fetch suitable queue"); } } // getGraphicsQueue @@ -1234,8 +1331,8 @@ void GEVulkanDriver::createSwapChain() create_info.imageArrayLayers = 1; create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - uint32_t queueFamilyIndices[] = { m_graphics_family, m_present_family }; - if (m_graphics_family != m_present_family) + uint32_t queueFamilyIndices[] = { m_queue_family[GVQI_GRAPHICS], m_present_family }; + if (m_present_family != m_queue_family[GVQI_GRAPHICS]) { create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT; create_info.queueFamilyIndexCount = 2; @@ -1391,7 +1488,7 @@ void GEVulkanDriver::createCommandBuffers() { VkCommandPoolCreateInfo pool_info = {}; pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_info.queueFamilyIndex = m_graphics_family; + pool_info.queueFamilyIndex = m_queue_family[GVQI_GRAPHICS]; VkResult result = vkCreateCommandPool(m_vk->device, &pool_info, NULL, &m_vk->command_pools[i]); if (result != VK_SUCCESS) @@ -1641,13 +1738,13 @@ bool GEVulkanDriver::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, void GEVulkanDriver::copyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer, VkDeviceSize size) { - VkCommandBuffer command_buffer = GEVulkanCommandLoader::beginSingleTimeCommands(); + VkCommandBuffer command_buffer = GEVulkanCommandLoader::beginSingleTimeCommands(GVQI_TRANSFER); VkBufferCopy copy_region = {}; copy_region.size = size; vkCmdCopyBuffer(command_buffer, src_buffer, dst_buffer, 1, ©_region); - GEVulkanCommandLoader::endSingleTimeCommands(command_buffer); + GEVulkanCommandLoader::endSingleTimeCommands(command_buffer, GVQI_TRANSFER); } // copyBuffer // ---------------------------------------------------------------------------- @@ -1707,30 +1804,6 @@ bool GEVulkanDriver::endScene() return false; } - if (m_vk->in_flight_fences.empty() || vkWaitForFences(m_vk->device, 1, - &m_vk->in_flight_fences[m_current_frame], VK_TRUE, 2000000000) == - VK_TIMEOUT) - { - // Attempt to restore after out focus in gnome fullscreen - video::CNullDriver::endScene(); - GEVulkan2dRenderer::clear(); - handleDeletedTextures(); - destroySwapChainRelated(false/*handle_surface*/); - try - { - createSwapChainRelated(false/*handle_surface*/); - } - catch (std::exception& e) - { - // When minimized in Windows swapchain depth buffer will fail to - // create - destroySwapChainRelated(false/*handle_surface*/); - } - return true; - } - - VkFence fence = m_vk->in_flight_fences[m_current_frame]; - vkResetFences(m_vk->device, 1, &fence); vkResetCommandPool(m_vk->device, m_vk->command_pools[m_current_frame], 0); VkSemaphore semaphore = m_vk->image_available_semaphores[m_current_frame]; @@ -1763,7 +1836,7 @@ bool GEVulkanDriver::endScene() submit_info.pSignalSemaphores = signal_semaphores; VkQueue queue = VK_NULL_HANDLE; - std::unique_lock ul = getGraphicsQueue(&queue); + std::unique_lock ul = getQueue(&queue, GVQI_GRAPHICS); result = vkQueueSubmit(queue, 1, &submit_info, m_vk->in_flight_fences[m_current_frame]); ul.unlock(); @@ -1792,12 +1865,12 @@ bool GEVulkanDriver::endScene() m_current_buffer_idx = (m_current_buffer_idx + 1) % (getMaxFrameInFlight() + 1); - if (m_present_queue) + if (m_present_family != m_queue_family[GVQI_GRAPHICS]) result = vkQueuePresentKHR(m_present_queue, &present_info); else { VkQueue present_queue = VK_NULL_HANDLE; - std::unique_lock ul = getGraphicsQueue(&present_queue); + std::unique_lock ul = getQueue(&present_queue, GVQI_GRAPHICS); result = vkQueuePresentKHR(present_queue, &present_info); ul.unlock(); } @@ -2348,11 +2421,13 @@ void GEVulkanDriver::waitIdle(bool flush_command_loader) if (m_disable_wait_idle) return; // Host access to all VkQueue objects created from device must be externally synchronized - for (std::mutex* m : m_graphics_queue_mutexes) - m->lock(); + for (int i = GVQI_MIN; i < GVQI_COMPUTE; i++) + for (std::mutex* m : m_queue_mutexes[i]) + m->lock(); vkDeviceWaitIdle(m_vk->device); - for (std::mutex* m : m_graphics_queue_mutexes) - m->unlock(); + for (int i = GVQI_MIN; i < GVQI_COMPUTE; i++) + for (std::mutex* m : m_queue_mutexes[i]) + m->unlock(); if (flush_command_loader) GEVulkanCommandLoader::waitIdle(); diff --git a/lib/graphics_engine/src/ge_vulkan_features.cpp b/lib/graphics_engine/src/ge_vulkan_features.cpp index ec3dabd7543..31654c61e0a 100644 --- a/lib/graphics_engine/src/ge_vulkan_features.cpp +++ b/lib/graphics_engine/src/ge_vulkan_features.cpp @@ -112,7 +112,7 @@ void GEVulkanFeatures::init(GEVulkanDriver* vk) std::vector queue_families(queue_family_count); vkGetPhysicalDeviceQueueFamilyProperties(vk->getPhysicalDevice(), &queue_family_count, &queue_families[0]); - uint32_t main_family = vk->getGraphicsFamily(); + uint32_t main_family = vk->getQueueFamily(GVQI_GRAPHICS); if (main_family < queue_families.size()) { g_supports_compute_in_main_queue = diff --git a/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp b/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp index 36b8c97545a..6eabf8a219d 100644 --- a/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp +++ b/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp @@ -191,7 +191,7 @@ void GEVulkanSceneManager::drawAll(irr::u32 flags) }; clear_values[1].depthStencil = {1.0f, 0}; - VkCommandBuffer cmd = GEVulkanCommandLoader::beginSingleTimeCommands(); + VkCommandBuffer cmd = GEVulkanCommandLoader::beginSingleTimeCommands(GVQI_GRAPHICS); GEVulkanCameraSceneNode* cam = static_cast< GEVulkanCameraSceneNode*>(getActiveCamera()); @@ -217,7 +217,7 @@ void GEVulkanSceneManager::drawAll(irr::u32 flags) vkCmdEndRenderPass(cmd); - GEVulkanCommandLoader::endSingleTimeCommands(cmd); + GEVulkanCommandLoader::endSingleTimeCommands(cmd, GVQI_GRAPHICS); vk->handleDeletedTextures(); } // drawAll diff --git a/lib/graphics_engine/src/ge_vulkan_texture.cpp b/lib/graphics_engine/src/ge_vulkan_texture.cpp index c3d977ec7da..23b9ef3b98d 100644 --- a/lib/graphics_engine/src/ge_vulkan_texture.cpp +++ b/lib/graphics_engine/src/ge_vulkan_texture.cpp @@ -236,7 +236,7 @@ bool GEVulkanTexture::createTextureImage(uint8_t* texture_data, goto destroy; } - command_buffer = GEVulkanCommandLoader::beginSingleTimeCommands(); + command_buffer = GEVulkanCommandLoader::beginSingleTimeCommands(GVQI_TRANSFER); transitionImageLayout(command_buffer, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); @@ -262,7 +262,7 @@ bool GEVulkanTexture::createTextureImage(uint8_t* texture_data, transitionImageLayout(command_buffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - GEVulkanCommandLoader::endSingleTimeCommands(command_buffer); + GEVulkanCommandLoader::endSingleTimeCommands(command_buffer, GVQI_TRANSFER); destroy: delete mipmap_generator; @@ -625,7 +625,7 @@ uint8_t* GEVulkanTexture::getTextureData() buffer_allocation)) return NULL; - VkCommandBuffer command_buffer = GEVulkanCommandLoader::beginSingleTimeCommands(); + VkCommandBuffer command_buffer = GEVulkanCommandLoader::beginSingleTimeCommands(GVQI_TRANSFER); transitionImageLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, @@ -648,7 +648,7 @@ uint8_t* GEVulkanTexture::getTextureData() transitionImageLayout(command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - GEVulkanCommandLoader::endSingleTimeCommands(command_buffer); + GEVulkanCommandLoader::endSingleTimeCommands(command_buffer, GVQI_TRANSFER); uint8_t* texture_data = new uint8_t[image_size]; void* mapped_data; @@ -750,7 +750,7 @@ void GEVulkanTexture::updateTexture(void* data, video::ECOLOR_FORMAT format, } } - VkCommandBuffer command_buffer = GEVulkanCommandLoader::beginSingleTimeCommands(); + VkCommandBuffer command_buffer = GEVulkanCommandLoader::beginSingleTimeCommands(GVQI_TRANSFER); transitionImageLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); @@ -830,7 +830,7 @@ void GEVulkanTexture::updateTexture(void* data, video::ECOLOR_FORMAT format, transitionImageLayout(command_buffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - GEVulkanCommandLoader::endSingleTimeCommands(command_buffer); + GEVulkanCommandLoader::endSingleTimeCommands(command_buffer, GVQI_TRANSFER); vmaDestroyBuffer(m_vk->getVmaAllocator(), staging_buffer, staging_buffer_allocation); From 52b6475305c0567d1d7e7161fd1230f57a8d6ddd Mon Sep 17 00:00:00 2001 From: CodingJellyfish Date: Mon, 15 Apr 2024 01:59:14 +0800 Subject: [PATCH 2/2] Replace dummie value --- lib/graphics_engine/src/ge_vulkan_driver.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/graphics_engine/src/ge_vulkan_driver.cpp b/lib/graphics_engine/src/ge_vulkan_driver.cpp index ad0e4e32ded..077feb78663 100644 --- a/lib/graphics_engine/src/ge_vulkan_driver.cpp +++ b/lib/graphics_engine/src/ge_vulkan_driver.cpp @@ -510,9 +510,9 @@ GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params, m_vk.reset(new VK()); m_physical_device = VK_NULL_HANDLE; m_present_queue = VK_NULL_HANDLE; - memset(m_queue_family, (uint8_t)-1, sizeof(m_queue_family)); - memset(m_queue_count, (uint8_t)-1, sizeof(m_queue_count)); - m_present_family = (uint32_t)-1; + memset(m_queue_family, 0, sizeof(m_queue_family)); + memset(m_queue_count, 0, sizeof(m_queue_count)); + m_present_family = 0; m_queue_family_count = 0; m_properties = {}; m_features = {};