vulkan: fix device related API version checks

The API version exposed by a particular device can be completely different from
what is exported by the parent instance.  Since Vulkan 1.1 it is also possible
to use newer device API than supported by the instance API version (with the
appropriate version checks).

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8554>
This commit is contained in:
Matthew Waters 2025-02-25 20:09:48 +11:00 committed by GStreamer Marge Bot
parent 72860a20bf
commit 51dda24a88
5 changed files with 89 additions and 13 deletions

View File

@ -1015,7 +1015,8 @@ gst_vulkan_decoder_update_ycbcr_sampler (GstVulkanDecoder * self,
device = self->queue->device;
if (!gst_vulkan_instance_check_version (device->instance, 1, 2, 0)) {
if (!gst_vulkan_physical_device_check_api_version (device->physical_device, 1,
2, 0)) {
g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED,
"Sampler Ycbcr conversion not available in API");
return FALSE;

View File

@ -77,6 +77,7 @@ struct _GstVulkanInstancePrivate
guint requested_api_major;
guint requested_api_minor;
uint32_t supported_instance_api;
uint32_t configured_instance_api;
guint n_available_layers;
VkLayerProperties *available_layers;
@ -983,6 +984,8 @@ gst_vulkan_instance_open (GstVulkanInstance * instance, GError ** error)
}
}
priv->configured_instance_api = requested_instance_api;
err =
vkEnumeratePhysicalDevices (instance->instance,
&instance->n_physical_devices, NULL);
@ -1334,7 +1337,7 @@ gst_vulkan_instance_check_version (GstVulkanInstance * instance,
* @minor: (out): minor version
* @patch: (out): patch version
*
* Retrieve the vulkan instance configured version. Only returns the supported
* Retrieve the vulkan instance supported version. Only returns the supported
* API version by the instance without taking into account the requested API
* version. This means gst_vulkan_instance_check_version() will return
* different values if a specific version has been requested (which is the
@ -1365,3 +1368,65 @@ gst_vulkan_instance_get_version (GstVulkanInstance * instance,
*patch = VK_VERSION_PATCH (priv->supported_instance_api);
GST_OBJECT_UNLOCK (instance);
}
/**
* gst_vulkan_instance_get_api_version:
* @instance: a #GstVulkanInstance
* @major: (out): major version
* @minor: (out): minor version
* @patch: (out): patch version
*
* Returns the vulkan API version configured when constructing the
* #GstVulkanInstance. This value can be any valid Vulkan API version and may
* not match gst_vulkan_instance_get_version() in any way. This version is the
* maximum allowed vulkan API to be used in any capacity.
*
* This will not return valid values until gst_vulkan_instance_open() has been
* called.
*
* Since: 1.26
*/
void
gst_vulkan_instance_get_api_version (GstVulkanInstance * instance,
guint * major, guint * minor, guint * patch)
{
GstVulkanInstancePrivate *priv;
g_return_if_fail (GST_IS_VULKAN_INSTANCE (instance));
priv = GET_PRIV (instance);
GST_OBJECT_LOCK (instance);
if (major)
*major = VK_VERSION_MAJOR (priv->configured_instance_api);
if (minor)
*minor = VK_VERSION_MINOR (priv->configured_instance_api);
if (patch)
*patch = VK_VERSION_PATCH (priv->configured_instance_api);
GST_OBJECT_UNLOCK (instance);
}
/**
* gst_vulkan_instance_check_api_version:
* @instance: a #GstVulkanInstance
* @major: the API major version to check
* @minor: the API minor version to check
* @patch: the API patch version to check
*
* Returns: whether the #GstVulkanInstance supports the version specified
* by @major, @minor and @patch.
*
* Since: 1.26
*/
gboolean
gst_vulkan_instance_check_api_version (GstVulkanInstance * instance,
guint major, guint minor, guint patch)
{
GstVulkanInstancePrivate *priv;
g_return_val_if_fail (GST_IS_VULKAN_INSTANCE (instance), FALSE);
priv = GET_PRIV (instance);
return VK_MAKE_VERSION (major, minor, patch) <= priv->configured_instance_api;
}

View File

@ -148,6 +148,16 @@ gboolean gst_vulkan_instance_enable_layer (GstVulkanInstan
GST_VULKAN_API
gboolean gst_vulkan_instance_is_layer_enabled (GstVulkanInstance * instance,
const gchar * name);
GST_VULKAN_API
void gst_vulkan_instance_get_api_version (GstVulkanInstance * instance,
guint * major,
guint * minor,
guint * patch);
GST_VULKAN_API
gboolean gst_vulkan_instance_check_api_version (GstVulkanInstance * instance,
guint major,
guint minor,
guint patch);
G_END_DECLS

View File

@ -504,7 +504,7 @@ dump_features (GstVulkanPhysicalDevice * device, GError ** error)
GstVulkanPhysicalDevicePrivate *priv = GET_PRIV (device);
VkBaseOutStructure *iter;
if (gst_vulkan_instance_check_version (device->instance, 1, 2, 0)) {
if (gst_vulkan_physical_device_check_api_version (device, 1, 2, 0)) {
for (iter = (VkBaseOutStructure *) & priv->features10; iter;
iter = iter->pNext) {
if (iter->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2)
@ -517,12 +517,12 @@ dump_features (GstVulkanPhysicalDevice * device, GError ** error)
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES)
dump_features12 (device, (VkPhysicalDeviceVulkan12Features *) iter);
#if defined (VK_API_VERSION_1_3)
else if (gst_vulkan_instance_check_version (device->instance, 1, 3, 0)
else if (gst_vulkan_physical_device_check_api_version (device, 1, 3, 0)
&& iter->sType ==
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES)
dump_features13 (device, (VkPhysicalDeviceVulkan13Features *) iter);
#if defined(VK_KHR_video_maintenance1)
else if (gst_vulkan_instance_check_version (device->instance, 1, 3, 283)
else if (gst_vulkan_physical_device_check_api_version (device, 1, 3, 283)
&& iter->sType ==
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR)
dump_videomaintenance1 (device,
@ -909,7 +909,7 @@ physical_device_info (GstVulkanPhysicalDevice * device, GError ** error)
return FALSE;
#if defined (VK_API_VERSION_1_2)
if (gst_vulkan_instance_check_version (device->instance, 1, 2, 0)) {
if (gst_vulkan_physical_device_check_api_version (device, 1, 2, 0)) {
for (iter = (VkBaseOutStructure *) & priv->properties10; iter;
iter = iter->pNext) {
if (iter->sType ==
@ -919,7 +919,7 @@ physical_device_info (GstVulkanPhysicalDevice * device, GError ** error)
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES)
dump_properties12 (device, (VkPhysicalDeviceVulkan12Properties *) iter);
#if defined (VK_API_VERSION_1_3)
else if (gst_vulkan_instance_check_version (device->instance, 1, 3, 0)
else if (gst_vulkan_physical_device_check_api_version (device, 1, 3, 0)
&& iter->sType ==
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES)
dump_properties13 (device, (VkPhysicalDeviceVulkan13Properties *) iter);
@ -992,7 +992,7 @@ gst_vulkan_physical_device_fill_info (GstVulkanPhysicalDevice * device,
vkGetPhysicalDeviceProperties (device->device, &device->properties);
#if defined (VK_API_VERSION_1_2)
if (gst_vulkan_instance_check_version (device->instance, 1, 2, 0)) {
if (gst_vulkan_physical_device_check_api_version (device, 1, 2, 0)) {
PFN_vkGetPhysicalDeviceProperties2 get_props2;
PFN_vkGetPhysicalDeviceMemoryProperties2 get_mem_props2;
PFN_vkGetPhysicalDeviceFeatures2 get_features2;
@ -1313,8 +1313,7 @@ gboolean
gst_vulkan_physical_device_check_api_version (GstVulkanPhysicalDevice * device,
guint major, guint minor, guint patch)
{
/* Since Vulkan 1.1 it is possible to have different supported API versions
* between an instance and a device */
return VK_MAKE_VERSION (major, minor, patch) <= device->properties.apiVersion
&& (gst_vulkan_instance_check_version (device->instance, 1, 1, 0) || (major == 1 && minor == 0));
&& gst_vulkan_instance_check_api_version (device->instance, major, minor,
patch);
}

View File

@ -62,8 +62,9 @@ GST_START_TEST (test_physical_device_version)
gst_vulkan_physical_device_get_api_version (phys, &major, &minor, NULL);
if (major > 1 || minor >= 0)
fail_unless (gst_vulkan_physical_device_check_api_version (phys, major, minor, 0));
if (major > 0)
fail_unless (gst_vulkan_physical_device_check_api_version (phys, major,
minor, 0));
if (minor > 0)
fail_unless (gst_vulkan_physical_device_check_api_version (phys, major,