vulkan: Add instance-level version getter
...as described in the Vulkan >= 1.1 spec. One can now call supportedApiVersion() (before create(), similarly to the other supported* functions) to determine the available Vulkan (instance-level) version. Fixes: QTBUG-90333 Change-Id: Ibe8482402b7f07e4abc48c88252ff0365e4e2faa Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
parent
9573441236
commit
7d378bd780
@ -135,6 +135,25 @@ void QBasicPlatformVulkanInstance::init(QLibrary *lib)
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not rely on non-1.0 header typedefs here.
|
||||
typedef VkResult (VKAPI_PTR *T_enumerateInstanceVersion)(uint32_t* pApiVersion);
|
||||
// Determine instance-level version as described in the Vulkan 1.2 spec.
|
||||
T_enumerateInstanceVersion enumerateInstanceVersion = reinterpret_cast<T_enumerateInstanceVersion>(
|
||||
m_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion"));
|
||||
if (enumerateInstanceVersion) {
|
||||
uint32_t ver = 0;
|
||||
if (enumerateInstanceVersion(&ver) == VK_SUCCESS) {
|
||||
m_supportedApiVersion = QVersionNumber(VK_VERSION_MAJOR(ver),
|
||||
VK_VERSION_MINOR(ver),
|
||||
VK_VERSION_PATCH(ver));
|
||||
} else {
|
||||
m_supportedApiVersion = QVersionNumber(1, 0, 0);
|
||||
}
|
||||
} else {
|
||||
// Vulkan 1.0
|
||||
m_supportedApiVersion = QVersionNumber(1, 0, 0);
|
||||
}
|
||||
|
||||
uint32_t layerCount = 0;
|
||||
m_vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
|
||||
if (layerCount) {
|
||||
@ -180,6 +199,11 @@ QVulkanInfoVector<QVulkanExtension> QBasicPlatformVulkanInstance::supportedExten
|
||||
return m_supportedExtensions;
|
||||
}
|
||||
|
||||
QVersionNumber QBasicPlatformVulkanInstance::supportedApiVersion() const
|
||||
{
|
||||
return m_supportedApiVersion;
|
||||
}
|
||||
|
||||
void QBasicPlatformVulkanInstance::initInstance(QVulkanInstance *instance, const QByteArrayList &extraExts)
|
||||
{
|
||||
if (!m_vkGetInstanceProcAddr) {
|
||||
|
@ -68,6 +68,7 @@ public:
|
||||
|
||||
QVulkanInfoVector<QVulkanLayer> supportedLayers() const override;
|
||||
QVulkanInfoVector<QVulkanExtension> supportedExtensions() const override;
|
||||
QVersionNumber supportedApiVersion() const override;
|
||||
bool isValid() const override;
|
||||
VkResult errorCode() const override;
|
||||
VkInstance vkInstance() const override;
|
||||
@ -99,6 +100,7 @@ private:
|
||||
VkResult m_errorCode;
|
||||
QVulkanInfoVector<QVulkanLayer> m_supportedLayers;
|
||||
QVulkanInfoVector<QVulkanExtension> m_supportedExtensions;
|
||||
QVersionNumber m_supportedApiVersion;
|
||||
QByteArrayList m_enabledLayers;
|
||||
QByteArrayList m_enabledExtensions;
|
||||
|
||||
|
@ -69,6 +69,7 @@ public:
|
||||
|
||||
virtual QVulkanInfoVector<QVulkanLayer> supportedLayers() const = 0;
|
||||
virtual QVulkanInfoVector<QVulkanExtension> supportedExtensions() const = 0;
|
||||
virtual QVersionNumber supportedApiVersion() const = 0;
|
||||
virtual void createOrAdoptInstance() = 0;
|
||||
virtual bool isValid() const = 0;
|
||||
virtual VkResult errorCode() const = 0;
|
||||
|
@ -447,6 +447,28 @@ QVulkanInfoVector<QVulkanExtension> QVulkanInstance::supportedExtensions()
|
||||
return d_ptr->ensureVulkan() ? d_ptr->platformInst->supportedExtensions() : QVulkanInfoVector<QVulkanExtension>();
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the version of instance-level functionality supported by the Vulkan
|
||||
implementation.
|
||||
|
||||
In practice this is either the value returned from
|
||||
vkEnumerateInstanceVersion, if that function is available (with Vulkan 1.1
|
||||
and newer), or 1.0.
|
||||
|
||||
Applications that want to branch in their Vulkan feature and API usage
|
||||
based on what Vulkan version is available at run time, can use this function
|
||||
to determine what version to pass in to setApiVersion() before calling
|
||||
create().
|
||||
|
||||
\note This function can be called before create().
|
||||
|
||||
\sa setApiVersion()
|
||||
*/
|
||||
QVersionNumber QVulkanInstance::supportedApiVersion()
|
||||
{
|
||||
return d_ptr->ensureVulkan() ? d_ptr->platformInst->supportedApiVersion() : QVersionNumber();
|
||||
}
|
||||
|
||||
/*!
|
||||
Makes QVulkanInstance adopt an existing VkInstance handle instead of
|
||||
creating a new one.
|
||||
@ -524,10 +546,9 @@ void QVulkanInstance::setExtensions(const QByteArrayList &extensions)
|
||||
}
|
||||
|
||||
/*!
|
||||
Specifies the Vulkan API against which the application expects to run.
|
||||
Specifies the highest Vulkan API version the application is designed to use.
|
||||
|
||||
By default no \a vulkanVersion is specified, and so no version check is performed
|
||||
during Vulkan instance creation.
|
||||
By default \a vulkanVersion is 0, which maps to Vulkan 1.0.
|
||||
|
||||
\note This function can only be called before create() and has no effect if
|
||||
called afterwards.
|
||||
@ -538,6 +559,13 @@ void QVulkanInstance::setExtensions(const QByteArrayList &extensions)
|
||||
as was mandated by the specification. Starting with Vulkan 1.1, the
|
||||
specification disallows this, the driver must accept any version without
|
||||
failing the instance creation.
|
||||
|
||||
Application developers are advised to familiarize themselves with the \c
|
||||
apiVersion notes in
|
||||
\l{https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkApplicationInfo.html}{the
|
||||
Vulkan specification}.
|
||||
|
||||
\sa supportedApiVersion()
|
||||
*/
|
||||
void QVulkanInstance::setApiVersion(const QVersionNumber &vulkanVersion)
|
||||
{
|
||||
|
@ -176,6 +176,7 @@ public:
|
||||
|
||||
QVulkanInfoVector<QVulkanLayer> supportedLayers();
|
||||
QVulkanInfoVector<QVulkanExtension> supportedExtensions();
|
||||
QVersionNumber supportedApiVersion();
|
||||
|
||||
void setVkInstance(VkInstance existingVkInstance);
|
||||
|
||||
|
@ -86,8 +86,8 @@ void tst_QVulkan::vulkanInstance()
|
||||
|
||||
void tst_QVulkan::vulkanCheckSupported()
|
||||
{
|
||||
// Test the early calls to supportedLayers/extensions that need the library
|
||||
// and some basics, but do not initialize the instance.
|
||||
// Test the early calls to supportedLayers/extensions/apiVersion that need
|
||||
// the library and some basics, but do not initialize the instance.
|
||||
QVulkanInstance inst;
|
||||
QVERIFY(!inst.isValid());
|
||||
|
||||
@ -103,6 +103,9 @@ void tst_QVulkan::vulkanCheckSupported()
|
||||
QVERIFY(!ve.isEmpty());
|
||||
QVERIFY(ve == inst.supportedExtensions());
|
||||
}
|
||||
|
||||
qDebug() << inst.supportedApiVersion();
|
||||
QVERIFY(inst.supportedApiVersion().majorVersion() >= 1);
|
||||
}
|
||||
|
||||
void tst_QVulkan::vulkanPlainWindow()
|
||||
@ -162,6 +165,15 @@ void tst_QVulkan::vulkanVersionRequest()
|
||||
// succeed for any bogus api version).
|
||||
if (!result)
|
||||
QCOMPARE(inst.errorCode(), VK_ERROR_INCOMPATIBLE_DRIVER);
|
||||
|
||||
inst.destroy();
|
||||
|
||||
// Verify that specifying the version returned from supportedApiVersion
|
||||
// (either 1.0.0 or what vkEnumerateInstanceVersion returns in Vulkan 1.1+)
|
||||
// leads to successful instance creation.
|
||||
inst.setApiVersion(inst.supportedApiVersion());
|
||||
result = inst.create();
|
||||
QVERIFY(result);
|
||||
}
|
||||
|
||||
static void waitForUnexposed(QWindow *w)
|
||||
|
Loading…
x
Reference in New Issue
Block a user