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);
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);
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);
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);
231 for (
auto ext : m_enabledExtensions)
232 envExtList.removeAll(
ext);
233 m_enabledExtensions.append(envExtList);
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))
263 instInfo.flags |= 0x00000001;
266 for (
const QByteArray &
ba : std::as_const(m_enabledLayers))
269 instInfo.enabledLayerCount = layerNameVec.
size();
270 instInfo.ppEnabledLayerNames = layerNameVec.
constData();
274 for (
const QByteArray &
ba : std::as_const(m_enabledExtensions))
277 instInfo.enabledExtensionCount = extNameVec.
size();
278 instInfo.ppEnabledExtensionNames = extNameVec.
constData();
281 m_errorCode = m_vkCreateInstance(&instInfo,
nullptr, &
m_vkInst);
282 if (m_errorCode != VK_SUCCESS || !
m_vkInst) {
283 qWarning(
"Failed to create Vulkan instance: %d", m_errorCode);
288 if (!m_vkDestroyInstance) {
289 qWarning(
"Failed to find vkDestroyInstance");
300 qWarning(
"Failed to find vkGetPhysicalDeviceSurfaceSupportKHR");
305 qWarning(
"Failed to find vkDestroySurfaceKHR");
307 if (!
flags.testFlag(QVulkanInstance::NoDebugOutputRedirect))
328 return m_enabledLayers;
333 return m_enabledExtensions;
341 const bool needsNullInstance = !strcmp(
name,
"vkEnumerateInstanceLayerProperties")
342 || !strcmp(
name,
"vkEnumerateInstanceExtensionProperties");
348 uint32_t queueFamilyIndex,
354 VkSurfaceKHR surface = QVulkanInstance::surfaceForWindow(
window);
355 VkBool32 supported =
false;
377#ifdef VK_EXT_debug_utils
378static VKAPI_ATTR VkBool32 VKAPI_CALL defaultDebugCallbackFunc(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
379 VkDebugUtilsMessageTypeFlagsEXT messageType,
380 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
386 for (QVulkanInstance::DebugFilter
filter : *self->debugFilters()) {
390 if (pCallbackData->objectCount > 0)
391 object = pCallbackData->pObjects[0].objectHandle;
392 if (
filter(0, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
object, 0,
393 pCallbackData->messageIdNumber,
"", pCallbackData->pMessage))
400 for (QVulkanInstance::DebugUtilsFilter
filter : *
self->debugUtilsFilters()) {
401 QVulkanInstance::DebugMessageSeverityFlags
severity;
402 if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT)
403 severity |= QVulkanInstance::VerboseSeverity;
404 if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT)
405 severity |= QVulkanInstance::InfoSeverity;
406 if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
407 severity |= QVulkanInstance::WarningSeverity;
408 if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
409 severity |= QVulkanInstance::ErrorSeverity;
410 QVulkanInstance::DebugMessageTypeFlags
type;
411 if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT)
412 type |= QVulkanInstance::GeneralMessage;
413 if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)
414 type |= QVulkanInstance::ValidationMessage;
415 if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
416 type |= QVulkanInstance::PerformanceMessage;
422 qDebug(
"vkDebug: %s", pCallbackData->pMessage);
428void QBasicPlatformVulkanInstance::setupDebugOutput()
430#ifdef VK_EXT_debug_utils
431 if (!m_enabledExtensions.contains(
"VK_EXT_debug_utils"))
434 PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT =
reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT
>(
437 m_vkDestroyDebugUtilsMessengerEXT =
reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT
>(
440 VkDebugUtilsMessengerCreateInfoEXT messengerInfo = {};
441 messengerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
442 messengerInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
443 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
444 messengerInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
445 | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
446 | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
447 messengerInfo.pfnUserCallback = defaultDebugCallbackFunc;
448 messengerInfo.pUserData =
this;
449 VkResult err = vkCreateDebugUtilsMessengerEXT(
m_vkInst, &messengerInfo,
nullptr, &m_debugMessenger);
450 if (err != VK_SUCCESS)
451 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.
QList< QByteArray > split(char sep) const
Splits the byte array into subarrays wherever sep occurs, and returns the list of those arrays.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
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.
qsizetype size() const noexcept
const_pointer constData() const noexcept
bool isEmpty() const noexcept
void append(parameter_type t)
\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]