From 699a0d2deea754ce581621ad0934da3360e63cc8 Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Sun, 25 Aug 2019 14:19:20 +0200 Subject: QVulkanWindow: Add function to retrieve graphics queue family index Change-Id: I51e4a006e82fbcd998815da3de6daa80558a973f Reviewed-by: Laszlo Agocs --- src/gui/vulkan/qvulkanwindow.cpp | 17 +++++++++++++++++ src/gui/vulkan/qvulkanwindow.h | 1 + 2 files changed, 18 insertions(+) (limited to 'src/gui/vulkan') diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp index 6d12377a60..3eabf72960 100644 --- a/src/gui/vulkan/qvulkanwindow.cpp +++ b/src/gui/vulkan/qvulkanwindow.cpp @@ -2210,6 +2210,23 @@ VkQueue QVulkanWindow::graphicsQueue() const return d->gfxQueue; } +/*! + Returns the family index of the active graphics queue. + + \note Calling this function is only valid from the invocation of + QVulkanWindowRenderer::initResources() up until + QVulkanWindowRenderer::releaseResources(). Implementations of + QVulkanWindowRenderer::updateQueueCreateInfo() can also call this + function. + + \since 5.15 + */ +uint32_t QVulkanWindow::graphicsQueueFamilyIndex() const +{ + Q_D(const QVulkanWindow); + return d->gfxQueueFamilyIdx; +} + /*! Returns the active graphics command pool. diff --git a/src/gui/vulkan/qvulkanwindow.h b/src/gui/vulkan/qvulkanwindow.h index 927c81042f..9169058138 100644 --- a/src/gui/vulkan/qvulkanwindow.h +++ b/src/gui/vulkan/qvulkanwindow.h @@ -112,6 +112,7 @@ public: const VkPhysicalDeviceProperties *physicalDeviceProperties() const; VkDevice device() const; VkQueue graphicsQueue() const; + uint32_t graphicsQueueFamilyIndex() const; VkCommandPool graphicsCommandPool() const; uint32_t hostVisibleMemoryIndex() const; uint32_t deviceLocalMemoryIndex() const; -- cgit v1.2.3 From 36a5b00a9245e0a6e3d690ecb234ebd464eedb7f Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Sat, 24 Aug 2019 18:25:51 +0200 Subject: 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(-) (limited to 'src/gui/vulkan') 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; -- cgit v1.2.3 From 3afe4a402c18a0956cab31169d843018d1b7a6d3 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 3 Oct 2019 17:08:13 +0200 Subject: Convert a few sizeof(array)/sizeof(element0) fors to range fors Increases readability Change-Id: I81ea915517fd2cd6bc2780f37ba8d8097c63f44b Reviewed-by: Thiago Macieira Reviewed-by: Volker Hilsheimer --- src/gui/vulkan/qvulkanwindow.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/gui/vulkan') diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp index 6d12377a60..4b5c2b56ee 100644 --- a/src/gui/vulkan/qvulkanwindow.cpp +++ b/src/gui/vulkan/qvulkanwindow.cpp @@ -498,12 +498,12 @@ QVector QVulkanWindow::supportedSampleCounts() VkSampleCountFlags depth = limits->framebufferDepthSampleCounts; VkSampleCountFlags stencil = limits->framebufferStencilSampleCounts; - for (size_t i = 0; i < sizeof(qvk_sampleCounts) / sizeof(qvk_sampleCounts[0]); ++i) { - if ((color & qvk_sampleCounts[i].mask) - && (depth & qvk_sampleCounts[i].mask) - && (stencil & qvk_sampleCounts[i].mask)) + for (const auto &qvk_sampleCount : qvk_sampleCounts) { + if ((color & qvk_sampleCount.mask) + && (depth & qvk_sampleCount.mask) + && (stencil & qvk_sampleCount.mask)) { - result.append(qvk_sampleCounts[i].count); + result.append(qvk_sampleCount.count); } } @@ -547,9 +547,9 @@ void QVulkanWindow::setSampleCount(int sampleCount) return; } - for (size_t i = 0; i < sizeof(qvk_sampleCounts) / sizeof(qvk_sampleCounts[0]); ++i) { - if (qvk_sampleCounts[i].count == sampleCount) { - d->sampleCount = qvk_sampleCounts[i].mask; + for (const auto &qvk_sampleCount : qvk_sampleCounts) { + if (qvk_sampleCount.count == sampleCount) { + d->sampleCount = qvk_sampleCount.mask; return; } } -- cgit v1.2.3 From 7a3d647bab633caae270a74d8a398669bbfe8521 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Fri, 4 Oct 2019 14:49:30 +0200 Subject: Vulkan: Add platform hooks before presenting This allows the Wayland plugin to circumvent the frame callback handling of the driver (which blocks until the frame is presented, potentially forever, if the window is minimized). Task-number: QTBUG-78000 Change-Id: Ia7d347019dfeae3bfcfad3d0cca3f4fffdc8c7a9 Reviewed-by: Laszlo Agocs --- src/gui/vulkan/qplatformvulkaninstance.cpp | 5 +++++ src/gui/vulkan/qplatformvulkaninstance.h | 1 + src/gui/vulkan/qvulkaninstance.cpp | 14 ++++++++++++++ src/gui/vulkan/qvulkaninstance.h | 1 + src/gui/vulkan/qvulkanwindow.cpp | 4 ++++ 5 files changed, 25 insertions(+) (limited to 'src/gui/vulkan') diff --git a/src/gui/vulkan/qplatformvulkaninstance.cpp b/src/gui/vulkan/qplatformvulkaninstance.cpp index 9d044bfd58..1b5d3370f0 100644 --- a/src/gui/vulkan/qplatformvulkaninstance.cpp +++ b/src/gui/vulkan/qplatformvulkaninstance.cpp @@ -80,6 +80,11 @@ QPlatformVulkanInstance::~QPlatformVulkanInstance() { } +void QPlatformVulkanInstance::presentAboutToBeQueued(QWindow *window) +{ + Q_UNUSED(window); +} + void QPlatformVulkanInstance::presentQueued(QWindow *window) { Q_UNUSED(window); diff --git a/src/gui/vulkan/qplatformvulkaninstance.h b/src/gui/vulkan/qplatformvulkaninstance.h index d47c59b5db..f96f1720fb 100644 --- a/src/gui/vulkan/qplatformvulkaninstance.h +++ b/src/gui/vulkan/qplatformvulkaninstance.h @@ -77,6 +77,7 @@ public: virtual QByteArrayList enabledExtensions() const = 0; virtual PFN_vkVoidFunction getInstanceProcAddr(const char *name) = 0; virtual bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) = 0; + virtual void presentAboutToBeQueued(QWindow *window); virtual void presentQueued(QWindow *window); virtual void setDebugFilters(const QVector &filters); diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp index 0605d88cca..daf37e3dc8 100644 --- a/src/gui/vulkan/qvulkaninstance.cpp +++ b/src/gui/vulkan/qvulkaninstance.cpp @@ -774,6 +774,20 @@ bool QVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, uint32_t return d_ptr->platformInst->supportsPresent(physicalDevice, queueFamilyIndex, window); } +/*! + This function should be called by the application's renderer before queuing + a present operation for \a window. + + While on some platforms this will be a no-op, some may perform windowing + system dependent synchronization. For example, on Wayland this will + add send a wl_surface.frame request in order to prevent the driver from + blocking for minimized windows. + */ +void QVulkanInstance::presentAboutToBeQueued(QWindow *window) +{ + d_ptr->platformInst->presentAboutToBeQueued(window); +} + /*! This function should be called by the application's renderer after queuing a present operation for \a window. diff --git a/src/gui/vulkan/qvulkaninstance.h b/src/gui/vulkan/qvulkaninstance.h index 70f2fd5102..5b3db9a4c8 100644 --- a/src/gui/vulkan/qvulkaninstance.h +++ b/src/gui/vulkan/qvulkaninstance.h @@ -186,6 +186,7 @@ public: bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window); + void presentAboutToBeQueued(QWindow *window); void presentQueued(QWindow *window); typedef bool (*DebugFilter)(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp index caf53eb586..790bef9e14 100644 --- a/src/gui/vulkan/qvulkanwindow.cpp +++ b/src/gui/vulkan/qvulkanwindow.cpp @@ -2018,6 +2018,10 @@ void QVulkanWindowPrivate::endFrame() presInfo.waitSemaphoreCount = 1; presInfo.pWaitSemaphores = gfxQueueFamilyIdx == presQueueFamilyIdx ? &frame.drawSem : &frame.presTransSem; + // Do platform-specific WM notification. F.ex. essential on Wayland in + // order to circumvent driver frame callbacks + inst->presentAboutToBeQueued(q); + err = vkQueuePresentKHR(gfxQueue, &presInfo); if (err != VK_SUCCESS) { if (err == VK_ERROR_OUT_OF_DATE_KHR) { -- cgit v1.2.3