5#include <QCoreApplication>
7#include <QLoggingCategory>
8#include <QVarLengthArray>
37#ifdef VK_EXT_debug_utils
39 m_vkDestroyDebugUtilsMessengerEXT(
m_vkInst, m_debugMessenger,
nullptr);
43 m_vkDestroyInstance(
m_vkInst,
nullptr);
48 QVarLengthArray<std::pair<QString, int>, 3> loadList;
58 loadList.append({ defaultLibraryName, defaultLibraryVersion });
63 if (defaultLibraryVersion >= 0)
64 loadList.append({ defaultLibraryName, -1 });
67 for (
const auto &lib : loadList) {
70 m_vulkanLib->setFileNameAndVersion(lib.first, lib.second);
72 m_vulkanLib->setFileName(lib.first);
73 if (m_vulkanLib->load()) {
84 init(m_vulkanLib.get());
103 qWarning(
"Failed to find vkGetInstanceProcAddr");
107 m_vkCreateInstance =
reinterpret_cast<PFN_vkCreateInstance
>(
m_vkGetInstanceProcAddr(VK_NULL_HANDLE,
"vkCreateInstance"));
108 if (!m_vkCreateInstance) {
109 qWarning(
"Failed to find vkCreateInstance");
112 m_vkEnumerateInstanceLayerProperties =
reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties
>(
114 if (!m_vkEnumerateInstanceLayerProperties) {
115 qWarning(
"Failed to find vkEnumerateInstanceLayerProperties");
118 m_vkEnumerateInstanceExtensionProperties =
reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties
>(
120 if (!m_vkEnumerateInstanceExtensionProperties) {
121 qWarning(
"Failed to find vkEnumerateInstanceExtensionProperties");
126 typedef VkResult (VKAPI_PTR *T_enumerateInstanceVersion)(uint32_t* pApiVersion);
128 T_enumerateInstanceVersion enumerateInstanceVersion =
reinterpret_cast<T_enumerateInstanceVersion
>(
130 if (enumerateInstanceVersion) {
132 if (enumerateInstanceVersion(&ver) == VK_SUCCESS) {
134 VK_VERSION_MINOR(ver),
135 VK_VERSION_PATCH(ver));
144 uint32_t layerCount = 0;
145 m_vkEnumerateInstanceLayerProperties(&layerCount,
nullptr);
147 QList<VkLayerProperties> layerProps(layerCount);
148 m_vkEnumerateInstanceLayerProperties(&layerCount, layerProps.data());
149 m_supportedLayers.reserve(layerCount);
150 for (
const VkLayerProperties &
p : std::as_const(layerProps)) {
153 layer.version =
p.implementationVersion;
155 VK_VERSION_MINOR(
p.specVersion),
156 VK_VERSION_PATCH(
p.specVersion));
157 layer.description =
p.description;
158 m_supportedLayers.append(
layer);
161 qCDebug(lcPlatVk) <<
"Supported Vulkan instance layers:" << m_supportedLayers;
163 uint32_t extCount = 0;
164 m_vkEnumerateInstanceExtensionProperties(
nullptr, &extCount,
nullptr);
166 QList<VkExtensionProperties> extProps(extCount);
167 m_vkEnumerateInstanceExtensionProperties(
nullptr, &extCount, extProps.data());
168 m_supportedExtensions.reserve(extCount);
169 for (
const VkExtensionProperties &
p : std::as_const(extProps)) {
171 ext.name =
p.extensionName;
172 ext.version =
p.specVersion;
173 m_supportedExtensions.append(ext);
176 qDebug(lcPlatVk) <<
"Supported Vulkan instance extensions:" << m_supportedExtensions;
181 return m_supportedLayers;
186 return m_supportedExtensions;
191 return m_supportedApiVersion;
197 qWarning(
"initInstance: No Vulkan library available");
203 QVulkanInstance::Flags
flags = instance->flags();
204 m_enabledLayers = instance->layers();
205 m_enabledExtensions = instance->extensions();
208 VkApplicationInfo appInfo = {};
209 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
211 appInfo.pApplicationName = appName.
constData();
213 if (!apiVersion.
isNull()) {
214 appInfo.apiVersion = VK_MAKE_VERSION(apiVersion.
majorVersion(),
219 m_enabledExtensions.append(
"VK_KHR_surface");
220 if (!
flags.testFlag(QVulkanInstance::NoPortabilityDrivers))
221 m_enabledExtensions.append(
"VK_KHR_portability_enumeration");
222 if (!
flags.testFlag(QVulkanInstance::NoDebugOutputRedirect))
223 m_enabledExtensions.append(
"VK_EXT_debug_utils");
226 m_enabledExtensions.append(ext);
229 if (!envExts.isEmpty()) {
231 for (
auto ext : m_enabledExtensions)
232 envExtList.removeAll(ext);
233 m_enabledExtensions.append(envExtList);
237 if (!envLayers.isEmpty()) {
239 for (
auto ext : m_enabledLayers)
240 envLayerList.removeAll(ext);
241 m_enabledLayers.append(envLayerList);
246 for (
int i = 0;
i < m_enabledLayers.size(); ++
i) {
248 if (!m_supportedLayers.contains(layerName))
249 m_enabledLayers.removeAt(
i--);
251 qDebug(lcPlatVk) <<
"Enabling Vulkan instance layers:" << m_enabledLayers;
252 for (
int i = 0;
i < m_enabledExtensions.size(); ++
i) {
254 if (!m_supportedExtensions.contains(extName))
255 m_enabledExtensions.removeAt(
i--);
257 qDebug(lcPlatVk) <<
"Enabling Vulkan instance extensions:" << m_enabledExtensions;
259 VkInstanceCreateInfo instInfo = {};
260 instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
261 instInfo.pApplicationInfo = &appInfo;
262 if (!
flags.testFlag(QVulkanInstance::NoPortabilityDrivers)) {
267 instInfo.flags |= 0x00000001;
270 QList<const char *> layerNameVec;
271 for (
const QByteArray &
ba : std::as_const(m_enabledLayers))
273 if (!layerNameVec.isEmpty()) {
274 instInfo.enabledLayerCount = layerNameVec.size();
275 instInfo.ppEnabledLayerNames = layerNameVec.constData();
278 QList<const char *> extNameVec;
279 for (
const QByteArray &
ba : std::as_const(m_enabledExtensions))
281 if (!extNameVec.isEmpty()) {
282 instInfo.enabledExtensionCount = extNameVec.size();
283 instInfo.ppEnabledExtensionNames = extNameVec.constData();
286 m_errorCode = m_vkCreateInstance(&instInfo,
nullptr, &
m_vkInst);
287 if (m_errorCode != VK_SUCCESS || !
m_vkInst) {
288 qWarning(
"Failed to create Vulkan instance: %d", m_errorCode);
293 if (!m_vkDestroyInstance) {
294 qWarning(
"Failed to find vkDestroyInstance");
305 qWarning(
"Failed to find vkGetPhysicalDeviceSurfaceSupportKHR");
310 qWarning(
"Failed to find vkDestroySurfaceKHR");
312 if (!
flags.testFlag(QVulkanInstance::NoDebugOutputRedirect))
333 return m_enabledLayers;
338 return m_enabledExtensions;
346 const bool needsNullInstance = !strcmp(
name,
"vkEnumerateInstanceLayerProperties")
347 || !strcmp(
name,
"vkEnumerateInstanceExtensionProperties");
353 uint32_t queueFamilyIndex,
359 VkSurfaceKHR surface = QVulkanInstance::surfaceForWindow(
window);
360 VkBool32 supported =
false;
382#ifdef VK_EXT_debug_utils
383static VKAPI_ATTR VkBool32 VKAPI_CALL defaultDebugCallbackFunc(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
384 VkDebugUtilsMessageTypeFlagsEXT messageType,
385 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
391 for (QVulkanInstance::DebugFilter
filter : *self->debugFilters()) {
395 if (pCallbackData->objectCount > 0)
396 object = pCallbackData->pObjects[0].objectHandle;
397 if (
filter(0, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
object, 0,
398 pCallbackData->messageIdNumber,
"", pCallbackData->pMessage))
405 for (QVulkanInstance::DebugUtilsFilter
filter : *
self->debugUtilsFilters()) {
406 QVulkanInstance::DebugMessageSeverityFlags
severity;
407 if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT)
408 severity |= QVulkanInstance::VerboseSeverity;
409 if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT)
410 severity |= QVulkanInstance::InfoSeverity;
411 if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
412 severity |= QVulkanInstance::WarningSeverity;
413 if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
414 severity |= QVulkanInstance::ErrorSeverity;
415 QVulkanInstance::DebugMessageTypeFlags
type;
416 if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT)
417 type |= QVulkanInstance::GeneralMessage;
418 if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)
419 type |= QVulkanInstance::ValidationMessage;
420 if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
421 type |= QVulkanInstance::PerformanceMessage;
427 qDebug(
"vkDebug: %s", pCallbackData->pMessage);
433void QBasicPlatformVulkanInstance::setupDebugOutput()
435#ifdef VK_EXT_debug_utils
436 if (!m_enabledExtensions.contains(
"VK_EXT_debug_utils"))
439 PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT =
reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT
>(
442 m_vkDestroyDebugUtilsMessengerEXT =
reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT
>(
445 VkDebugUtilsMessengerCreateInfoEXT messengerInfo = {};
446 messengerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
447 messengerInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
448 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
449 messengerInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
450 | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
451 | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
452 messengerInfo.pfnUserCallback = defaultDebugCallbackFunc;
453 messengerInfo.pUserData =
this;
454 VkResult err = vkCreateDebugUtilsMessengerEXT(
m_vkInst, &messengerInfo,
nullptr, &m_debugMessenger);
455 if (err != VK_SUCCESS)
456 qWarning(
"Failed to create debug report callback: %d", err);
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
QString applicationName
the name of this application
\inmodule QtCore \reentrant
QString fileName
the file name of the library
QFunctionPointer resolve(const char *symbol)
Returns the address of the exported symbol symbol.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray toUtf8() const &
bool isNull() const noexcept
Returns true if there are zero numerical segments, otherwise returns false.
int minorVersion() const noexcept
Returns the minor version number, that is, the second segment.
int majorVersion() const noexcept
Returns the major version number, that is, the first segment.
int microVersion() const noexcept
Returns the micro version number, that is, the third segment.
The QVulkanInstance class represents a native Vulkan instance, enabling Vulkan rendering onto a QSurf...
Combined button and popup list for selecting options.
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
#define qPrintable(string)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
const QStringList filters({"Image files (*.png *.xpm *.jpg)", "Text files (*.txt)", "Any files (*)" })
[6]