From 1807c1a798d344652c19e2d910e5841f0c54d342 Mon Sep 17 00:00:00 2001 From: Tobias Frisch <tfrisch@uni-koblenz.de> Date: Tue, 18 May 2021 16:21:47 +0200 Subject: [PATCH] Refactored context and core in structure Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de> --- include/vkcv/Context.hpp | 17 ++- include/vkcv/Core.hpp | 4 +- include/vkcv/QueueManager.hpp | 37 +++-- src/vkcv/Context.cpp | 241 ++++++++++++++++++++++++++++++++- src/vkcv/Core.cpp | 247 ++++------------------------------ src/vkcv/QueueManager.cpp | 42 +++--- 6 files changed, 327 insertions(+), 261 deletions(-) diff --git a/include/vkcv/Context.hpp b/include/vkcv/Context.hpp index 1352ce0c..1c01a613 100644 --- a/include/vkcv/Context.hpp +++ b/include/vkcv/Context.hpp @@ -2,6 +2,8 @@ #include <vulkan/vulkan.hpp> +#include "QueueManager.hpp" + namespace vkcv { class Context @@ -21,10 +23,21 @@ namespace vkcv [[nodiscard]] const vk::Instance &getInstance() const; + [[nodiscard]] const vk::PhysicalDevice &getPhysicalDevice() const; + [[nodiscard]] const vk::Device &getDevice() const; + + [[nodiscard]] + const QueueManager& getQueueManager() const; + + static Context create(const char *applicationName, + uint32_t applicationVersion, + std::vector<vk::QueueFlagBits> queueFlags, + std::vector<const char *> instanceExtensions, + std::vector<const char *> deviceExtensions); private: /** @@ -34,9 +47,11 @@ namespace vkcv * @param physicalDevice Vulkan-PhysicalDevice * @param device Vulkan-Device */ - Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device device) noexcept; + Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device device, QueueManager&& queueManager) noexcept; + vk::Instance m_Instance; vk::PhysicalDevice m_PhysicalDevice; vk::Device m_Device; + QueueManager m_QueueManager; }; } diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 506e72f2..6d48e89b 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -15,7 +15,6 @@ #include "vkcv/PipelineConfig.hpp" #include "CommandResources.hpp" #include "SyncResources.hpp" -#include "vkcv/QueueManager.hpp" namespace vkcv { @@ -36,7 +35,7 @@ namespace vkcv * @param context encapsulates various Vulkan objects */ Core(Context &&context, const Window &window, SwapChain swapChain, std::vector<vk::ImageView> imageViews, - const CommandResources& commandResources, const SyncResources& syncResources, const QueueManager &queues) noexcept; + const CommandResources& commandResources, const SyncResources& syncResources) noexcept; // explicit destruction of default constructor Core() = delete; @@ -53,7 +52,6 @@ namespace vkcv std::unique_ptr<PipelineManager> m_PipelineManager; CommandResources m_CommandResources; SyncResources m_SyncResources; - QueueManager m_QueueManager; uint32_t m_currentSwapchainImageIndex; std::vector<vk::Framebuffer> m_TemporaryFramebuffers; public: diff --git a/include/vkcv/QueueManager.hpp b/include/vkcv/QueueManager.hpp index 1779fb66..9dc5fa16 100644 --- a/include/vkcv/QueueManager.hpp +++ b/include/vkcv/QueueManager.hpp @@ -2,6 +2,14 @@ #include <vulkan/vulkan.hpp> namespace vkcv { + + struct Queue { + int familyIndex; + int queueIndex; + + vk::Queue handle; + }; + class QueueManager { public: static QueueManager create(vk::Device device, @@ -9,13 +17,17 @@ namespace vkcv { std::vector<std::pair<int, int>> &queuePairsCompute, std::vector<std::pair<int, int>> &queuePairsTransfer); - const vk::Queue &getPresentQueue() const; - - const std::vector<vk::Queue> &getGraphicsQueues() const; - - const std::vector<vk::Queue> &getComputeQueues() const; - - const std::vector<vk::Queue> &getTransferQueues() const; + [[nodiscard]] + const Queue &getPresentQueue() const; + + [[nodiscard]] + const std::vector<Queue> &getGraphicsQueues() const; + + [[nodiscard]] + const std::vector<Queue> &getComputeQueues() const; + + [[nodiscard]] + const std::vector<Queue> &getTransferQueues() const; static void queueCreateInfosQueueHandles(vk::PhysicalDevice &physicalDevice, std::vector<float> &queuePriorities, @@ -26,11 +38,12 @@ namespace vkcv { std::vector<std::pair<int, int>> &queuePairsTransfer); private: - vk::Queue m_presentQueue; - std::vector<vk::Queue> m_graphicsQueues; - std::vector<vk::Queue> m_computeQueues; - std::vector<vk::Queue> m_transferQueues; + std::vector<Queue> m_graphicsQueues; + std::vector<Queue> m_computeQueues; + std::vector<Queue> m_transferQueues; + + size_t m_presentIndex; - QueueManager(std::vector<vk::Queue> graphicsQueues, std::vector<vk::Queue> computeQueues, std::vector<vk::Queue> transferQueues, vk::Queue presentQueue); + QueueManager(std::vector<Queue>&& graphicsQueues, std::vector<Queue>&& computeQueues, std::vector<Queue>&& transferQueues, size_t presentIndex); }; } diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp index d5261285..b53a1a2c 100644 --- a/src/vkcv/Context.cpp +++ b/src/vkcv/Context.cpp @@ -1,3 +1,6 @@ + +#include <GLFW/glfw3.h> + #include "vkcv/Context.hpp" namespace vkcv @@ -5,7 +8,8 @@ namespace vkcv Context::Context(Context &&other) noexcept: m_Instance(other.m_Instance), m_PhysicalDevice(other.m_PhysicalDevice), - m_Device(other.m_Device) + m_Device(other.m_Device), + m_QueueManager(other.m_QueueManager) { other.m_Instance = nullptr; other.m_PhysicalDevice = nullptr; @@ -17,6 +21,7 @@ namespace vkcv m_Instance = other.m_Instance; m_PhysicalDevice = other.m_PhysicalDevice; m_Device = other.m_Device; + m_QueueManager = other.m_QueueManager; other.m_Instance = nullptr; other.m_PhysicalDevice = nullptr; @@ -27,10 +32,12 @@ namespace vkcv Context::Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, - vk::Device device) noexcept : + vk::Device device, + QueueManager&& queueManager) noexcept : m_Instance{instance}, m_PhysicalDevice{physicalDevice}, - m_Device{device} + m_Device{device}, + m_QueueManager{queueManager} {} Context::~Context() noexcept @@ -53,4 +60,232 @@ namespace vkcv { return m_Device; } + + const QueueManager& Context::getQueueManager() const { + return m_QueueManager; + } + + /** + * @brief The physical device is evaluated by three categories: + * discrete GPU vs. integrated GPU, amount of queues and its abilities, and VRAM.physicalDevice. + * @param physicalDevice The physical device + * @return Device score as integer + */ + int deviceScore(const vk::PhysicalDevice& physicalDevice) + { + int score = 0; + vk::PhysicalDeviceProperties properties = physicalDevice.getProperties(); + std::vector<vk::QueueFamilyProperties> qFamilyProperties = physicalDevice.getQueueFamilyProperties(); + + // for every queue family compute queue flag bits and the amount of queues + for (const auto& qFamily : qFamilyProperties) { + uint32_t qCount = qFamily.queueCount; + uint32_t bitCount = (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eCompute) != 0) + + (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eGraphics) != 0) + + (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eTransfer) != 0) + + (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eSparseBinding) != 0); + score += static_cast<int>(qCount * bitCount); + } + + // compute the VRAM of the physical device + vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevice.getMemoryProperties(); + auto vram = static_cast<int>(memoryProperties.memoryHeaps[0].size / static_cast<uint32_t>(1E9)); + score *= vram; + + if (properties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) { + score *= 2; + } + else if (properties.deviceType != vk::PhysicalDeviceType::eIntegratedGpu) { + score = -1; + } + + return score; + } + + /** + * @brief All existing physical devices will be evaluated by deviceScore. + * @param instance The instance + * @return The optimal physical device + * @see Context.deviceScore + */ + vk::PhysicalDevice pickPhysicalDevice(vk::Instance& instance) + { + vk::PhysicalDevice phyDevice; + std::vector<vk::PhysicalDevice> devices = instance.enumeratePhysicalDevices(); + + if (devices.empty()) { + throw std::runtime_error("failed to find GPUs with Vulkan support!"); + } + + int max_score = -1; + for (const auto& device : devices) { + int score = deviceScore(device); + if (score > max_score) { + max_score = score; + phyDevice = device; + } + } + + if (max_score == -1) { + throw std::runtime_error("failed to find a suitable GPU!"); + } + + return phyDevice; + } + + /** + * @brief With the help of the reference "supported" all elements in "check" checked, + * if they are supported by the physical device. + * @param supported The reference that can be used to check "check" + * @param check The elements to be checked + * @return True, if all elements in "check" are supported + */ + bool checkSupport(std::vector<const char*>& supported, std::vector<const char*>& check) + { + for (auto checkElem : check) { + bool found = false; + for (auto supportedElem : supported) { + if (strcmp(supportedElem, checkElem) == 0) { + found = true; + break; + } + } + if (!found) + return false; + } + return true; + } + + + std::vector<const char*> getRequiredExtensions() { + uint32_t glfwExtensionCount = 0; + const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); + +#ifndef NDEBUG + extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); +#endif + + return extensions; + } + + Context Context::create(const char *applicationName, + uint32_t applicationVersion, + std::vector<vk::QueueFlagBits> queueFlags, + std::vector<const char *> instanceExtensions, + std::vector<const char *> deviceExtensions) { + // check for layer support + + const std::vector<vk::LayerProperties>& layerProperties = vk::enumerateInstanceLayerProperties(); + + std::vector<const char*> supportedLayers; + supportedLayers.reserve(layerProperties.size()); + + for (auto& elem : layerProperties) { + supportedLayers.push_back(elem.layerName); + } + +// if in debug mode, check if validation layers are supported. Enable them if supported +#ifndef NDEBUG + std::vector<const char*> validationLayers = { + "VK_LAYER_KHRONOS_validation" + }; + + if (!checkSupport(supportedLayers, validationLayers)) { + throw std::runtime_error("Validation layers requested but not available!"); + } +#endif + + // check for extension support + std::vector<vk::ExtensionProperties> instanceExtensionProperties = vk::enumerateInstanceExtensionProperties(); + + std::vector<const char*> supportedExtensions; + supportedExtensions.reserve(instanceExtensionProperties.size()); + + for (auto& elem : instanceExtensionProperties) { + supportedExtensions.push_back(elem.extensionName); + } + + if (!checkSupport(supportedExtensions, instanceExtensions)) { + throw std::runtime_error("The requested instance extensions are not supported!"); + } + + // for GLFW: get all required extensions + std::vector<const char*> requiredExtensions = getRequiredExtensions(); + instanceExtensions.insert(instanceExtensions.end(), requiredExtensions.begin(), requiredExtensions.end()); + + const vk::ApplicationInfo applicationInfo( + applicationName, + applicationVersion, + "vkCV", + VK_MAKE_VERSION(0, 0, 1), + VK_HEADER_VERSION_COMPLETE + ); + + vk::InstanceCreateInfo instanceCreateInfo( + vk::InstanceCreateFlags(), + &applicationInfo, + 0, + nullptr, + static_cast<uint32_t>(instanceExtensions.size()), + instanceExtensions.data() + ); + +#ifndef NDEBUG + instanceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size()); + instanceCreateInfo.ppEnabledLayerNames = validationLayers.data(); +#endif + + vk::Instance instance = vk::createInstance(instanceCreateInfo); + + std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices(); + vk::PhysicalDevice physicalDevice = pickPhysicalDevice(instance); + + // check for physical device extension support + std::vector<vk::ExtensionProperties> deviceExtensionProperties = physicalDevice.enumerateDeviceExtensionProperties(); + supportedExtensions.clear(); + for (auto& elem : deviceExtensionProperties) { + supportedExtensions.push_back(elem.extensionName); + } + if (!checkSupport(supportedExtensions, deviceExtensions)) { + throw std::runtime_error("The requested device extensions are not supported by the physical device!"); + } + + std::vector<vk::DeviceQueueCreateInfo> qCreateInfos; + + // create required queues + std::vector<float> qPriorities; + qPriorities.resize(queueFlags.size(), 1.f); + std::vector<std::pair<int, int>> queuePairsGraphics, queuePairsCompute, queuePairsTransfer; + + QueueManager::queueCreateInfosQueueHandles(physicalDevice, qPriorities, queueFlags, qCreateInfos, queuePairsGraphics, queuePairsCompute, queuePairsTransfer); + + vk::DeviceCreateInfo deviceCreateInfo( + vk::DeviceCreateFlags(), + qCreateInfos.size(), + qCreateInfos.data(), + 0, + nullptr, + deviceExtensions.size(), + deviceExtensions.data(), + nullptr // Should our device use some features??? If yes: TODO + ); + +#ifndef NDEBUG + deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size()); + deviceCreateInfo.ppEnabledLayerNames = validationLayers.data(); +#endif + + // Ablauf + // qCreateInfos erstellen --> braucht das Device + // device erstellen + // jetzt koennen wir mit dem device die queues erstellen + + vk::Device device = physicalDevice.createDevice(deviceCreateInfo); + + QueueManager queueManager = QueueManager::create(device, queuePairsGraphics, queuePairsCompute, queuePairsTransfer); + + return Context(instance, physicalDevice, device, std::move(queueManager)); + } + } diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 7e6d87ca..0cfbaa24 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -14,110 +14,6 @@ namespace vkcv { - /** - * @brief The physical device is evaluated by three categories: - * discrete GPU vs. integrated GPU, amount of queues and its abilities, and VRAM.physicalDevice. - * @param physicalDevice The physical device - * @return Device score as integer - */ - int deviceScore(const vk::PhysicalDevice& physicalDevice) - { - int score = 0; - vk::PhysicalDeviceProperties properties = physicalDevice.getProperties(); - std::vector<vk::QueueFamilyProperties> qFamilyProperties = physicalDevice.getQueueFamilyProperties(); - - // for every queue family compute queue flag bits and the amount of queues - for (const auto& qFamily : qFamilyProperties) { - uint32_t qCount = qFamily.queueCount; - uint32_t bitCount = (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eCompute) != 0) - + (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eGraphics) != 0) - + (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eTransfer) != 0) - + (static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eSparseBinding) != 0); - score += static_cast<int>(qCount * bitCount); - } - - // compute the VRAM of the physical device - vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevice.getMemoryProperties(); - auto vram = static_cast<int>(memoryProperties.memoryHeaps[0].size / static_cast<uint32_t>(1E9)); - score *= vram; - - if (properties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) { - score *= 2; - } - else if (properties.deviceType != vk::PhysicalDeviceType::eIntegratedGpu) { - score = -1; - } - - return score; - } - - /** - * @brief All existing physical devices will be evaluated by deviceScore. - * @param instance The instance - * @return The optimal physical device - * @see Context.deviceScore - */ - vk::PhysicalDevice pickPhysicalDevice(vk::Instance& instance) - { - vk::PhysicalDevice phyDevice; - std::vector<vk::PhysicalDevice> devices = instance.enumeratePhysicalDevices(); - - if (devices.empty()) { - throw std::runtime_error("failed to find GPUs with Vulkan support!"); - } - - int max_score = -1; - for (const auto& device : devices) { - int score = deviceScore(device); - if (score > max_score) { - max_score = score; - phyDevice = device; - } - } - - if (max_score == -1) { - throw std::runtime_error("failed to find a suitable GPU!"); - } - - return phyDevice; - } - - /** - * @brief With the help of the reference "supported" all elements in "check" checked, - * if they are supported by the physical device. - * @param supported The reference that can be used to check "check" - * @param check The elements to be checked - * @return True, if all elements in "check" are supported - */ - bool checkSupport(std::vector<const char*>& supported, std::vector<const char*>& check) - { - for (auto checkElem : check) { - bool found = false; - for (auto supportedElem : supported) { - if (strcmp(supportedElem, checkElem) == 0) { - found = true; - break; - } - } - if (!found) - return false; - } - return true; - } - - - std::vector<const char*> getRequiredExtensions() { - uint32_t glfwExtensionCount = 0; - const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); - std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); - -#ifndef NDEBUG - extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); -#endif - - return extensions; - } - Core Core::create(const Window &window, const char *applicationName, uint32_t applicationVersion, @@ -125,122 +21,22 @@ namespace vkcv std::vector<const char *> instanceExtensions, std::vector<const char *> deviceExtensions) { - // check for layer support - - const std::vector<vk::LayerProperties>& layerProperties = vk::enumerateInstanceLayerProperties(); - - std::vector<const char*> supportedLayers; - supportedLayers.reserve(layerProperties.size()); - - for (auto& elem : layerProperties) { - supportedLayers.push_back(elem.layerName); - } - -// if in debug mode, check if validation layers are supported. Enable them if supported -#ifndef NDEBUG - std::vector<const char*> validationLayers = { - "VK_LAYER_KHRONOS_validation" - }; - - if (!checkSupport(supportedLayers, validationLayers)) { - throw std::runtime_error("Validation layers requested but not available!"); - } -#endif - - // check for extension support - std::vector<vk::ExtensionProperties> instanceExtensionProperties = vk::enumerateInstanceExtensionProperties(); - - std::vector<const char*> supportedExtensions; - supportedExtensions.reserve(instanceExtensionProperties.size()); - - for (auto& elem : instanceExtensionProperties) { - supportedExtensions.push_back(elem.extensionName); - } - - if (!checkSupport(supportedExtensions, instanceExtensions)) { - throw std::runtime_error("The requested instance extensions are not supported!"); - } - - // for GLFW: get all required extensions - std::vector<const char*> requiredExtensions = getRequiredExtensions(); - instanceExtensions.insert(instanceExtensions.end(), requiredExtensions.begin(), requiredExtensions.end()); - - const vk::ApplicationInfo applicationInfo( - applicationName, - applicationVersion, - "vkCV", - VK_MAKE_VERSION(0, 0, 1), - VK_HEADER_VERSION_COMPLETE - ); - - vk::InstanceCreateInfo instanceCreateInfo( - vk::InstanceCreateFlags(), - &applicationInfo, - 0, - nullptr, - static_cast<uint32_t>(instanceExtensions.size()), - instanceExtensions.data() - ); - -#ifndef NDEBUG - instanceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size()); - instanceCreateInfo.ppEnabledLayerNames = validationLayers.data(); -#endif - - vk::Instance instance = vk::createInstance(instanceCreateInfo); - - std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices(); - vk::PhysicalDevice physicalDevice = pickPhysicalDevice(instance); - - // check for physical device extension support - std::vector<vk::ExtensionProperties> deviceExtensionProperties = physicalDevice.enumerateDeviceExtensionProperties(); - supportedExtensions.clear(); - for (auto& elem : deviceExtensionProperties) { - supportedExtensions.push_back(elem.extensionName); - } - if (!checkSupport(supportedExtensions, deviceExtensions)) { - throw std::runtime_error("The requested device extensions are not supported by the physical device!"); - } - - const vk::SurfaceKHR surface = createSurface(window.getWindow(), instance, physicalDevice); - std::vector<vk::DeviceQueueCreateInfo> qCreateInfos; - - // create required queues - std::vector<float> qPriorities; - qPriorities.resize(queueFlags.size(), 1.f); - std::vector<std::pair<int, int>> queuePairsGraphics, queuePairsCompute, queuePairsTransfer; - QueueManager::queueCreateInfosQueueHandles(physicalDevice, qPriorities, queueFlags, qCreateInfos, queuePairsGraphics, queuePairsCompute, queuePairsTransfer); - - vk::DeviceCreateInfo deviceCreateInfo( - vk::DeviceCreateFlags(), - qCreateInfos.size(), - qCreateInfos.data(), - 0, - nullptr, - deviceExtensions.size(), - deviceExtensions.data(), - nullptr // Should our device use some features??? If yes: TODO + Context context = Context::create( + applicationName, applicationVersion, + queueFlags, + instanceExtensions, + deviceExtensions + ); + + const vk::SurfaceKHR surface = createSurface( + window.getWindow(), + context.getInstance(), + context.getPhysicalDevice() ); - -#ifndef NDEBUG - deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size()); - deviceCreateInfo.ppEnabledLayerNames = validationLayers.data(); -#endif - - // Ablauf - // qCreateInfos erstellen --> braucht das Device - // device erstellen - // jetzt koennen wir mit dem device die queues erstellen - - vk::Device device = physicalDevice.createDevice(deviceCreateInfo); - - QueueManager queueManager = QueueManager::create(device, queuePairsGraphics, queuePairsCompute, queuePairsTransfer); - - Context context (instance, physicalDevice, device); SwapChain swapChain = SwapChain::create(window, context, surface); - std::vector<vk::Image> swapChainImages = device.getSwapchainImagesKHR(swapChain.getSwapchain()); + std::vector<vk::Image> swapChainImages = context.getDevice().getSwapchainImagesKHR(swapChain.getSwapchain()); std::vector<vk::ImageView> imageViews; imageViews.reserve( swapChainImages.size() ); //here can be swizzled with vk::ComponentSwizzle if needed @@ -263,14 +59,16 @@ namespace vkcv subResourceRange ); - imageViews.push_back( device.createImageView( imageViewCreateInfo )); + imageViews.push_back(context.getDevice().createImageView(imageViewCreateInfo)); } - const int graphicQueueFamilyIndex = queuePairsGraphics[0].first; + const auto& queueManager = context.getQueueManager(); + + const int graphicQueueFamilyIndex = queueManager.getGraphicsQueues()[0].familyIndex; const auto defaultCommandResources = createDefaultCommandResources(context.getDevice(), graphicQueueFamilyIndex); const auto defaultSyncResources = createDefaultSyncResources(context.getDevice()); - return Core(std::move(context) , window, swapChain, imageViews, defaultCommandResources, defaultSyncResources, queueManager); + return Core(std::move(context) , window, swapChain, imageViews, defaultCommandResources, defaultSyncResources); } const Context &Core::getContext() const @@ -279,7 +77,7 @@ namespace vkcv } Core::Core(Context &&context, const Window &window , SwapChain swapChain, std::vector<vk::ImageView> imageViews, - const CommandResources& commandResources, const SyncResources& syncResources, const QueueManager& queueManager) noexcept : + const CommandResources& commandResources, const SyncResources& syncResources) noexcept : m_Context(std::move(context)), m_window(window), m_swapchain(swapChain), @@ -287,8 +85,7 @@ namespace vkcv m_PassManager{std::make_unique<PassManager>(m_Context.m_Device)}, m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)}, m_CommandResources(commandResources), - m_SyncResources(syncResources), - m_QueueManager(queueManager) + m_SyncResources(syncResources) {} Core::~Core() noexcept { @@ -387,14 +184,16 @@ namespace vkcv m_CommandResources.commandBuffer.end(); + const auto& queueManager = m_Context.getQueueManager(); + const vk::SubmitInfo submitInfo(0, nullptr, 0, 1, &(m_CommandResources.commandBuffer), 1, &m_SyncResources.renderFinished); - m_QueueManager.getGraphicsQueues()[0].submit(submitInfo); + queueManager.getGraphicsQueues()[0].handle.submit(submitInfo); vk::Result presentResult; const vk::SwapchainKHR& swapchain = m_swapchain.getSwapchain(); const vk::PresentInfoKHR presentInfo(1, &m_SyncResources.renderFinished, 1, &swapchain, &m_currentSwapchainImageIndex, &presentResult); - m_QueueManager.getPresentQueue().presentKHR(presentInfo); + queueManager.getPresentQueue().handle.presentKHR(presentInfo); if (presentResult != vk::Result::eSuccess) { std::cout << "Error: swapchain present failed" << std::endl; } diff --git a/src/vkcv/QueueManager.cpp b/src/vkcv/QueueManager.cpp index c6c9dda4..ef34643e 100644 --- a/src/vkcv/QueueManager.cpp +++ b/src/vkcv/QueueManager.cpp @@ -1,6 +1,9 @@ -#include "vkcv/QueueManager.hpp" + +#include <limits> #include <unordered_set> +#include "vkcv/QueueManager.hpp" + namespace vkcv { /** @@ -143,14 +146,17 @@ namespace vkcv { * @param queuePairs The queuePairs that were created separately for each queue type (e.g., vk::QueueFlagBits::eGraphics) * @return An array of queue handles based on the @p queuePairs */ - std::vector<vk::Queue> getQueueHandles(const vk::Device device, const std::vector<std::pair<int, int>> queuePairs) { - std::vector<vk::Queue> queueHandles; + std::vector<Queue> getQueues(const vk::Device& device, const std::vector<std::pair<int, int>>& queuePairs) { + std::vector<Queue> queues; + for (auto q : queuePairs) { - int queueFamilyIndex = q.first; // the queueIndex of the queue family - int queueIndex = q.second; // the queueIndex within a queue family - queueHandles.push_back(device.getQueue(queueFamilyIndex, queueIndex)); + const int queueFamilyIndex = q.first; // the queueIndex of the queue family + const int queueIndex = q.second; // the queueIndex within a queue family + + queues.push_back({ queueFamilyIndex, queueIndex, device.getQueue(queueFamilyIndex, queueIndex) }); } - return queueHandles; + + return queues; } @@ -159,30 +165,30 @@ namespace vkcv { std::vector<std::pair<int, int>> &queuePairsCompute, std::vector<std::pair<int, int>> &queuePairsTransfer) { - std::vector<vk::Queue> graphicsQueues = getQueueHandles(device, queuePairsGraphics); - std::vector<vk::Queue> computeQueues = getQueueHandles(device, queuePairsCompute ); - std::vector<vk::Queue> transferQueues = getQueueHandles(device, queuePairsTransfer); + std::vector<Queue> graphicsQueues = getQueues(device, queuePairsGraphics); + std::vector<Queue> computeQueues = getQueues(device, queuePairsCompute ); + std::vector<Queue> transferQueues = getQueues(device, queuePairsTransfer); - return QueueManager( graphicsQueues, computeQueues, transferQueues, graphicsQueues[0]); + return QueueManager( std::move(graphicsQueues), std::move(computeQueues), std::move(transferQueues), 0); } - QueueManager::QueueManager(std::vector<vk::Queue> graphicsQueues, std::vector<vk::Queue> computeQueues, std::vector<vk::Queue> transferQueues, vk::Queue presentQueue) - : m_graphicsQueues(graphicsQueues), m_computeQueues(computeQueues), m_transferQueues(transferQueues), m_presentQueue(presentQueue) + QueueManager::QueueManager(std::vector<Queue>&& graphicsQueues, std::vector<Queue>&& computeQueues, std::vector<Queue>&& transferQueues, size_t presentIndex) + : m_graphicsQueues(graphicsQueues), m_computeQueues(computeQueues), m_transferQueues(transferQueues), m_presentIndex(presentIndex) {} - const vk::Queue &QueueManager::getPresentQueue() const { - return m_presentQueue; + const Queue &QueueManager::getPresentQueue() const { + return m_graphicsQueues[m_presentIndex]; } - const std::vector<vk::Queue> &QueueManager::getGraphicsQueues() const { + const std::vector<Queue> &QueueManager::getGraphicsQueues() const { return m_graphicsQueues; } - const std::vector<vk::Queue> &QueueManager::getComputeQueues() const { + const std::vector<Queue> &QueueManager::getComputeQueues() const { return m_computeQueues; } - const std::vector<vk::Queue> &QueueManager::getTransferQueues() const { + const std::vector<Queue> &QueueManager::getTransferQueues() const { return m_transferQueues; } -- GitLab