diff options
author | Matthew Waters <matthew@centricular.com> | 2020-06-13 17:31:07 +1000 |
---|---|---|
committer | GStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org> | 2020-06-21 09:30:29 +0000 |
commit | aad7ed31e1a92fab3e0990c371b75c3e03be2458 (patch) | |
tree | f8efe84ef03dda92ffcab7f6a617dffa9b9d6bbf /gst-libs | |
parent | 595dd1c1499bb2eb7026aeab32c54dbfe45c0e5e (diff) | |
download | gstreamer-plugins-bad-aad7ed31e1a92fab3e0990c371b75c3e03be2458.tar.gz |
vulkan/instance: add vulkan API version selection and checking
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1341>
Diffstat (limited to 'gst-libs')
-rw-r--r-- | gst-libs/gst/vulkan/gstvkinstance.c | 250 | ||||
-rw-r--r-- | gst-libs/gst/vulkan/gstvkinstance.h | 10 |
2 files changed, 251 insertions, 9 deletions
diff --git a/gst-libs/gst/vulkan/gstvkinstance.c b/gst-libs/gst/vulkan/gstvkinstance.c index e4d01e379..ddd619b6a 100644 --- a/gst-libs/gst/vulkan/gstvkinstance.c +++ b/gst-libs/gst/vulkan/gstvkinstance.c @@ -29,11 +29,17 @@ /** * SECTION:vkinstance * @title: GstVulkanInstance - * @short_description: memory subclass for Vulkan image memory - * @see_also: #GstMemory, #GstAllocator + * @short_description: GStreamer Vulkan instance + * @see_also: #GstVulkanPhysicalDevice, #GstVulkanDevice * - * GstVulkanImageMemory is a #GstMemory subclass providing support for the - * mapping of Vulkan device memory. + * #GstVulkanInstance encapsulates the necessary information for the toplevel + * Vulkan instance object. + * + * If GStreamer is built with debugging support, the default Vulkan API chosen + * can be selected with the environment variable + * `GST_VULKAN_INSTANCE_API_VERSION=1.0`. Any subsequent setting of the + * requested Vulkan API version through the available properties will override + * the environment variable. */ #define APP_SHORT_NAME "GStreamer" @@ -50,6 +56,16 @@ enum LAST_SIGNAL }; +enum +{ + PROP_0, + PROP_REQUESTED_API_MAJOR_VERSION, + PROP_REQUESTED_API_MINOR_VERSION, +}; + +#define DEFAULT_REQUESTED_API_VERSION_MAJOR 0 +#define DEFAULT_REQUESTED_API_VERSION_MINOR 0 + static guint gst_vulkan_instance_signals[LAST_SIGNAL] = { 0 }; static void gst_vulkan_instance_finalize (GObject * object); @@ -57,6 +73,9 @@ static void gst_vulkan_instance_finalize (GObject * object); struct _GstVulkanInstancePrivate { gboolean opened; + guint requested_api_major; + guint requested_api_minor; + uint32_t supported_instance_api; }; static void @@ -93,17 +112,110 @@ gst_vulkan_instance_new (void) } static void +gst_vulkan_instance_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVulkanInstance *instance = GST_VULKAN_INSTANCE (object); + GstVulkanInstancePrivate *priv = GET_PRIV (instance); + + GST_OBJECT_LOCK (instance); + switch (prop_id) { + case PROP_REQUESTED_API_MAJOR_VERSION: + if (priv->opened) + g_warning ("Attempt to set the requested API version after the " + "instance has been opened"); + priv->requested_api_major = g_value_get_uint (value); + break; + case PROP_REQUESTED_API_MINOR_VERSION: + if (priv->opened) + g_warning ("Attempt to set the requested API version after the " + "instance has been opened"); + priv->requested_api_minor = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + GST_OBJECT_UNLOCK (instance); +} + +static void +gst_vulkan_instance_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstVulkanInstance *instance = GST_VULKAN_INSTANCE (object); + GstVulkanInstancePrivate *priv = GET_PRIV (instance); + + GST_OBJECT_LOCK (instance); + switch (prop_id) { + case PROP_REQUESTED_API_MAJOR_VERSION: + g_value_set_uint (value, priv->requested_api_major); + break; + case PROP_REQUESTED_API_MINOR_VERSION: + g_value_set_uint (value, priv->requested_api_minor); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + GST_OBJECT_UNLOCK (instance); +} + +static void gst_vulkan_instance_init (GstVulkanInstance * instance) { + GstVulkanInstancePrivate *priv = GET_PRIV (instance); + + priv->requested_api_major = DEFAULT_REQUESTED_API_VERSION_MAJOR; + priv->requested_api_minor = DEFAULT_REQUESTED_API_VERSION_MINOR; + +#if !defined (GST_DISABLE_DEBUG) + { + const gchar *api_override = g_getenv ("GST_VULKAN_INSTANCE_API_VERSION"); + if (api_override) { + gchar *end; + gint64 major, minor; + + major = g_ascii_strtoll (api_override, &end, 10); + if (end && end[0] == '.') { + minor = g_ascii_strtoll (&end[1], NULL, 10); + if (major > 0 && major < G_MAXINT64 && minor >= 0 && minor < G_MAXINT64) { + priv->requested_api_major = major; + priv->requested_api_minor = minor; + } + } + } + } +#endif } static void gst_vulkan_instance_class_init (GstVulkanInstanceClass * klass) { + GObjectClass *gobject_class = (GObjectClass *) klass; + gst_vulkan_memory_init_once (); gst_vulkan_image_memory_init_once (); gst_vulkan_buffer_memory_init_once (); + gobject_class->get_property = gst_vulkan_instance_get_property; + gobject_class->set_property = gst_vulkan_instance_set_property; + gobject_class->finalize = gst_vulkan_instance_finalize; + + g_object_class_install_property (gobject_class, + PROP_REQUESTED_API_MAJOR_VERSION, + g_param_spec_uint ("requested-api-major", "Requested API Major", + "Major version of the requested Vulkan API (0 = maximum supported)", + 0, G_MAXUINT, DEFAULT_REQUESTED_API_VERSION_MAJOR, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, + PROP_REQUESTED_API_MINOR_VERSION, + g_param_spec_uint ("requested-api-minor", "Requested API Minor", + "Minor version of the requested Vulkan API", + 0, G_MAXUINT, DEFAULT_REQUESTED_API_VERSION_MINOR, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** * GstVulkanInstance::create-device: * @object: the #GstVulkanDisplay @@ -118,8 +230,6 @@ gst_vulkan_instance_class_init (GstVulkanInstanceClass * klass) gst_vulkan_instance_signals[SIGNAL_CREATE_DEVICE] = g_signal_new ("create-device", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, GST_TYPE_VULKAN_DEVICE, 0); - - G_OBJECT_CLASS (klass)->finalize = gst_vulkan_instance_finalize; } static void @@ -181,6 +291,26 @@ _gst_vk_debug_callback (VkDebugReportFlagsEXT msgFlags, return FALSE; } +static void +gst_vulkan_get_supported_api_version_unlocked (GstVulkanInstance * instance) +{ + GstVulkanInstancePrivate *priv = GET_PRIV (instance); + PFN_vkEnumerateInstanceVersion gst_vkEnumerateInstanceVersion; + + if (priv->supported_instance_api) + return; + + gst_vkEnumerateInstanceVersion = + (PFN_vkEnumerateInstanceVersion) vkGetInstanceProcAddr (NULL, + "vkEnumerateInstanceVersion"); + + if (!gst_vkEnumerateInstanceVersion + || VK_SUCCESS != + gst_vkEnumerateInstanceVersion (&priv->supported_instance_api)) { + priv->supported_instance_api = VK_MAKE_VERSION (1, 0, 0); + } +} + /** * gst_vulkan_instance_open: * @instance: a #GstVulkanInstance @@ -200,6 +330,7 @@ gst_vulkan_instance_open (GstVulkanInstance * instance, GError ** error) uint32_t instance_extension_count = 0; uint32_t enabled_extension_count = 0; uint32_t instance_layer_count = 0; + uint32_t requested_instance_api; gboolean have_debug_extension = FALSE; VkResult err; @@ -213,6 +344,32 @@ gst_vulkan_instance_open (GstVulkanInstance * instance, GError ** error) return TRUE; } + gst_vulkan_get_supported_api_version_unlocked (instance); + if (priv->requested_api_major) { + requested_instance_api = + VK_MAKE_VERSION (priv->requested_api_major, priv->requested_api_minor, + 0); + GST_INFO_OBJECT (instance, "requesting Vulkan API %u.%u, max supported " + "%u.%u", priv->requested_api_major, priv->requested_api_minor, + VK_VERSION_MAJOR (priv->supported_instance_api), + VK_VERSION_MINOR (priv->supported_instance_api)); + } else { + requested_instance_api = priv->supported_instance_api; + GST_INFO_OBJECT (instance, "requesting maximum supported API %u.%u", + VK_VERSION_MAJOR (priv->supported_instance_api), + VK_VERSION_MINOR (priv->supported_instance_api)); + } + + if (requested_instance_api > priv->supported_instance_api) { + g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED, + "Requested API version (%u.%u) is larger than the maximum supported " + "version (%u.%u)", VK_VERSION_MAJOR (requested_instance_api), + VK_VERSION_MINOR (requested_instance_api), + VK_VERSION_MAJOR (priv->supported_instance_api), + VK_VERSION_MINOR (priv->supported_instance_api)); + goto error; + } + /* Look for validation layers */ err = vkEnumerateInstanceLayerProperties (&instance_layer_count, NULL); if (gst_vulkan_error_to_g_error (err, error, @@ -319,7 +476,7 @@ gst_vulkan_instance_open (GstVulkanInstance * instance, GError ** error) .applicationVersion = 0, .pEngineName = APP_SHORT_NAME, .engineVersion = 0, - .apiVersion = VK_API_VERSION_1_0 + .apiVersion = requested_instance_api, }; inst_info = (VkInstanceCreateInfo) { @@ -432,13 +589,17 @@ gpointer gst_vulkan_instance_get_proc_address (GstVulkanInstance * instance, const gchar * name) { + gpointer ret; + g_return_val_if_fail (GST_IS_VULKAN_INSTANCE (instance), NULL); g_return_val_if_fail (instance->instance != NULL, NULL); g_return_val_if_fail (name != NULL, NULL); - GST_TRACE_OBJECT (instance, "%s", name); + ret = vkGetInstanceProcAddr (instance->instance, name); - return vkGetInstanceProcAddr (instance->instance, name); + GST_TRACE_OBJECT (instance, "%s = %p", name, ret); + + return ret; } /** @@ -613,3 +774,74 @@ gst_vulkan_instance_run_context_query (GstElement * element, return FALSE; } + +/** + * gst_vulkan_instance_check_version: + * @instance: a #GstVulkanInstance + * @major: major version + * @minor: minor version + * @patch: patch version + * + * Check if the configured vulkan instance supports the specified version. + * Will not work prior to opening the instance with gst_vulkan_instance_open(). + * If a specific version is requested, the @patch level is ignored. + * + * Returns: whether @instance is at least the requested version. + * + * Since: 1.18 + */ +gboolean +gst_vulkan_instance_check_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 (priv->requested_api_major == 0 + && VK_MAKE_VERSION (major, minor, patch) <= priv->supported_instance_api) + || (priv->requested_api_major >= 0 && (major < priv->requested_api_major + || (major == priv->requested_api_major + && minor <= priv->requested_api_minor))); +} + +/** + * gst_vulkan_instance_get_version: + * @instance: a #GstVulkanInstance + * @major: major version + * @minor: minor version + * @patch: patch version + * + * Retrieve the vulkan instance configured 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 + * default) than a version check that is performed manually by retrieving the + * version with this function. + * + * Since: 1.18 + */ +void +gst_vulkan_instance_get_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 (!priv->supported_instance_api) + gst_vulkan_get_supported_api_version_unlocked (instance); + + if (major) + *major = VK_VERSION_MAJOR (priv->supported_instance_api); + if (minor) + *minor = VK_VERSION_MINOR (priv->supported_instance_api); + if (patch) + *patch = VK_VERSION_PATCH (priv->supported_instance_api); + GST_OBJECT_UNLOCK (instance); +} diff --git a/gst-libs/gst/vulkan/gstvkinstance.h b/gst-libs/gst/vulkan/gstvkinstance.h index 4330d5790..81c3806c7 100644 --- a/gst-libs/gst/vulkan/gstvkinstance.h +++ b/gst-libs/gst/vulkan/gstvkinstance.h @@ -82,6 +82,16 @@ gboolean gst_vulkan_instance_handle_context_query (GstElement * el GST_VULKAN_API gboolean gst_vulkan_instance_run_context_query (GstElement * element, GstVulkanInstance ** instance); +GST_VULKAN_API +gboolean gst_vulkan_instance_check_version (GstVulkanInstance * instance, + guint major, + guint minor, + guint patch); +GST_VULKAN_API +void gst_vulkan_instance_get_version (GstVulkanInstance * instance, + guint * major, + guint * minor, + guint * patch); G_END_DECLS |