47void QBasicPlatformVulkanInstance::loadVulkanLibrary(
const QString &defaultLibraryName,
int defaultLibraryVersion)
49 QVarLengthArray<std::pair<QString,
int>, 3> loadList;
54 if (qEnvironmentVariableIsSet(
"QT_VULKAN_LIB"))
55 loadList.append({ qEnvironmentVariable(
"QT_VULKAN_LIB"), -1 });
59 loadList.append({ defaultLibraryName, defaultLibraryVersion });
64 if (defaultLibraryVersion >= 0)
65 loadList.append({ defaultLibraryName, -1 });
68 for (
const auto &lib : loadList) {
69 m_vulkanLib.reset(
new QLibrary);
71 m_vulkanLib->setFileNameAndVersion(lib.first, lib.second);
73 m_vulkanLib->setFileName(lib.first);
74 if (m_vulkanLib->load()) {
81 qWarning(
"Failed to load %s: %s", qPrintable(m_vulkanLib->fileName()), qPrintable(m_vulkanLib->errorString()));
85 init(m_vulkanLib.get());
88void QBasicPlatformVulkanInstance::init(QLibrary *lib)
90 if (m_vkGetInstanceProcAddr)
93 qCDebug(lcPlatVk,
"Vulkan init (%s)", qPrintable(lib->fileName()));
102 m_vkGetInstanceProcAddr =
reinterpret_cast<PFN_vkGetInstanceProcAddr>(lib->resolve(
"vkGetInstanceProcAddr"));
103 if (!m_vkGetInstanceProcAddr) {
104 qWarning(
"Failed to find vkGetInstanceProcAddr");
108 m_vkCreateInstance =
reinterpret_cast<PFN_vkCreateInstance>(m_vkGetInstanceProcAddr(VK_NULL_HANDLE,
"vkCreateInstance"));
109 if (!m_vkCreateInstance) {
110 qWarning(
"Failed to find vkCreateInstance");
113 m_vkEnumerateInstanceLayerProperties =
reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
114 m_vkGetInstanceProcAddr(VK_NULL_HANDLE,
"vkEnumerateInstanceLayerProperties"));
115 if (!m_vkEnumerateInstanceLayerProperties) {
116 qWarning(
"Failed to find vkEnumerateInstanceLayerProperties");
119 m_vkEnumerateInstanceExtensionProperties =
reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
120 m_vkGetInstanceProcAddr(VK_NULL_HANDLE,
"vkEnumerateInstanceExtensionProperties"));
121 if (!m_vkEnumerateInstanceExtensionProperties) {
122 qWarning(
"Failed to find vkEnumerateInstanceExtensionProperties");
127 typedef VkResult (VKAPI_PTR *T_enumerateInstanceVersion)(uint32_t* pApiVersion);
129 T_enumerateInstanceVersion enumerateInstanceVersion =
reinterpret_cast<T_enumerateInstanceVersion>(
130 m_vkGetInstanceProcAddr(VK_NULL_HANDLE,
"vkEnumerateInstanceVersion"));
131 if (enumerateInstanceVersion) {
133 if (enumerateInstanceVersion(&ver) == VK_SUCCESS) {
134 m_supportedApiVersion = QVersionNumber(VK_VERSION_MAJOR(ver),
135 VK_VERSION_MINOR(ver),
136 VK_VERSION_PATCH(ver));
138 m_supportedApiVersion = QVersionNumber(1, 0, 0);
142 m_supportedApiVersion = QVersionNumber(1, 0, 0);
145 uint32_t layerCount = 0;
146 m_vkEnumerateInstanceLayerProperties(&layerCount,
nullptr);
148 QList<VkLayerProperties> layerProps(layerCount);
149 m_vkEnumerateInstanceLayerProperties(&layerCount, layerProps.data());
150 m_supportedLayers.reserve(layerCount);
151 for (
const VkLayerProperties &p : std::as_const(layerProps)) {
153 layer.name = p.layerName;
154 layer.version = p.implementationVersion;
155 layer.specVersion = QVersionNumber(VK_VERSION_MAJOR(p.specVersion),
156 VK_VERSION_MINOR(p.specVersion),
157 VK_VERSION_PATCH(p.specVersion));
158 layer.description = p.description;
159 m_supportedLayers.append(layer);
162 qCDebug(lcPlatVk) <<
"Supported Vulkan instance layers:" << m_supportedLayers;
164 uint32_t extCount = 0;
165 m_vkEnumerateInstanceExtensionProperties(
nullptr, &extCount,
nullptr);
167 QList<VkExtensionProperties> extProps(extCount);
168 m_vkEnumerateInstanceExtensionProperties(
nullptr, &extCount, extProps.data());
169 m_supportedExtensions.reserve(extCount);
170 for (
const VkExtensionProperties &p : std::as_const(extProps)) {
171 QVulkanExtension ext;
172 ext.name = p.extensionName;
173 ext.version = p.specVersion;
174 m_supportedExtensions.append(ext);
177 qCDebug(lcPlatVk) <<
"Supported Vulkan instance extensions:" << m_supportedExtensions;
195void QBasicPlatformVulkanInstance::initInstance(QVulkanInstance *instance,
const QByteArrayList &extraExts)
197 if (!m_vkGetInstanceProcAddr) {
198 qWarning(
"initInstance: No Vulkan library available");
202 m_vkInst = instance->vkInstance();
204 QVulkanInstance::Flags flags = instance->flags();
205 m_enabledLayers = instance->layers();
206 m_enabledExtensions = instance->extensions();
209 VkApplicationInfo appInfo = {};
210 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
211 QByteArray appName = QCoreApplication::applicationName().toUtf8();
212 appInfo.pApplicationName = appName.constData();
213 const QVersionNumber apiVersion = instance->apiVersion();
214 if (!apiVersion.isNull()) {
215 appInfo.apiVersion = VK_MAKE_VERSION(apiVersion.majorVersion(),
216 apiVersion.minorVersion(),
217 apiVersion.microVersion());
220 m_enabledExtensions.append(
"VK_KHR_surface");
221 if (!flags.testFlag(QVulkanInstance::NoPortabilityDrivers))
222 m_enabledExtensions.append(
"VK_KHR_portability_enumeration");
223 if (!flags.testFlag(QVulkanInstance::NoDebugOutputRedirect))
224 m_enabledExtensions.append(
"VK_EXT_debug_utils");
226 for (
const QByteArray &ext : extraExts)
227 m_enabledExtensions.append(ext);
229 QByteArray envExts = qgetenv(
"QT_VULKAN_INSTANCE_EXTENSIONS");
230 if (!envExts.isEmpty()) {
231 QByteArrayList envExtList = envExts.split(
';');
232 for (
auto ext : m_enabledExtensions)
233 envExtList.removeAll(ext);
234 m_enabledExtensions.append(envExtList);
237 QByteArray envLayers = qgetenv(
"QT_VULKAN_INSTANCE_LAYERS");
238 if (!envLayers.isEmpty()) {
239 QByteArrayList envLayerList = envLayers.split(
';');
240 for (
auto ext : m_enabledLayers)
241 envLayerList.removeAll(ext);
242 m_enabledLayers.append(envLayerList);
247 for (
int i = 0; i < m_enabledLayers.size(); ++i) {
248 const QByteArray &layerName(m_enabledLayers[i]);
249 if (!m_supportedLayers.contains(layerName))
250 m_enabledLayers.removeAt(i--);
252 qCDebug(lcPlatVk) <<
"Enabling Vulkan instance layers:" << m_enabledLayers;
253 for (
int i = 0; i < m_enabledExtensions.size(); ++i) {
254 const QByteArray &extName(m_enabledExtensions[i]);
255 if (!m_supportedExtensions.contains(extName))
256 m_enabledExtensions.removeAt(i--);
258 qCDebug(lcPlatVk) <<
"Enabling Vulkan instance extensions:" << m_enabledExtensions;
260 VkInstanceCreateInfo instInfo = {};
261 instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
262 instInfo.pApplicationInfo = &appInfo;
263 if (!flags.testFlag(QVulkanInstance::NoPortabilityDrivers)) {
267 if (m_supportedApiVersion >= QVersionNumber(1, 3, 216))
268 instInfo.flags |= 0x00000001;
271 QList<
const char *> layerNameVec;
272 for (
const QByteArray &ba : std::as_const(m_enabledLayers))
273 layerNameVec.append(ba.constData());
274 if (!layerNameVec.isEmpty()) {
275 instInfo.enabledLayerCount = layerNameVec.size();
276 instInfo.ppEnabledLayerNames = layerNameVec.constData();
279 QList<
const char *> extNameVec;
280 for (
const QByteArray &ba : std::as_const(m_enabledExtensions))
281 extNameVec.append(ba.constData());
282 if (!extNameVec.isEmpty()) {
283 instInfo.enabledExtensionCount = extNameVec.size();
284 instInfo.ppEnabledExtensionNames = extNameVec.constData();
287 m_errorCode = m_vkCreateInstance(&instInfo,
nullptr, &m_vkInst);
288 if (m_errorCode != VK_SUCCESS || !m_vkInst) {
289 qWarning(
"Failed to create Vulkan instance: %d", m_errorCode);
293 m_vkDestroyInstance =
reinterpret_cast<PFN_vkDestroyInstance>(m_vkGetInstanceProcAddr(m_vkInst,
"vkDestroyInstance"));
294 if (!m_vkDestroyInstance) {
295 qWarning(
"Failed to find vkDestroyInstance");
296 m_vkInst = VK_NULL_HANDLE;
303 m_getPhysDevSurfaceSupport =
reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(
304 m_vkGetInstanceProcAddr(m_vkInst,
"vkGetPhysicalDeviceSurfaceSupportKHR"));
305 if (!m_getPhysDevSurfaceSupport)
306 qWarning(
"Failed to find vkGetPhysicalDeviceSurfaceSupportKHR");
308 m_destroySurface =
reinterpret_cast<PFN_vkDestroySurfaceKHR>(
309 m_vkGetInstanceProcAddr(m_vkInst,
"vkDestroySurfaceKHR"));
310 if (!m_destroySurface)
311 qWarning(
"Failed to find vkDestroySurfaceKHR");
313 if (!flags.testFlag(QVulkanInstance::NoDebugOutputRedirect))