vulkan: Port to VK_EXT_debug_utils
Fixes: QTBUG-89762 Change-Id: Ie32043578968cbeda7c7f87990b98c10f5d06ff8 Reviewed-by: Andy Nichols <andy.nichols@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
parent
525a3f08e8
commit
595526e446
@ -300,7 +300,6 @@ QByteArrayList QRhiVulkanInitParams::preferredExtensionsForImportedDevice()
|
||||
{
|
||||
return {
|
||||
QByteArrayLiteral("VK_KHR_swapchain"),
|
||||
QByteArrayLiteral("VK_EXT_debug_marker"),
|
||||
QByteArrayLiteral("VK_EXT_vertex_attribute_divisor")
|
||||
};
|
||||
}
|
||||
@ -328,20 +327,19 @@ QRhiVulkan::QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *im
|
||||
}
|
||||
}
|
||||
|
||||
static bool qvk_debug_filter(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object,
|
||||
size_t location, int32_t messageCode, const char *pLayerPrefix, const char *pMessage)
|
||||
static bool qvk_debug_filter(QVulkanInstance::DebugMessageSeverityFlags severity,
|
||||
QVulkanInstance::DebugMessageTypeFlags type,
|
||||
const void *callbackData)
|
||||
{
|
||||
Q_UNUSED(flags);
|
||||
Q_UNUSED(objectType);
|
||||
Q_UNUSED(object);
|
||||
Q_UNUSED(location);
|
||||
Q_UNUSED(messageCode);
|
||||
Q_UNUSED(pLayerPrefix);
|
||||
Q_UNUSED(severity);
|
||||
Q_UNUSED(type);
|
||||
#ifdef VK_EXT_debug_utils
|
||||
const VkDebugUtilsMessengerCallbackDataEXT *d = static_cast<const VkDebugUtilsMessengerCallbackDataEXT *>(callbackData);
|
||||
|
||||
// Filter out certain misleading validation layer messages, as per
|
||||
// VulkanMemoryAllocator documentation.
|
||||
if (strstr(pMessage, "Mapping an image with layout")
|
||||
&& strstr(pMessage, "can result in undefined behavior if this memory is used by the device"))
|
||||
if (strstr(d->pMessage, "Mapping an image with layout")
|
||||
&& strstr(d->pMessage, "can result in undefined behavior if this memory is used by the device"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -352,9 +350,11 @@ static bool qvk_debug_filter(VkDebugReportFlagsEXT flags, VkDebugReportObjectTyp
|
||||
// then move on to another pool. If there is a real error, a qWarning
|
||||
// message is shown by allocateDescriptorSet(), so the validation warning
|
||||
// does not have any value and is just noise.
|
||||
if (strstr(pMessage, "VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307"))
|
||||
if (strstr(d->pMessage, "VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307"))
|
||||
return true;
|
||||
|
||||
#else
|
||||
Q_UNUSED(callbackData);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -394,6 +394,7 @@ bool QRhiVulkan::create(QRhi::Flags flags)
|
||||
for (const char *ext : inst->extensions())
|
||||
qCDebug(QRHI_LOG_INFO, " %s", ext);
|
||||
}
|
||||
caps.debugUtils = inst->extensions().contains(QByteArrayLiteral("VK_EXT_debug_utils"));
|
||||
|
||||
QList<VkQueueFamilyProperties> queueFamilyProps;
|
||||
auto queryQueueFamilyProps = [this, &queueFamilyProps] {
|
||||
@ -551,12 +552,6 @@ bool QRhiVulkan::create(QRhi::Flags flags)
|
||||
QList<const char *> requestedDevExts;
|
||||
requestedDevExts.append("VK_KHR_swapchain");
|
||||
|
||||
caps.debugMarkers = false;
|
||||
if (devExts.contains(VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
|
||||
requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
|
||||
caps.debugMarkers = true;
|
||||
}
|
||||
|
||||
caps.vertexAttribDivisor = false;
|
||||
if (devExts.contains(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
|
||||
if (inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"))) {
|
||||
@ -770,12 +765,14 @@ bool QRhiVulkan::create(QRhi::Flags flags)
|
||||
timestampQueryPoolMap.resize(QVK_MAX_ACTIVE_TIMESTAMP_PAIRS); // 1 bit per pair
|
||||
timestampQueryPoolMap.fill(false);
|
||||
|
||||
if (caps.debugMarkers) {
|
||||
vkCmdDebugMarkerBegin = reinterpret_cast<PFN_vkCmdDebugMarkerBeginEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdDebugMarkerBeginEXT"));
|
||||
vkCmdDebugMarkerEnd = reinterpret_cast<PFN_vkCmdDebugMarkerEndEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdDebugMarkerEndEXT"));
|
||||
vkCmdDebugMarkerInsert = reinterpret_cast<PFN_vkCmdDebugMarkerInsertEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdDebugMarkerInsertEXT"));
|
||||
vkDebugMarkerSetObjectName = reinterpret_cast<PFN_vkDebugMarkerSetObjectNameEXT>(f->vkGetDeviceProcAddr(dev, "vkDebugMarkerSetObjectNameEXT"));
|
||||
#ifdef VK_EXT_debug_utils
|
||||
if (caps.debugUtils) {
|
||||
vkSetDebugUtilsObjectNameEXT = reinterpret_cast<PFN_vkSetDebugUtilsObjectNameEXT>(f->vkGetDeviceProcAddr(dev, "vkSetDebugUtilsObjectNameEXT"));
|
||||
vkCmdBeginDebugUtilsLabelEXT = reinterpret_cast<PFN_vkCmdBeginDebugUtilsLabelEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdBeginDebugUtilsLabelEXT"));
|
||||
vkCmdEndDebugUtilsLabelEXT = reinterpret_cast<PFN_vkCmdEndDebugUtilsLabelEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdEndDebugUtilsLabelEXT"));
|
||||
vkCmdInsertDebugUtilsLabelEXT = reinterpret_cast<PFN_vkCmdInsertDebugUtilsLabelEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdInsertDebugUtilsLabelEXT"));
|
||||
}
|
||||
#endif
|
||||
|
||||
deviceLost = false;
|
||||
|
||||
@ -3914,17 +3911,23 @@ void QRhiVulkan::recordPrimaryCommandBuffer(QVkCommandBuffer *cbD)
|
||||
cmd.args.drawIndexed.firstInstance);
|
||||
break;
|
||||
case QVkCommandBuffer::Command::DebugMarkerBegin:
|
||||
cmd.args.debugMarkerBegin.marker.pMarkerName =
|
||||
cbD->pools.debugMarkerData[cmd.args.debugMarkerBegin.markerNameIndex].constData();
|
||||
vkCmdDebugMarkerBegin(cbD->cb, &cmd.args.debugMarkerBegin.marker);
|
||||
#ifdef VK_EXT_debug_utils
|
||||
cmd.args.debugMarkerBegin.label.pLabelName =
|
||||
cbD->pools.debugMarkerData[cmd.args.debugMarkerBegin.labelNameIndex].constData();
|
||||
vkCmdBeginDebugUtilsLabelEXT(cbD->cb, &cmd.args.debugMarkerBegin.label);
|
||||
#endif
|
||||
break;
|
||||
case QVkCommandBuffer::Command::DebugMarkerEnd:
|
||||
vkCmdDebugMarkerEnd(cbD->cb);
|
||||
#ifdef VK_EXT_debug_utils
|
||||
vkCmdEndDebugUtilsLabelEXT(cbD->cb);
|
||||
#endif
|
||||
break;
|
||||
case QVkCommandBuffer::Command::DebugMarkerInsert:
|
||||
cmd.args.debugMarkerInsert.marker.pMarkerName =
|
||||
cbD->pools.debugMarkerData[cmd.args.debugMarkerInsert.markerNameIndex].constData();
|
||||
vkCmdDebugMarkerInsert(cbD->cb, &cmd.args.debugMarkerInsert.marker);
|
||||
#ifdef VK_EXT_debug_utils
|
||||
cmd.args.debugMarkerInsert.label.pLabelName =
|
||||
cbD->pools.debugMarkerData[cmd.args.debugMarkerInsert.labelNameIndex].constData();
|
||||
vkCmdInsertDebugUtilsLabelEXT(cbD->cb, &cmd.args.debugMarkerInsert.label);
|
||||
#endif
|
||||
break;
|
||||
case QVkCommandBuffer::Command::TransitionPassResources:
|
||||
recordTransitionPassResources(cbD, cbD->passResTrackers[cmd.args.transitionResources.trackerIndex]);
|
||||
@ -4251,7 +4254,7 @@ bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const
|
||||
case QRhi::MultisampleRenderBuffer:
|
||||
return true;
|
||||
case QRhi::DebugMarkers:
|
||||
return caps.debugMarkers;
|
||||
return caps.debugUtils;
|
||||
case QRhi::Timestamps:
|
||||
return timestampValidBits != 0;
|
||||
case QRhi::Instancing:
|
||||
@ -5046,58 +5049,72 @@ void QRhiVulkan::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
|
||||
|
||||
void QRhiVulkan::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
|
||||
{
|
||||
if (!debugMarkers || !caps.debugMarkers)
|
||||
#ifdef VK_EXT_debug_utils
|
||||
if (!debugMarkers || !caps.debugUtils)
|
||||
return;
|
||||
|
||||
VkDebugMarkerMarkerInfoEXT marker = {};
|
||||
marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
|
||||
VkDebugUtilsLabelEXT label = {};
|
||||
label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
|
||||
|
||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->passUsesSecondaryCb) {
|
||||
marker.pMarkerName = name.constData();
|
||||
vkCmdDebugMarkerBegin(cbD->activeSecondaryCbStack.last(), &marker);
|
||||
label.pLabelName = name.constData();
|
||||
vkCmdBeginDebugUtilsLabelEXT(cbD->activeSecondaryCbStack.last(), &label);
|
||||
} else {
|
||||
QVkCommandBuffer::Command &cmd(cbD->commands.get());
|
||||
cmd.cmd = QVkCommandBuffer::Command::DebugMarkerBegin;
|
||||
cmd.args.debugMarkerBegin.marker = marker;
|
||||
cmd.args.debugMarkerBegin.markerNameIndex = cbD->pools.debugMarkerData.count();
|
||||
cmd.args.debugMarkerBegin.label = label;
|
||||
cmd.args.debugMarkerBegin.labelNameIndex = cbD->pools.debugMarkerData.count();
|
||||
cbD->pools.debugMarkerData.append(name);
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(cb);
|
||||
Q_UNUSED(name);
|
||||
#endif
|
||||
}
|
||||
|
||||
void QRhiVulkan::debugMarkEnd(QRhiCommandBuffer *cb)
|
||||
{
|
||||
if (!debugMarkers || !caps.debugMarkers)
|
||||
#ifdef VK_EXT_debug_utils
|
||||
if (!debugMarkers || !caps.debugUtils)
|
||||
return;
|
||||
|
||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->passUsesSecondaryCb) {
|
||||
vkCmdDebugMarkerEnd(cbD->activeSecondaryCbStack.last());
|
||||
vkCmdEndDebugUtilsLabelEXT(cbD->activeSecondaryCbStack.last());
|
||||
} else {
|
||||
QVkCommandBuffer::Command &cmd(cbD->commands.get());
|
||||
cmd.cmd = QVkCommandBuffer::Command::DebugMarkerEnd;
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(cb);
|
||||
#endif
|
||||
}
|
||||
|
||||
void QRhiVulkan::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
|
||||
{
|
||||
if (!debugMarkers || !caps.debugMarkers)
|
||||
#ifdef VK_EXT_debug_utils
|
||||
if (!debugMarkers || !caps.debugUtils)
|
||||
return;
|
||||
|
||||
VkDebugMarkerMarkerInfoEXT marker = {};
|
||||
marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
|
||||
VkDebugUtilsLabelEXT label = {};
|
||||
label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
|
||||
|
||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->passUsesSecondaryCb) {
|
||||
marker.pMarkerName = msg.constData();
|
||||
vkCmdDebugMarkerInsert(cbD->activeSecondaryCbStack.last(), &marker);
|
||||
label.pLabelName = msg.constData();
|
||||
vkCmdInsertDebugUtilsLabelEXT(cbD->activeSecondaryCbStack.last(), &label);
|
||||
} else {
|
||||
QVkCommandBuffer::Command &cmd(cbD->commands.get());
|
||||
cmd.cmd = QVkCommandBuffer::Command::DebugMarkerInsert;
|
||||
cmd.args.debugMarkerInsert.marker = marker;
|
||||
cmd.args.debugMarkerInsert.markerNameIndex = cbD->pools.debugMarkerData.count();
|
||||
cmd.args.debugMarkerInsert.label = label;
|
||||
cmd.args.debugMarkerInsert.labelNameIndex = cbD->pools.debugMarkerData.count();
|
||||
cbD->pools.debugMarkerData.append(msg);
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(cb);
|
||||
Q_UNUSED(msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
const QRhiNativeHandles *QRhiVulkan::nativeHandles(QRhiCommandBuffer *cb)
|
||||
@ -5178,22 +5195,29 @@ void QRhiVulkan::endExternal(QRhiCommandBuffer *cb)
|
||||
cbD->resetCachedState();
|
||||
}
|
||||
|
||||
void QRhiVulkan::setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name, int slot)
|
||||
void QRhiVulkan::setObjectName(uint64_t object, VkObjectType type, const QByteArray &name, int slot)
|
||||
{
|
||||
if (!debugMarkers || !caps.debugMarkers || name.isEmpty())
|
||||
#ifdef VK_EXT_debug_utils
|
||||
if (!debugMarkers || !caps.debugUtils || name.isEmpty())
|
||||
return;
|
||||
|
||||
VkDebugMarkerObjectNameInfoEXT nameInfo = {};
|
||||
nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT;
|
||||
VkDebugUtilsObjectNameInfoEXT nameInfo = {};
|
||||
nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
||||
nameInfo.objectType = type;
|
||||
nameInfo.object = object;
|
||||
nameInfo.objectHandle = object;
|
||||
QByteArray decoratedName = name;
|
||||
if (slot >= 0) {
|
||||
decoratedName += '/';
|
||||
decoratedName += QByteArray::number(slot);
|
||||
}
|
||||
nameInfo.pObjectName = decoratedName.constData();
|
||||
vkDebugMarkerSetObjectName(dev, &nameInfo);
|
||||
vkSetDebugUtilsObjectNameEXT(dev, &nameInfo);
|
||||
#else
|
||||
Q_UNUSED(object);
|
||||
Q_UNUSED(type);
|
||||
Q_UNUSED(name);
|
||||
Q_UNUSED(slot);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline VkBufferUsageFlagBits toVkBufferUsage(QRhiBuffer::UsageFlags usage)
|
||||
@ -5681,7 +5705,7 @@ bool QVkBuffer::create()
|
||||
if (err != VK_SUCCESS)
|
||||
break;
|
||||
allocations[i] = allocation;
|
||||
rhiD->setObjectName(uint64_t(buffers[i]), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, m_objectName,
|
||||
rhiD->setObjectName(uint64_t(buffers[i]), VK_OBJECT_TYPE_BUFFER, m_objectName,
|
||||
m_type == Dynamic ? i : -1);
|
||||
}
|
||||
}
|
||||
@ -5831,7 +5855,7 @@ bool QVkRenderBuffer::create()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
rhiD->setObjectName(uint64_t(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, m_objectName);
|
||||
rhiD->setObjectName(uint64_t(image), VK_OBJECT_TYPE_IMAGE, m_objectName);
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
@ -6095,7 +6119,7 @@ bool QVkTexture::create()
|
||||
if (!finishCreate())
|
||||
return false;
|
||||
|
||||
rhiD->setObjectName(uint64_t(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, m_objectName);
|
||||
rhiD->setObjectName(uint64_t(image), VK_OBJECT_TYPE_IMAGE, m_objectName);
|
||||
|
||||
owns = true;
|
||||
rhiD->registerResource(this);
|
||||
|
@ -499,14 +499,18 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
|
||||
uint32_t firstInstance;
|
||||
} drawIndexed;
|
||||
struct {
|
||||
VkDebugMarkerMarkerInfoEXT marker;
|
||||
int markerNameIndex;
|
||||
#ifdef VK_EXT_debug_utils
|
||||
VkDebugUtilsLabelEXT label;
|
||||
int labelNameIndex;
|
||||
#endif
|
||||
} debugMarkerBegin;
|
||||
struct {
|
||||
} debugMarkerEnd;
|
||||
struct {
|
||||
VkDebugMarkerMarkerInfoEXT marker;
|
||||
int markerNameIndex;
|
||||
#ifdef VK_EXT_debug_utils
|
||||
VkDebugUtilsLabelEXT label;
|
||||
int labelNameIndex;
|
||||
#endif
|
||||
} debugMarkerInsert;
|
||||
struct {
|
||||
int trackerIndex;
|
||||
@ -795,7 +799,7 @@ public:
|
||||
void executeDeferredReleases(bool forced = false);
|
||||
void finishActiveReadbacks(bool forced = false);
|
||||
|
||||
void setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name, int slot = -1);
|
||||
void setObjectName(uint64_t object, VkObjectType type, const QByteArray &name, int slot = -1);
|
||||
void trackedBufferBarrier(QVkCommandBuffer *cbD, QVkBuffer *bufD, int slot,
|
||||
VkAccessFlags access, VkPipelineStageFlags stage);
|
||||
void trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD,
|
||||
@ -833,10 +837,12 @@ public:
|
||||
bool deviceLost = false;
|
||||
bool releaseCachedResourcesCalledBeforeFrameStart = false;
|
||||
|
||||
PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBegin = nullptr;
|
||||
PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEnd = nullptr;
|
||||
PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsert = nullptr;
|
||||
PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectName = nullptr;
|
||||
#ifdef VK_EXT_debug_utils
|
||||
PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = nullptr;
|
||||
PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT = nullptr;
|
||||
PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT = nullptr;
|
||||
PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT = nullptr;
|
||||
#endif
|
||||
|
||||
PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = nullptr;
|
||||
PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
|
||||
@ -850,7 +856,7 @@ public:
|
||||
struct {
|
||||
bool compute = false;
|
||||
bool wideLines = false;
|
||||
bool debugMarkers = false;
|
||||
bool debugUtils = false;
|
||||
bool vertexAttribDivisor = false;
|
||||
bool texture3DSliceAs2D = false;
|
||||
bool tessellation = false;
|
||||
|
@ -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"));
|
||||
PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>(
|
||||
m_vkGetInstanceProcAddr(m_vkInst, "vkCreateDebugUtilsMessengerEXT"));
|
||||
|
||||
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;
|
||||
m_vkDestroyDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT>(
|
||||
m_vkGetInstanceProcAddr(m_vkInst, "vkDestroyDebugUtilsMessengerEXT"));
|
||||
|
||||
VkResult err = createDebugReportCallback(m_vkInst, &dbgCallbackInfo, nullptr, &m_debugCallback);
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user