From 16a3a04405a052d77a79e9f702b9598ecdd33b9a Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 19 Oct 2023 13:34:40 +0200 Subject: [PATCH] vulkan: Add support for enumerating dmabuf formats This code does not add a downloader, so we do not claim support for all the new formats. It just queries the formats. But this can be used to import dmabufs directly into the Vulkaan renderer. --- gdk/gdkdisplay.c | 13 ++++++- gdk/gdkdisplayprivate.h | 1 + gdk/gdkdmabuf.c | 13 +++++++ gdk/gdkdmabufprivate.h | 3 ++ gdk/gdkvulkancontext.c | 69 +++++++++++++++++++++++++++++++++++ gdk/gdkvulkancontextprivate.h | 5 +++ 6 files changed, 103 insertions(+), 1 deletion(-) diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c index 9add64c62d..a139d6a122 100644 --- a/gdk/gdkdisplay.c +++ b/gdk/gdkdisplay.c @@ -40,7 +40,7 @@ #include "gdkglcontextprivate.h" #include "gdkmonitorprivate.h" #include "gdkrectangle.h" -#include "gdkvulkancontext.h" +#include "gdkvulkancontextprivate.h" #ifdef HAVE_EGL #include @@ -416,6 +416,13 @@ gdk_display_dispose (GObject *object) g_clear_pointer (&display->egl_dmabuf_formats, gdk_dmabuf_formats_unref); g_clear_pointer (&display->egl_external_formats, gdk_dmabuf_formats_unref); +#ifdef GDK_RENDERING_VULKAN + if (display->vk_dmabuf_formats) + { + gdk_display_unref_vulkan (display); + g_assert (display->vk_dmabuf_formats == NULL); + } +#endif g_clear_object (&priv->gl_context); #ifdef HAVE_EGL @@ -1939,6 +1946,10 @@ gdk_display_init_dmabuf (GdkDisplay *self) #ifdef HAVE_DMABUF if (!GDK_DISPLAY_DEBUG_CHECK (self, DMABUF_DISABLE)) { +#ifdef GDK_RENDERING_VULKAN + gdk_display_add_dmabuf_downloader (self, gdk_vulkan_get_dmabuf_downloader (self, builder)); +#endif + #ifdef HAVE_EGL gdk_display_add_dmabuf_downloader (self, gdk_dmabuf_get_egl_downloader (self, builder)); #endif diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h index 085a1226c1..67d8f4abbe 100644 --- a/gdk/gdkdisplayprivate.h +++ b/gdk/gdkdisplayprivate.h @@ -112,6 +112,7 @@ struct _GdkDisplay char *vk_pipeline_cache_etag; guint vk_save_pipeline_cache_source; GHashTable *vk_shader_modules; + GdkDmabufFormats *vk_dmabuf_formats; GdkVulkanFeatures vulkan_features; guint vulkan_refcount; diff --git a/gdk/gdkdmabuf.c b/gdk/gdkdmabuf.c index b946ebe6fe..d1b8cf2d83 100644 --- a/gdk/gdkdmabuf.c +++ b/gdk/gdkdmabuf.c @@ -1919,6 +1919,19 @@ gdk_dmabuf_get_memory_format (guint32 fourcc, } #ifdef GDK_RENDERING_VULKAN +gboolean +gdk_dmabuf_vk_get_nth (gsize n, + guint32 *fourcc, + VkFormat *vk_format) +{ + if (n >= G_N_ELEMENTS (supported_formats)) + return FALSE; + + *fourcc = supported_formats[n].fourcc; + *vk_format = supported_formats[n].vk.format; + return TRUE; +} + VkFormat gdk_dmabuf_get_vk_format (guint32 fourcc, VkComponentMapping *out_components) diff --git a/gdk/gdkdmabufprivate.h b/gdk/gdkdmabufprivate.h index 8ea83afa94..914ee1f408 100644 --- a/gdk/gdkdmabufprivate.h +++ b/gdk/gdkdmabufprivate.h @@ -54,6 +54,9 @@ gboolean gdk_dmabuf_get_memory_format (guint32 gboolean premultiplied, GdkMemoryFormat *out_format); #ifdef GDK_RENDERING_VULKAN +gboolean gdk_dmabuf_vk_get_nth (gsize n, + guint32 *fourcc, + VkFormat *vk_format); VkFormat gdk_dmabuf_get_vk_format (guint32 fourcc, VkComponentMapping *out_components); #endif diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c index ebf74ed039..680a78d6d1 100644 --- a/gdk/gdkvulkancontext.c +++ b/gdk/gdkvulkancontext.c @@ -24,6 +24,10 @@ #include "gdkvulkancontextprivate.h" +#include "gdkdebugprivate.h" +#include "gdkdmabufformatsbuilderprivate.h" +#include "gdkdmabuffourccprivate.h" +#include "gdkdmabuftextureprivate.h" #include "gdkdisplayprivate.h" #include #include @@ -1726,6 +1730,7 @@ gdk_display_unref_vulkan (GdkDisplay *display) GDK_DEBUG (VULKAN, "Closing Vulkan instance"); display->vulkan_features = 0; + g_clear_pointer (&display->vk_dmabuf_formats, gdk_dmabuf_formats_unref); g_hash_table_iter_init (&iter, display->vk_shader_modules); while (g_hash_table_iter_next (&iter, &key, &value)) { @@ -1763,6 +1768,70 @@ gdk_display_unref_vulkan (GdkDisplay *display) display->vk_instance = VK_NULL_HANDLE; } +GdkDmabufDownloader * +gdk_vulkan_get_dmabuf_downloader (GdkDisplay *display, + GdkDmabufFormatsBuilder *builder) +{ + GdkDmabufFormatsBuilder *vulkan_builder; + VkDrmFormatModifierPropertiesEXT modifier_list[100]; + VkDrmFormatModifierPropertiesListEXT modifier_props = { + .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT, + .pNext = NULL, + .pDrmFormatModifierProperties = modifier_list, + }; + VkFormatProperties2 props = { + .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, + .pNext = &modifier_props, + }; + VkFormat vk_format; + guint32 fourcc; + gsize i, j; + + g_assert (display->vk_dmabuf_formats == NULL); + + if (!gdk_display_init_vulkan (display, NULL)) + return NULL; + + if ((display->vulkan_features & GDK_VULKAN_FEATURE_DMABUF) == 0) + return NULL; + + vulkan_builder = gdk_dmabuf_formats_builder_new (); + + for (i = 0; gdk_dmabuf_vk_get_nth (i, &fourcc, &vk_format); i++) + { + if (vk_format == VK_FORMAT_UNDEFINED) + continue; + + modifier_props.drmFormatModifierCount = sizeof (modifier_list); + vkGetPhysicalDeviceFormatProperties2 (display->vk_physical_device, + vk_format, + &props); + g_warn_if_fail (modifier_props.drmFormatModifierCount < sizeof (modifier_list)); + for (j = 0; j < modifier_props.drmFormatModifierCount; j++) + { + GDK_DISPLAY_DEBUG (display, DMABUF, + "Vulkan supports dmabuf format %.4s::%016llx with %u planes and features 0x%x", + (char *) &fourcc, + (long long unsigned) modifier_list[j].drmFormatModifier, + modifier_list[j].drmFormatModifierPlaneCount, + modifier_list[j].drmFormatModifierTilingFeatures); + + if (modifier_list[j].drmFormatModifier == DRM_FORMAT_MOD_LINEAR) + continue; + + gdk_dmabuf_formats_builder_add_format (vulkan_builder, + fourcc, + modifier_list[j].drmFormatModifier); + } + } + + display->vk_dmabuf_formats = gdk_dmabuf_formats_builder_free_to_formats (vulkan_builder); + + gdk_dmabuf_formats_builder_add_formats (builder, display->vk_dmabuf_formats); + + return NULL; +} + VkShaderModule gdk_display_get_vk_shader_module (GdkDisplay *self, const char *resource_name) diff --git a/gdk/gdkvulkancontextprivate.h b/gdk/gdkvulkancontextprivate.h index 98f97bd37d..ed84a260c1 100644 --- a/gdk/gdkvulkancontextprivate.h +++ b/gdk/gdkvulkancontextprivate.h @@ -23,6 +23,8 @@ #include "gdkvulkancontext.h" #include "gdkdebugprivate.h" +#include "gdkdmabufprivate.h" +#include "gdkdmabufdownloaderprivate.h" #include "gdkdrawcontextprivate.h" #include "gdkenums.h" @@ -74,6 +76,9 @@ gboolean gdk_display_init_vulkan (GdkDisp void gdk_display_ref_vulkan (GdkDisplay *display); void gdk_display_unref_vulkan (GdkDisplay *display); +GdkDmabufDownloader * gdk_vulkan_get_dmabuf_downloader (GdkDisplay *display, + GdkDmabufFormatsBuilder *builder); + VkShaderModule gdk_display_get_vk_shader_module (GdkDisplay *display, const char *resource_name);