When we create a Vulkan-enabled application, it can be executed on many different devices. It may be a desktop computer, a notebook, or a mobile phone. Each such device may have a different configuration, and may contain different graphics hardware that provide different performance, or, more importantly, different capabilities. A given computer may have more than one graphics card installed. So, in order to find a device that suits our needs, and is able to perform operations we want to implement in our code, we should check not only how many devices there are, but also, to be able to properly choose one of them, we need to check what the capabilities of each device are.
Getting features and properties of a physical device
How to do it...
- Prepare the handle of the physical device returned by the vkEnumeratePhysicalDevices() function. Store it in a variable of type VkPhysicalDevice named physical_device.
- Create a variable of type VkPhysicalDeviceFeatures named device_features.
- Create a second variable of type VkPhysicalDeviceProperties named device_properties.
- To get the list of features supported by a given device ,call vkGetPhysicalDeviceFeatures( physical_device, &device_features ). Set the handle of the physical device returned by the
vkEnumeratePhysicalDevices() function for the first parameter. The second parameter must point to the device_features variable.
- To acquire the properties of a given physical device call the vkGetPhysicalDeviceProperties( physical_device, &device_properties ) function. Provide the handle of the physical device in the first argument. This handle must have been returned by the vkEnumeratePhysicalDevices() function. The second parameter must be a pointer to a device_properties variable.
How it works...
Here you can find an implementation of the preceding recipe:
vkGetPhysicalDeviceFeatures( physical_device, &device_features ); vkGetPhysicalDeviceProperties( physical_device, &device_properties );
This code, while short and simple, gives us much information about the graphics hardware on which we can perform operations using the Vulkan API.
The VkPhysicalDeviceProperties structure contains general information about a given physical device. Through it, we can check the name of the device, the version of a driver, and a supported version of a Vulkan API. We can also check the type of a device: Whether it is an integrated device (built into a main processor) or a discrete (dedicated) graphics card, or maybe even a CPU itself. We can also read the limitations (limits) of a given hardware, for example, how big images (textures) can be created on it, how many buffers can be used in shaders, or we can check the upper limit of vertex attributes used during drawing operations.
The VkPhysicalDeviceFeatures structure lists additional features that may be supported by the given hardware, but are not required by the core Vulkan specification. Features include items such as geometry and tessellation shaders, depth clamp and bias, multiple viewports, or wide lines. You may wonder why geometry and tessellation shaders are on the list. Graphics hardware has supported these features for many years now. However, don't forget that the Vulkan API is portable and can be supported on many different hardware platforms, not only high-end PCs, but also mobile phones or even dedicated, portable devices, which should be as power efficient as possible. That's why these performance-hungry features are not in the core specification. This allows for some driver flexibility and, more importantly, power efficiency and lower memory consumption.
There is one additional thing you should know about the physical device features. Like extensions, they are not enabled by default and can't be used just like that. They must be implicitly enabled during the logical device creation. We can't request all features during this operation, because if there is any feature that is not supported, the logical device creation process will fail. If we are interested in a specific feature, we need to check if it is available and specify it during the creation of a logical device. If the feature is not supported, we can't use such a feature on this device and we need to look for another device that supports it.
If we want to enable all features supported by a given physical device, we just need to query for the available features and provide the acquired data during logical device creation.
See also
The following recipes in this chapter:
- Creating a logical device
- Creating a logical device with geometry shaders, graphics, and compute queues