diff options
Diffstat (limited to 'src/gui/vulkan')
-rw-r--r-- | src/gui/vulkan/qbasicvulkanplatforminstance.cpp | 107 | ||||
-rw-r--r-- | src/gui/vulkan/qbasicvulkanplatforminstance_p.h | 17 | ||||
-rw-r--r-- | src/gui/vulkan/qplatformvulkaninstance.cpp | 5 | ||||
-rw-r--r-- | src/gui/vulkan/qplatformvulkaninstance.h | 1 | ||||
-rw-r--r-- | src/gui/vulkan/qvulkaninstance.cpp | 89 | ||||
-rw-r--r-- | src/gui/vulkan/qvulkaninstance.h | 21 | ||||
-rw-r--r-- | src/gui/vulkan/qvulkaninstance_p.h | 3 |
7 files changed, 196 insertions, 47 deletions
diff --git a/src/gui/vulkan/qbasicvulkanplatforminstance.cpp b/src/gui/vulkan/qbasicvulkanplatforminstance.cpp index 6825da8069..c5a0b5de17 100644 --- a/src/gui/vulkan/qbasicvulkanplatforminstance.cpp +++ b/src/gui/vulkan/qbasicvulkanplatforminstance.cpp @@ -26,11 +26,6 @@ Q_LOGGING_CATEGORY(lcPlatVk, "qt.vulkan") */ QBasicPlatformVulkanInstance::QBasicPlatformVulkanInstance() - : m_vkInst(VK_NULL_HANDLE), - m_vkGetInstanceProcAddr(nullptr), - m_ownsVkInst(false), - m_errorCode(VK_SUCCESS), - m_debugCallback(VK_NULL_HANDLE) { } @@ -39,8 +34,10 @@ QBasicPlatformVulkanInstance::~QBasicPlatformVulkanInstance() if (!m_vkInst) return; - if (m_debugCallback && m_vkDestroyDebugReportCallbackEXT) - m_vkDestroyDebugReportCallbackEXT(m_vkInst, m_debugCallback, nullptr); +#ifdef VK_EXT_debug_utils + if (m_debugMessenger) + m_vkDestroyDebugUtilsMessengerEXT(m_vkInst, m_debugMessenger, nullptr); +#endif if (m_ownsVkInst) m_vkDestroyInstance(m_vkInst, nullptr); @@ -208,8 +205,7 @@ void QBasicPlatformVulkanInstance::initInstance(QVulkanInstance *instance, const m_enabledExtensions = instance->extensions(); if (!m_vkInst) { - VkApplicationInfo appInfo; - memset(&appInfo, 0, sizeof(appInfo)); + VkApplicationInfo appInfo = {}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; QByteArray appName = QCoreApplication::applicationName().toUtf8(); appInfo.pApplicationName = appName.constData(); @@ -221,7 +217,7 @@ void QBasicPlatformVulkanInstance::initInstance(QVulkanInstance *instance, const } if (!flags.testFlag(QVulkanInstance::NoDebugOutputRedirect)) - m_enabledExtensions.append("VK_EXT_debug_report"); + m_enabledExtensions.append("VK_EXT_debug_utils"); m_enabledExtensions.append("VK_KHR_surface"); @@ -259,8 +255,7 @@ void QBasicPlatformVulkanInstance::initInstance(QVulkanInstance *instance, const } qDebug(lcPlatVk) << "Enabling Vulkan instance extensions:" << m_enabledExtensions; - VkInstanceCreateInfo instInfo; - memset(&instInfo, 0, sizeof(instInfo)); + VkInstanceCreateInfo instInfo = {}; instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instInfo.pApplicationInfo = &appInfo; @@ -365,55 +360,93 @@ void QBasicPlatformVulkanInstance::setDebugFilters(const QList<QVulkanInstance:: m_debugFilters = filters; } +void QBasicPlatformVulkanInstance::setDebugUtilsFilters(const QList<QVulkanInstance::DebugUtilsFilter> &filters) +{ + m_debugUtilsFilters = filters; +} + void QBasicPlatformVulkanInstance::destroySurface(VkSurfaceKHR surface) const { if (m_destroySurface && surface) m_destroySurface(m_vkInst, surface, nullptr); } -static VKAPI_ATTR VkBool32 VKAPI_CALL defaultDebugCallbackFunc(VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objectType, - uint64_t object, - size_t location, - int32_t messageCode, - const char *pLayerPrefix, - const char *pMessage, +#ifdef VK_EXT_debug_utils +static VKAPI_ATTR VkBool32 VKAPI_CALL defaultDebugCallbackFunc(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData) { QBasicPlatformVulkanInstance *self = static_cast<QBasicPlatformVulkanInstance *>(pUserData); + + // legacy filters for (QVulkanInstance::DebugFilter filter : *self->debugFilters()) { - if (filter(flags, objectType, object, location, messageCode, pLayerPrefix, pMessage)) + // As per docs in qvulkaninstance.cpp we pass object, messageCode, + // pMessage to the callback with the legacy signature. + uint64_t object = 0; + if (pCallbackData->objectCount > 0) + object = pCallbackData->pObjects[0].objectHandle; + if (filter(0, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, object, 0, + pCallbackData->messageIdNumber, "", pCallbackData->pMessage)) + { + return VK_FALSE; + } + } + + // filters with new signature + for (QVulkanInstance::DebugUtilsFilter filter : *self->debugUtilsFilters()) { + QVulkanInstance::DebugMessageSeverityFlags severity; + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) + severity |= QVulkanInstance::VerboseSeverity; + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) + severity |= QVulkanInstance::InfoSeverity; + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) + severity |= QVulkanInstance::WarningSeverity; + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) + severity |= QVulkanInstance::ErrorSeverity; + QVulkanInstance::DebugMessageTypeFlags type; + if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) + type |= QVulkanInstance::GeneralMessage; + if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) + type |= QVulkanInstance::ValidationMessage; + if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) + type |= QVulkanInstance::PerformanceMessage; + if (filter(severity, type, pCallbackData)) return VK_FALSE; } // not categorized, just route to plain old qDebug - qDebug("vkDebug: %s: %d: %s", pLayerPrefix, messageCode, pMessage); + qDebug("vkDebug: %s", pCallbackData->pMessage); return VK_FALSE; } +#endif void QBasicPlatformVulkanInstance::setupDebugOutput() { - if (!m_enabledExtensions.contains("VK_EXT_debug_report")) +#ifdef VK_EXT_debug_utils + if (!m_enabledExtensions.contains("VK_EXT_debug_utils")) return; - PFN_vkCreateDebugReportCallbackEXT createDebugReportCallback = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>( - m_vkGetInstanceProcAddr(m_vkInst, "vkCreateDebugReportCallbackEXT")); - m_vkDestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>( - m_vkGetInstanceProcAddr(m_vkInst, "vkDestroyDebugReportCallbackEXT")); - - VkDebugReportCallbackCreateInfoEXT dbgCallbackInfo; - memset(&dbgCallbackInfo, 0, sizeof(dbgCallbackInfo)); - dbgCallbackInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; - dbgCallbackInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT - | VK_DEBUG_REPORT_WARNING_BIT_EXT - | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; - dbgCallbackInfo.pfnCallback = defaultDebugCallbackFunc; - dbgCallbackInfo.pUserData = this; - - VkResult err = createDebugReportCallback(m_vkInst, &dbgCallbackInfo, nullptr, &m_debugCallback); + PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>( + m_vkGetInstanceProcAddr(m_vkInst, "vkCreateDebugUtilsMessengerEXT")); + + m_vkDestroyDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT>( + m_vkGetInstanceProcAddr(m_vkInst, "vkDestroyDebugUtilsMessengerEXT")); + + VkDebugUtilsMessengerCreateInfoEXT messengerInfo = {}; + messengerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + messengerInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT + | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + messengerInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT + | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT + | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + messengerInfo.pfnUserCallback = defaultDebugCallbackFunc; + messengerInfo.pUserData = this; + VkResult err = vkCreateDebugUtilsMessengerEXT(m_vkInst, &messengerInfo, nullptr, &m_debugMessenger); if (err != VK_SUCCESS) qWarning("Failed to create debug report callback: %d", err); +#endif } QT_END_NAMESPACE diff --git a/src/gui/vulkan/qbasicvulkanplatforminstance_p.h b/src/gui/vulkan/qbasicvulkanplatforminstance_p.h index 70e9d65ef3..dfa5003f16 100644 --- a/src/gui/vulkan/qbasicvulkanplatforminstance_p.h +++ b/src/gui/vulkan/qbasicvulkanplatforminstance_p.h @@ -40,17 +40,19 @@ public: PFN_vkVoidFunction getInstanceProcAddr(const char *name) override; bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override; void setDebugFilters(const QList<QVulkanInstance::DebugFilter> &filters) override; + void setDebugUtilsFilters(const QList<QVulkanInstance::DebugUtilsFilter> &filters) override; void destroySurface(VkSurfaceKHR surface) const; const QList<QVulkanInstance::DebugFilter> *debugFilters() const { return &m_debugFilters; } + const QList<QVulkanInstance::DebugUtilsFilter> *debugUtilsFilters() const { return &m_debugUtilsFilters; } protected: void loadVulkanLibrary(const QString &defaultLibraryName, int defaultLibraryVersion = -1); void init(QLibrary *lib); void initInstance(QVulkanInstance *instance, const QByteArrayList &extraExts); - VkInstance m_vkInst; - PFN_vkGetInstanceProcAddr m_vkGetInstanceProcAddr; + VkInstance m_vkInst = VK_NULL_HANDLE; + PFN_vkGetInstanceProcAddr m_vkGetInstanceProcAddr = nullptr; PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_getPhysDevSurfaceSupport; PFN_vkDestroySurfaceKHR m_destroySurface; @@ -59,8 +61,8 @@ private: std::unique_ptr<QLibrary> m_vulkanLib; - bool m_ownsVkInst; - VkResult m_errorCode; + bool m_ownsVkInst = false; + VkResult m_errorCode = VK_SUCCESS; QVulkanInfoVector<QVulkanLayer> m_supportedLayers; QVulkanInfoVector<QVulkanExtension> m_supportedExtensions; QVersionNumber m_supportedApiVersion; @@ -73,9 +75,12 @@ private: PFN_vkDestroyInstance m_vkDestroyInstance; - VkDebugReportCallbackEXT m_debugCallback; - PFN_vkDestroyDebugReportCallbackEXT m_vkDestroyDebugReportCallbackEXT; +#ifdef VK_EXT_debug_utils + VkDebugUtilsMessengerEXT m_debugMessenger = VK_NULL_HANDLE; + PFN_vkDestroyDebugUtilsMessengerEXT m_vkDestroyDebugUtilsMessengerEXT; +#endif QList<QVulkanInstance::DebugFilter> m_debugFilters; + QList<QVulkanInstance::DebugUtilsFilter> m_debugUtilsFilters; }; QT_END_NAMESPACE diff --git a/src/gui/vulkan/qplatformvulkaninstance.cpp b/src/gui/vulkan/qplatformvulkaninstance.cpp index 0349358993..2955f2f300 100644 --- a/src/gui/vulkan/qplatformvulkaninstance.cpp +++ b/src/gui/vulkan/qplatformvulkaninstance.cpp @@ -59,4 +59,9 @@ void QPlatformVulkanInstance::setDebugFilters(const QList<QVulkanInstance::Debug Q_UNUSED(filters); } +void QPlatformVulkanInstance::setDebugUtilsFilters(const QList<QVulkanInstance::DebugUtilsFilter> &filters) +{ + Q_UNUSED(filters); +} + QT_END_NAMESPACE diff --git a/src/gui/vulkan/qplatformvulkaninstance.h b/src/gui/vulkan/qplatformvulkaninstance.h index 2bb89f1018..a3dcc37f0b 100644 --- a/src/gui/vulkan/qplatformvulkaninstance.h +++ b/src/gui/vulkan/qplatformvulkaninstance.h @@ -45,6 +45,7 @@ public: virtual void presentAboutToBeQueued(QWindow *window); virtual void presentQueued(QWindow *window); virtual void setDebugFilters(const QList<QVulkanInstance::DebugFilter> &filters); + virtual void setDebugUtilsFilters(const QList<QVulkanInstance::DebugUtilsFilter> &filters); private: QScopedPointer<QPlatformVulkanInstancePrivate> d_ptr; diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp index bfc4b38b5a..83d1e9b1b5 100644 --- a/src/gui/vulkan/qvulkaninstance.cpp +++ b/src/gui/vulkan/qvulkaninstance.cpp @@ -104,7 +104,7 @@ QT_BEGIN_NAMESPACE \note It is up to the component creating the external instance to ensure the necessary extensions are enabled on it. These are: \c{VK_KHR_surface}, the WSI-specific \c{VK_KHR_*_surface} that is appropriate for the platform - in question, and \c{VK_EXT_debug_report} in case QVulkanInstance's debug + in question, and \c{VK_EXT_debug_utils} in case QVulkanInstance's debug output redirection is desired. \section1 Accessing Core Vulkan Commands @@ -205,7 +205,7 @@ QT_BEGIN_NAMESPACE This enum describes the flags that can be passed to setFlags(). These control the behavior of create(). - \value NoDebugOutputRedirect Disables Vulkan debug output (\c{VK_EXT_debug_report}) redirection to qDebug. + \value NoDebugOutputRedirect Disables Vulkan debug output (\c{VK_EXT_debug_utils}) redirection to qDebug. */ bool QVulkanInstancePrivate::ensureVulkan() @@ -425,7 +425,7 @@ QVersionNumber QVulkanInstance::supportedApiVersion() const \note \a existingVkInstance must have at least \c{VK_KHR_surface} and the appropriate WSI-specific \c{VK_KHR_*_surface} extensions enabled. To ensure - debug output redirection is functional, \c{VK_EXT_debug_report} is needed as + debug output redirection is functional, \c{VK_EXT_debug_utils} is needed as well. \note This function can only be called before create() and has no effect if @@ -812,10 +812,21 @@ void QVulkanInstance::presentQueued(QWindow *window) Typedef for debug filtering callback functions. + Returning \c true suppresses the printing of the message. + + \note Starting with Qt 6.5 \c{VK_EXT_debug_utils} is used instead of the + deprecated \c{VK_EXT_debug_report}. The callback signature is based on + VK_EXT_debug_report. Therefore, not all arguments can be expected to be + valid anymore. Avoid relying on arguments other than \c pMessage, \c + messageCode, and \c object. Applications wishing to access all the callback + data as specified in VK_EXT_debug_utils should migrate to DebugUtilsFilter. + \sa installDebugOutputFilter(), removeDebugOutputFilter() */ /*! + \overload + Installs a \a filter function that is called for every Vulkan debug message. When the callback returns \c true, the message is stopped (filtered out) and will not appear on the debug output. @@ -837,6 +848,8 @@ void QVulkanInstance::installDebugOutputFilter(DebugFilter filter) } /*! + \overload + Removes a \a filter function previously installed by installDebugOutputFilter(). @@ -851,6 +864,76 @@ void QVulkanInstance::removeDebugOutputFilter(DebugFilter filter) d_ptr->platformInst->setDebugFilters(d_ptr->debugFilters); } +/*! + \typedef QVulkanInstance::DebugUtilsFilter + + Typedef for debug filtering callback functions. The \c callbackData + argument is a pointer to the VkDebugUtilsMessengerCallbackDataEXT + structure. + + Returning \c true suppresses the printing of the message. + + \sa installDebugOutputFilter(), removeDebugOutputFilter() + \since 6.5 + */ + +/*! + \enum QVulkanInstance::DebugMessageSeverityFlag + \since 6.5 + + \value VerboseSeverity + \value InfoSeverity + \value WarningSeverity + \value ErrorSeverity + */ + +/*! + \enum QVulkanInstance::DebugMessageTypeFlag + \since 6.5 + + \value GeneralMessage + \value ValidationMessage + \value PerformanceMessage + */ + +/*! + Installs a \a filter function that is called for every Vulkan debug + message. When the callback returns \c true, the message is stopped (filtered + out) and will not appear on the debug output. + + \note Filtering is only effective when NoDebugOutputRedirect is not + \l{setFlags()}{set}. Installing filters has no effect otherwise. + + \note This function can be called before create(). + + \sa removeDebugOutputFilter() + \since 6.5 + */ +void QVulkanInstance::installDebugOutputFilter(DebugUtilsFilter filter) +{ + if (!d_ptr->debugUtilsFilters.contains(filter)) { + d_ptr->debugUtilsFilters.append(filter); + if (d_ptr->platformInst) + d_ptr->platformInst->setDebugUtilsFilters(d_ptr->debugUtilsFilters); + } +} + +/*! + Removes a \a filter function previously installed by + installDebugOutputFilter(). + + \note This function can be called before create(). + + \sa installDebugOutputFilter() + \since 6.5 + */ +void QVulkanInstance::removeDebugOutputFilter(DebugUtilsFilter filter) +{ + d_ptr->debugUtilsFilters.removeOne(filter); + if (d_ptr->platformInst) + d_ptr->platformInst->setDebugUtilsFilters(d_ptr->debugUtilsFilters); +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QVulkanLayer &layer) { diff --git a/src/gui/vulkan/qvulkaninstance.h b/src/gui/vulkan/qvulkaninstance.h index a51ce5ec99..6fd5116aab 100644 --- a/src/gui/vulkan/qvulkaninstance.h +++ b/src/gui/vulkan/qvulkaninstance.h @@ -187,6 +187,25 @@ public: void installDebugOutputFilter(DebugFilter filter); void removeDebugOutputFilter(DebugFilter filter); + enum DebugMessageSeverityFlag { + VerboseSeverity = 0x01, + InfoSeverity = 0x02, + WarningSeverity = 0x04, + ErrorSeverity = 0x08 + }; + Q_DECLARE_FLAGS(DebugMessageSeverityFlags, DebugMessageSeverityFlag) + + enum DebugMessageTypeFlag { + GeneralMessage = 0x01, + ValidationMessage = 0x02, + PerformanceMessage = 0x04 + }; + Q_DECLARE_FLAGS(DebugMessageTypeFlags, DebugMessageTypeFlag) + + typedef bool (*DebugUtilsFilter)(DebugMessageSeverityFlags severity, DebugMessageTypeFlags type, const void *callbackData); + void installDebugOutputFilter(DebugUtilsFilter filter); + void removeDebugOutputFilter(DebugUtilsFilter filter); + private: friend class QVulkanInstancePrivate; QScopedPointer<QVulkanInstancePrivate> d_ptr; @@ -194,6 +213,8 @@ private: }; Q_DECLARE_OPERATORS_FOR_FLAGS(QVulkanInstance::Flags) +Q_DECLARE_OPERATORS_FOR_FLAGS(QVulkanInstance::DebugMessageTypeFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(QVulkanInstance::DebugMessageSeverityFlags) QT_END_NAMESPACE diff --git a/src/gui/vulkan/qvulkaninstance_p.h b/src/gui/vulkan/qvulkaninstance_p.h index 27dc5383cf..9545d4e688 100644 --- a/src/gui/vulkan/qvulkaninstance_p.h +++ b/src/gui/vulkan/qvulkaninstance_p.h @@ -49,7 +49,8 @@ public: VkResult errorCode; QScopedPointer<QVulkanFunctions> funcs; QHash<VkDevice, QVulkanDeviceFunctions *> deviceFuncs; - QList<QVulkanInstance::DebugFilter> debugFilters; + QList<QVulkanInstance::DebugFilter> debugFilters; // legacy filters based on VK_EXT_debug_report + QList<QVulkanInstance::DebugUtilsFilter> debugUtilsFilters; // the modern version based on VK_EXT_debug_utils }; QT_END_NAMESPACE |