rhi: vulkan: Sanitize device extension handling
Instead of qputenv("QT_VULKAN_DEVICE_EXTENSIONS", "VK_KHR_get_memory_requirements2;VK_NV_ray_tracing"); one can now do params.deviceExtensions = { "VK_KHR_get_memory_requirements2", "VK_NV_ray_tracing" }; on the QRhiVulkanInitParams passed to QRhi::create(). The environment variable stays important for Qt Quick applications, which provide no configurability for the QRhi construction (yet). On the other hand, applications using QRhi directly can now also use the new approach to specify the list of device extensions to enable. In addition, take QVulkanInfoVector<QVulkanExtension> into use. There is no reason not to rely on the infrastructure provided by QVulkanInstance. This also implies showing an informative warning for unsupported extensions, instead of merely failing the device creation. (applications will likely not be able to recover of course, but at least the reason for failing is made obvious this way) Task-number: QTBUG-82435 Change-Id: Ib47fd1a10c02be5ceef2c973e61e896c34f92fa3 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
parent
5bbc9986f9
commit
bd2b77120e
@ -149,6 +149,10 @@ QT_BEGIN_NAMESPACE
|
||||
for other windows as well, as long as they all have their
|
||||
QWindow::surfaceType() set to QSurface::VulkanSurface.
|
||||
|
||||
To request additional extensions to be enabled on the Vulkan device, list them
|
||||
in deviceExtensions. This can be relevant when integrating with native Vulkan
|
||||
rendering code.
|
||||
|
||||
\section2 Working with existing Vulkan devices
|
||||
|
||||
When interoperating with another graphics engine, it may be necessary to
|
||||
@ -299,6 +303,7 @@ QRhiVulkan::QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *im
|
||||
{
|
||||
inst = params->inst;
|
||||
maybeWindow = params->window; // may be null
|
||||
requestedDeviceExtensions = params->deviceExtensions;
|
||||
|
||||
importedDevice = importDevice != nullptr;
|
||||
if (importedDevice) {
|
||||
@ -463,40 +468,59 @@ bool QRhiVulkan::create(QRhi::Flags flags)
|
||||
if (inst->layers().contains("VK_LAYER_LUNARG_standard_validation"))
|
||||
devLayers.append("VK_LAYER_LUNARG_standard_validation");
|
||||
|
||||
QVulkanInfoVector<QVulkanExtension> devExts;
|
||||
uint32_t devExtCount = 0;
|
||||
f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, nullptr);
|
||||
QVector<VkExtensionProperties> devExts(devExtCount);
|
||||
f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, devExts.data());
|
||||
if (devExtCount) {
|
||||
QVector<VkExtensionProperties> extProps(devExtCount);
|
||||
f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, extProps.data());
|
||||
for (const VkExtensionProperties &p : qAsConst(extProps))
|
||||
devExts.append({ p.extensionName, p.specVersion });
|
||||
}
|
||||
qCDebug(QRHI_LOG_INFO, "%d device extensions available", devExts.count());
|
||||
|
||||
QVector<const char *> requestedDevExts;
|
||||
requestedDevExts.append("VK_KHR_swapchain");
|
||||
|
||||
debugMarkersAvailable = false;
|
||||
if (devExts.contains(VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
|
||||
requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
|
||||
debugMarkersAvailable = true;
|
||||
}
|
||||
|
||||
vertexAttribDivisorAvailable = false;
|
||||
for (const VkExtensionProperties &ext : devExts) {
|
||||
if (!strcmp(ext.extensionName, VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
|
||||
requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
|
||||
debugMarkersAvailable = true;
|
||||
} else if (!strcmp(ext.extensionName, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
|
||||
if (inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"))) {
|
||||
requestedDevExts.append(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
|
||||
vertexAttribDivisorAvailable = true;
|
||||
}
|
||||
if (devExts.contains(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
|
||||
if (inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"))) {
|
||||
requestedDevExts.append(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
|
||||
vertexAttribDivisorAvailable = true;
|
||||
}
|
||||
}
|
||||
|
||||
QByteArrayList envExtList;
|
||||
if (qEnvironmentVariableIsSet("QT_VULKAN_DEVICE_EXTENSIONS")) {
|
||||
envExtList = qgetenv("QT_VULKAN_DEVICE_EXTENSIONS").split(';');
|
||||
for (auto ext : requestedDevExts)
|
||||
envExtList.removeAll(ext);
|
||||
for (const QByteArray &ext : envExtList) {
|
||||
if (!ext.isEmpty())
|
||||
for (const QByteArray &ext : requestedDeviceExtensions) {
|
||||
if (!ext.isEmpty()) {
|
||||
if (devExts.contains(ext))
|
||||
requestedDevExts.append(ext.constData());
|
||||
else
|
||||
qWarning("Device extension %s is not supported", ext.constData());
|
||||
}
|
||||
}
|
||||
|
||||
QByteArrayList envExtList = qgetenv("QT_VULKAN_DEVICE_EXTENSIONS").split(';');
|
||||
for (const QByteArray &ext : envExtList) {
|
||||
if (!ext.isEmpty() && !requestedDevExts.contains(ext)) {
|
||||
if (devExts.contains(ext))
|
||||
requestedDevExts.append(ext.constData());
|
||||
else
|
||||
qWarning("Device extension %s is not supported", ext.constData());
|
||||
}
|
||||
}
|
||||
|
||||
if (QRHI_LOG_INFO().isEnabled(QtDebugMsg)) {
|
||||
qCDebug(QRHI_LOG_INFO, "Enabling device extensions:");
|
||||
for (const char *ext : requestedDevExts)
|
||||
qCDebug(QRHI_LOG_INFO, " %s", ext);
|
||||
}
|
||||
|
||||
VkDeviceCreateInfo devInfo;
|
||||
memset(&devInfo, 0, sizeof(devInfo));
|
||||
devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
|
@ -57,6 +57,7 @@ struct Q_GUI_EXPORT QRhiVulkanInitParams : public QRhiInitParams
|
||||
{
|
||||
QVulkanInstance *inst = nullptr;
|
||||
QWindow *window = nullptr;
|
||||
QByteArrayList deviceExtensions;
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiVulkanNativeHandles : public QRhiNativeHandles
|
||||
|
@ -810,6 +810,7 @@ public:
|
||||
|
||||
QVulkanInstance *inst = nullptr;
|
||||
QWindow *maybeWindow = nullptr;
|
||||
QByteArrayList requestedDeviceExtensions;
|
||||
bool importedDevice = false;
|
||||
VkPhysicalDevice physDev = VK_NULL_HANDLE;
|
||||
VkDevice dev = VK_NULL_HANDLE;
|
||||
|
Loading…
Reference in New Issue
Block a user