From 36a5b00a9245e0a6e3d690ecb234ebd464eedb7f Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Sat, 24 Aug 2019 18:25:51 +0200 Subject: [PATCH] QVulkanWindow: Allow to change queues to create This allows users to request queues beyond the default graphics queue without having to completely reimplement Vulkan device initialization or giving up the convenience of QVulkanWindow. [ChangeLog][QtGui] Extended QVulkanWindow to allow user to specify additional queues to be created. Change-Id: I96d8d4bcc4da3ffedca3d25c87547669f5b18e40 Reviewed-by: Laszlo Agocs --- src/gui/vulkan/qvulkanwindow.cpp | 92 +++++++++++++++++++++++++++----- src/gui/vulkan/qvulkanwindow.h | 6 +++ src/gui/vulkan/qvulkanwindow_p.h | 1 + 3 files changed, 87 insertions(+), 12 deletions(-) diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp index 3eabf72960..1114516fa8 100644 --- a/src/gui/vulkan/qvulkanwindow.cpp +++ b/src/gui/vulkan/qvulkanwindow.cpp @@ -647,18 +647,40 @@ void QVulkanWindowPrivate::init() #endif qCDebug(lcGuiVk, "Using queue families: graphics = %u present = %u", gfxQueueFamilyIdx, presQueueFamilyIdx); - VkDeviceQueueCreateInfo queueInfo[2]; + QVector queueInfo; + queueInfo.reserve(2); const float prio[] = { 0 }; - memset(queueInfo, 0, sizeof(queueInfo)); - queueInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueInfo[0].queueFamilyIndex = gfxQueueFamilyIdx; - queueInfo[0].queueCount = 1; - queueInfo[0].pQueuePriorities = prio; + VkDeviceQueueCreateInfo addQueueInfo; + memset(&addQueueInfo, 0, sizeof(addQueueInfo)); + addQueueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + addQueueInfo.queueFamilyIndex = gfxQueueFamilyIdx; + addQueueInfo.queueCount = 1; + addQueueInfo.pQueuePriorities = prio; + queueInfo.append(addQueueInfo); if (gfxQueueFamilyIdx != presQueueFamilyIdx) { - queueInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueInfo[1].queueFamilyIndex = presQueueFamilyIdx; - queueInfo[1].queueCount = 1; - queueInfo[1].pQueuePriorities = prio; + addQueueInfo.queueFamilyIndex = presQueueFamilyIdx; + addQueueInfo.queueCount = 1; + addQueueInfo.pQueuePriorities = prio; + queueInfo.append(addQueueInfo); + } + if (queueCreateInfoModifier) { + queueCreateInfoModifier(queueFamilyProps.constData(), queueCount, queueInfo); + bool foundGfxQueue = false; + bool foundPresQueue = false; + for (const VkDeviceQueueCreateInfo& createInfo : qAsConst(queueInfo)) { + foundGfxQueue |= createInfo.queueFamilyIndex == gfxQueueFamilyIdx; + foundPresQueue |= createInfo.queueFamilyIndex == presQueueFamilyIdx; + } + if (!foundGfxQueue) { + qWarning("QVulkanWindow: Graphics queue missing after call to queueCreateInfoModifier"); + status = StatusFail; + return; + } + if (!foundPresQueue) { + qWarning("QVulkanWindow: Present queue missing after call to queueCreateInfoModifier"); + status = StatusFail; + return; + } } // Filter out unsupported extensions in order to keep symmetry @@ -676,8 +698,8 @@ void QVulkanWindowPrivate::init() VkDeviceCreateInfo devInfo; memset(&devInfo, 0, sizeof(devInfo)); devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - devInfo.queueCreateInfoCount = gfxQueueFamilyIdx == presQueueFamilyIdx ? 1 : 2; - devInfo.pQueueCreateInfos = queueInfo; + devInfo.queueCreateInfoCount = queueInfo.size(); + devInfo.pQueueCreateInfos = queueInfo.constData(); devInfo.enabledExtensionCount = devExts.count(); devInfo.ppEnabledExtensionNames = devExts.constData(); @@ -1545,6 +1567,52 @@ bool QVulkanWindow::event(QEvent *e) return QWindow::event(e); } +/*! + \typedef QVulkanWindow::QueueCreateInfoModifier + + A function function that is called during graphics initialization to add + additAional queues that should be created. + + Set if the renderer needs additional queues besides the default graphics + queue (e.g. a transfer queue). + The provided queue family properties can be used to select the indices for + the additional queues. + The renderer can subsequently request the actual queue in initResources(). + + Note when requesting additional graphics queues: Qt itself always requests + a graphics queue, you'll need to search queueCreateInfo for the appropriate + entry and manipulate it to obtain the additional queue. + + \sa setQueueCreateInfoModifier() + */ + +/*! + Return a previously set queue create info modification function. + + \sa setQueueCreateInfoModifier() + + \since 5.15 + */ +QVulkanWindow::QueueCreateInfoModifier QVulkanWindow::queueCreateInfoModifier() const +{ + Q_D(const QVulkanWindow); + return d->queueCreateInfoModifier; +} + +/*! + Set a queue create info modification function. + + \sa queueCreateInfoModifier() + + \since 5.15 + */ +void QVulkanWindow::setQueueCreateInfoModifier(QueueCreateInfoModifier modifier) +{ + Q_D(QVulkanWindow); + d->queueCreateInfoModifier = modifier; +} + + /*! Returns true if this window has successfully initialized all Vulkan resources, including the swapchain. diff --git a/src/gui/vulkan/qvulkanwindow.h b/src/gui/vulkan/qvulkanwindow.h index 9169058138..530b6c0744 100644 --- a/src/gui/vulkan/qvulkanwindow.h +++ b/src/gui/vulkan/qvulkanwindow.h @@ -103,6 +103,12 @@ public: QVector supportedSampleCounts(); void setSampleCount(int sampleCount); + typedef std::function &)> QueueCreateInfoModifier; + QueueCreateInfoModifier queueCreateInfoModifier() const; + void setQueueCreateInfoModifier(QueueCreateInfoModifier modifier); + bool isValid() const; virtual QVulkanWindowRenderer *createRenderer(); diff --git a/src/gui/vulkan/qvulkanwindow_p.h b/src/gui/vulkan/qvulkanwindow_p.h index fb374a5564..777be237a8 100644 --- a/src/gui/vulkan/qvulkanwindow_p.h +++ b/src/gui/vulkan/qvulkanwindow_p.h @@ -102,6 +102,7 @@ public: QHash > supportedDevExtensions; QVector requestedColorFormats; VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; + QVulkanWindow::QueueCreateInfoModifier queueCreateInfoModifier; VkDevice dev = VK_NULL_HANDLE; QVulkanDeviceFunctions *devFuncs;