How to determine highest supported Vulkan version on machine?

I have this problem that I want to write code that would run on every machine with Vulkan support, but I would need to know version of Vulkan that application will use. This is tied with fact that some extensions are promoted to core in later API versions, and for example in Vulkan 1.1 ‘VK_KHR_16bit_storage’ extension is promoted to core, but can be not listed in supported extensions and still associated feature can be supported. Another situation for which it would be useful is when runtime and drivers support different Vulkan versions. It can happen because Vulkan runtime can be installed separately from drivers and even is edge cases someone could change runtime library one that supports lower Vulkan version. In my opinion this would be problematic when ‘VkInstance’ is created for Vulkan 1.2 because that version was returrned from ‘vkEnumerateInstanceVersion’ and ‘VkPhysicalDevice’ supports and uses functionality from Vulkan 1.3. Is there a reliable way to check highest supported Vulkan version, or is it better to just create app for Vulkan 1.0 and maybe in the future add support for extensions and features?

I don’t understand; aren’t you writing the application that will use some version of Vulkan? So how do you not know which version of Vulkan you created?

Um, not really. If the SDK loader is 1.1, you can still get Vulkan 1.3 implementations. And vice-versa.

There is no problem there at all. The instance version and the Vulkan implementation versions are completely separate queries and concepts. Indeed, it is even wrong to say that the instance is “created for Vulkan 1.2”. The instance version is 1.2, but this has little bearing on the versions you can get for Vulkan implementations (ie: VkPhysicalDevice versions) through that instance.

Yes. It’s called vkGetPhysicalDeviceProperties. That’s the version which matters.

1 Like

@Alfonse_Reinheart You said that VkInstance API version doesn’t matter, so that means that all Vulkan functions have their implementation in GPU driver? And because of that only driver version matters that is obtained through vkGetPhysicalDeviceProperties. Sorry if this is stupid question, I just want to understand how Vulkan exactly works.

First, FYI: You shouldn’t mark an answer as a solution unless it has actually answered all your questions.

As to your questions, things work as follows.

On your computer is one or more pieces of hardware that can do “graphics” work. This hardware is registered with your operating system through drivers that allow the OS to talk to them. These drivers provide implementations of various graphics APIs for user-space applications as well.

But each of the drivers on a computer come from possibly different vendors. They could provide implementations of different versions of the Vulkan API. Also, they install their software in different places, so there needs to be some unified way of checking to see what Vulkan implementations are available.

While you could write all of the boilerplate code to do this, the Vulkan SDK already wrote this. That functionality (along with some other really useful stuff) is exposed to you through the Vulkan instance. Instances are optional; you could bypass them and talk to the drivers directly. But you really shouldn’t, especially since it would make debugging Vulkan applications a nightmare.

The instance is the interface between your application and all of the hardware that offers Vulkan implementations. This interface has a version and its own extensions, which represents ways of asking about the capabilities of hardware devices.

An actual implementation of Vulkan for a particular piece of hardware is represented by the VkDevice object. These have their own version largely independent of the implementation version.

@Alfonse_Reinheart Just last question. After my firts reply, I found something on reddit from kroOoze:

You do vkInstanceGetProcAddr on vkEnumerateInstanceVersion. If it returns NULL, it means 1.0, otherwise what vkEnumerateInstanceVersion returns is the instance version.
Then you vkCreateInstance with a version your app is written against, and stick with it.
Then you use VkInstance level stuff with that version.
Then you use VkPhysicalDevice level stuff with min(yourInstanceCreateVersion, physicalDeviceVersion).

Does this mean that no matter what version of Vulkan is supported by choosen VkPhysicalDevice, VkInstance can use functionality up to version that vkEnumerateInstanceVersion.

It might have been answered above but:

vkEnumerateInstanceVersion will give you the SDK version you have installed
vkGetPhysicalDeviceProperties ->VkPhysicalDeviceProperties.apiVersion is the highest supported version(by the driver) for the hardware/GPU you are running the Vulkan app on.

This last bit is important because I used vkEnumerateInstaceVersion to get the vulkan SDK version and pass that to the Instance Creation Info. All worked just fine until I decided to update the SDK when 1.3 came out. My hardware supported 1.3 but I haven’t updated my drivers and the layers were giving me errors.

So assuming 1.0 has wider support, then maybe start an Instance using a hardcoded 1.0 version check the device properties, and if it supports 1.3 or whatever create a new instance with that version?

There’s a three-way handshake between Instance version, Device version, and App version.

Instance version is what the vkEnumerateInstanceVersion says it is. If the command does not exist, that implies the version is 1.0.

The application version is declared with VkApplicationInfo::version. If the instance is 1.0, then it must also be 1.0 (or the vkCreateInstance will not allow you through). Otherwise it can be arbitrary version number (even higher than Instance version).

Then on, the application is allowed to use only min(Instance version, Application version) functionality of the VkInstance.

VkPhysicalDeviceProperties::apiVersion gives the Device version.

Then on, the application is allowed to use only min(Device version, Application version) functionality of the VkPhysicalDevice, VkDevice, VkQueue, and VkCommandBuffer.

The Runtime generally should come with the driver package, so it should always be greater or equal than any of the versions of the Devices, but Linuxes typically being made as piling manure until it is in a shape of an operating system, it might not always be so. It is also frequent Linuxes happily expose even non-conformant drivers, so one has to juggle chainsaws in some way and hope all will be well. Lower instance version should theoretically work, but will have trouble dispatching the VkPhysicalDevice commands of higer versions. In practice there might be other compatibility problems.

In theory higher Instance version should work just fine, unless Khronos has occasional brain-fart and removes support of old driver manifest versions or some such. And maintaining effective and complete compatibility in practice is always a pain. So ideal condition is if Instance version and Device version is the same. And there is little reason for it to be otherwise if there is only one (or set of identical) GPU on the system.

It should be noted that apiVersion is not something you ask for from Vulkan. It’s a value you give to Vulkan. It’s the highest version of Vulkan that your application expects to see.

Yea, it is the application’s version. You are the application when using Vulkan.