46void QBasicPlatformVulkanInstance::loadVulkanLibrary(
const QString &defaultLibraryName,
int defaultLibraryVersion)
48 QVarLengthArray<std::pair<QString,
int>, 3> loadList;
53 if (qEnvironmentVariableIsSet(
"QT_VULKAN_LIB"))
54 loadList.append({ qEnvironmentVariable(
"QT_VULKAN_LIB"), -1 });
58 loadList.append({ defaultLibraryName, defaultLibraryVersion });
63 if (defaultLibraryVersion >= 0)
64 loadList.append({ defaultLibraryName, -1 });
67 for (
const auto &lib : loadList) {
68 m_vulkanLib.reset(
new QLibrary);
70 m_vulkanLib->setFileNameAndVersion(lib.first, lib.second);
72 m_vulkanLib->setFileName(lib.first);
73 if (m_vulkanLib->load()) {
80 qWarning(
"Failed to load %s: %s", qPrintable(m_vulkanLib->fileName()), qPrintable(m_vulkanLib->errorString()));
84 init(m_vulkanLib.get());
87void QBasicPlatformVulkanInstance::init(QLibrary *lib)
89 if (m_vkGetInstanceProcAddr)
92 qCDebug(lcPlatVk,
"Vulkan init (%s)", qPrintable(lib->fileName()));
101 m_vkGetInstanceProcAddr =
reinterpret_cast<PFN_vkGetInstanceProcAddr>(lib->resolve(
"vkGetInstanceProcAddr"));
102 if (!m_vkGetInstanceProcAddr) {
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>(
113 m_vkGetInstanceProcAddr(VK_NULL_HANDLE,
"vkEnumerateInstanceLayerProperties"));
114 if (!m_vkEnumerateInstanceLayerProperties) {
115 qWarning(
"Failed to find vkEnumerateInstanceLayerProperties");
118 m_vkEnumerateInstanceExtensionProperties =
reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
119 m_vkGetInstanceProcAddr(VK_NULL_HANDLE,
"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>(
129 m_vkGetInstanceProcAddr(VK_NULL_HANDLE,
"vkEnumerateInstanceVersion"));
130 if (enumerateInstanceVersion) {
132 if (enumerateInstanceVersion(&ver) == VK_SUCCESS) {
133 m_supportedApiVersion = QVersionNumber(VK_VERSION_MAJOR(ver),
134 VK_VERSION_MINOR(ver),
135 VK_VERSION_PATCH(ver));
137 m_supportedApiVersion = QVersionNumber(1, 0, 0);
141 m_supportedApiVersion = QVersionNumber(1, 0, 0);
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)) {
152 layer.name = p.layerName;
153 layer.version = p.implementationVersion;
154 layer.specVersion = QVersionNumber(VK_VERSION_MAJOR(p.specVersion),
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)) {
170 QVulkanExtension ext;
171 ext.name = p.extensionName;
172 ext.version = p.specVersion;
173 m_supportedExtensions.append(ext);
176 qCDebug(lcPlatVk) <<
"Supported Vulkan instance extensions:" << m_supportedExtensions;
194void QBasicPlatformVulkanInstance::initInstance(QVulkanInstance *instance,
const QByteArrayList &extraExts)
196 if (!m_vkGetInstanceProcAddr) {
197 qWarning(
"initInstance: No Vulkan library available");
201 m_vkInst = instance->vkInstance();
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;
210 QByteArray appName = QCoreApplication::applicationName().toUtf8();
211 appInfo.pApplicationName = appName.constData();
212 const QVersionNumber apiVersion = instance->apiVersion();
213 if (!apiVersion.isNull()) {
214 appInfo.apiVersion = VK_MAKE_VERSION(apiVersion.majorVersion(),
215 apiVersion.minorVersion(),
216 apiVersion.microVersion());
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");
225 for (
const QByteArray &ext : extraExts)
226 m_enabledExtensions.append(ext);
228 QByteArray envExts = qgetenv(
"QT_VULKAN_INSTANCE_EXTENSIONS");
229 if (!envExts.isEmpty()) {
230 QByteArrayList envExtList = envExts.split(
';');
231 for (
auto ext : m_enabledExtensions)
232 envExtList.removeAll(ext);
233 m_enabledExtensions.append(envExtList);
236 QByteArray envLayers = qgetenv(
"QT_VULKAN_INSTANCE_LAYERS");
237 if (!envLayers.isEmpty()) {
238 QByteArrayList envLayerList = envLayers.split(
';');
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) {
247 const QByteArray &layerName(m_enabledLayers[i]);
248 if (!m_supportedLayers.contains(layerName))
249 m_enabledLayers.removeAt(i--);
251 qCDebug(lcPlatVk) <<
"Enabling Vulkan instance layers:" << m_enabledLayers;
252 for (
int i = 0; i < m_enabledExtensions.size(); ++i) {
253 const QByteArray &extName(m_enabledExtensions[i]);
254 if (!m_supportedExtensions.contains(extName))
255 m_enabledExtensions.removeAt(i--);
257 qCDebug(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)) {
266 if (m_supportedApiVersion >= QVersionNumber(1, 3, 216))
267 instInfo.flags |= 0x00000001;
270 QList<
const char *> layerNameVec;
271 for (
const QByteArray &ba : std::as_const(m_enabledLayers))
272 layerNameVec.append(ba.constData());
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))
280 extNameVec.append(ba.constData());
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);
292 m_vkDestroyInstance =
reinterpret_cast<PFN_vkDestroyInstance>(m_vkGetInstanceProcAddr(m_vkInst,
"vkDestroyInstance"));
293 if (!m_vkDestroyInstance) {
294 qWarning(
"Failed to find vkDestroyInstance");
295 m_vkInst = VK_NULL_HANDLE;
302 m_getPhysDevSurfaceSupport =
reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(
303 m_vkGetInstanceProcAddr(m_vkInst,
"vkGetPhysicalDeviceSurfaceSupportKHR"));
304 if (!m_getPhysDevSurfaceSupport)
305 qWarning(
"Failed to find vkGetPhysicalDeviceSurfaceSupportKHR");
307 m_destroySurface =
reinterpret_cast<PFN_vkDestroySurfaceKHR>(
308 m_vkGetInstanceProcAddr(m_vkInst,
"vkDestroySurfaceKHR"));
309 if (!m_destroySurface)
310 qWarning(
"Failed to find vkDestroySurfaceKHR");
312 if (!flags.testFlag(QVulkanInstance::NoDebugOutputRedirect))