diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h index 702f7bdbd4..085a1226c1 100644 --- a/gdk/gdkdisplayprivate.h +++ b/gdk/gdkdisplayprivate.h @@ -41,6 +41,11 @@ G_BEGIN_DECLS typedef struct _GdkDisplayClass GdkDisplayClass; +typedef enum { + GDK_VULKAN_FEATURE_DMABUF = 1 << 0, + GDK_VULKAN_FEATURE_YCBCR = 1 << 1 +} GdkVulkanFeatures; + /* Tracks information about the device grab on this display */ typedef struct { @@ -107,6 +112,7 @@ struct _GdkDisplay char *vk_pipeline_cache_etag; guint vk_save_pipeline_cache_source; GHashTable *vk_shader_modules; + GdkVulkanFeatures vulkan_features; guint vulkan_refcount; #endif /* GDK_RENDERING_VULKAN */ diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c index 4ba2c6bbd4..ebf74ed039 100644 --- a/gdk/gdkvulkancontext.c +++ b/gdk/gdkvulkancontext.c @@ -533,6 +533,36 @@ physical_device_supports_extension (VkPhysicalDevice device, return FALSE; } +static gboolean +physical_device_check_features (VkPhysicalDevice device, + GdkVulkanFeatures *out_features) +{ + VkPhysicalDeviceSamplerYcbcrConversionFeatures ycbcr_features = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES + }; + VkPhysicalDeviceFeatures2 features = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, + .pNext = &ycbcr_features + }; + + vkGetPhysicalDeviceFeatures2 (device, &features); + + *out_features = 0; + + if (!features.features.shaderUniformBufferArrayDynamicIndexing || + !features.features.shaderSampledImageArrayDynamicIndexing) + return FALSE; + + if (ycbcr_features.samplerYcbcrConversion) + *out_features |= GDK_VULKAN_FEATURE_YCBCR; + + if (physical_device_supports_extension (device, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME) && + physical_device_supports_extension (device, VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME)) + *out_features |= GDK_VULKAN_FEATURE_DMABUF; + + return TRUE; +} + static void gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context, GdkMemoryDepth depth, @@ -1368,11 +1398,15 @@ gdk_display_create_vulkan_device (GdkDisplay *display, for (i = first; i < last; i++) { + GdkVulkanFeatures features; uint32_t n_queue_props; if (!physical_device_supports_extension (devices[i], VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)) continue; + if (!physical_device_check_features (devices[i], &features)) + continue; + vkGetPhysicalDeviceQueueFamilyProperties (devices[i], &n_queue_props, NULL); VkQueueFamilyProperties *queue_props = g_newa (VkQueueFamilyProperties, n_queue_props); vkGetPhysicalDeviceQueueFamilyProperties (devices[i], &n_queue_props, queue_props); @@ -1381,16 +1415,17 @@ gdk_display_create_vulkan_device (GdkDisplay *display, if (queue_props[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) { GPtrArray *device_extensions; - gboolean has_incremental_present; - - has_incremental_present = physical_device_supports_extension (devices[i], - VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME); device_extensions = g_ptr_array_new (); g_ptr_array_add (device_extensions, (gpointer) VK_KHR_SWAPCHAIN_EXTENSION_NAME); g_ptr_array_add (device_extensions, (gpointer) VK_KHR_MAINTENANCE_3_EXTENSION_NAME); g_ptr_array_add (device_extensions, (gpointer) VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); - if (has_incremental_present) + if (features & GDK_VULKAN_FEATURE_DMABUF) + { + g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); + g_ptr_array_add (device_extensions, (gpointer) VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME); + } + if (physical_device_supports_extension (devices[i], VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME)) g_ptr_array_add (device_extensions, (gpointer) VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME); GDK_DISPLAY_DEBUG (display, VULKAN, "Using Vulkan device %u, queue %u", i, j); @@ -1406,15 +1441,19 @@ gdk_display_create_vulkan_device (GdkDisplay *display, }, .enabledExtensionCount = device_extensions->len, .ppEnabledExtensionNames = (const char * const *) device_extensions->pdata, - .pNext = &(VkPhysicalDeviceVulkan12Features) { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, - .shaderSampledImageArrayNonUniformIndexing = VK_TRUE, - .shaderStorageBufferArrayNonUniformIndexing = VK_TRUE, - .descriptorIndexing = VK_TRUE, - .descriptorBindingPartiallyBound = VK_TRUE, - .descriptorBindingVariableDescriptorCount = VK_TRUE, - .descriptorBindingSampledImageUpdateAfterBind = VK_TRUE, - .descriptorBindingStorageBufferUpdateAfterBind = VK_TRUE, + .pNext = &(VkPhysicalDeviceVulkan11Features) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES, + .samplerYcbcrConversion = features & GDK_VULKAN_FEATURE_YCBCR ? VK_TRUE : VK_FALSE, + .pNext = &(VkPhysicalDeviceVulkan12Features) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, + .shaderSampledImageArrayNonUniformIndexing = VK_TRUE, + .shaderStorageBufferArrayNonUniformIndexing = VK_TRUE, + .descriptorIndexing = VK_TRUE, + .descriptorBindingPartiallyBound = VK_TRUE, + .descriptorBindingVariableDescriptorCount = VK_TRUE, + .descriptorBindingSampledImageUpdateAfterBind = VK_TRUE, + .descriptorBindingStorageBufferUpdateAfterBind = VK_TRUE, + } } }, NULL, @@ -1429,6 +1468,7 @@ gdk_display_create_vulkan_device (GdkDisplay *display, display->vk_physical_device = devices[i]; vkGetDeviceQueue(display->vk_device, j, 0, &display->vk_queue); display->vk_queue_family_index = j; + display->vulkan_features = features; return TRUE; } } @@ -1685,6 +1725,7 @@ gdk_display_unref_vulkan (GdkDisplay *display) return; GDK_DEBUG (VULKAN, "Closing Vulkan instance"); + display->vulkan_features = 0; g_hash_table_iter_init (&iter, display->vk_shader_modules); while (g_hash_table_iter_next (&iter, &key, &value)) { diff --git a/gsk/gpu/gskvulkandevice.c b/gsk/gpu/gskvulkandevice.c index c45dec49b9..6de7551e4d 100644 --- a/gsk/gpu/gskvulkandevice.c +++ b/gsk/gpu/gskvulkandevice.c @@ -17,6 +17,7 @@ struct _GskVulkanDevice GskGpuDevice parent_instance; GskVulkanAllocator *allocators[VK_MAX_MEMORY_TYPES]; + GdkVulkanFeatures features; GHashTable *pipeline_cache; GHashTable *render_pass_cache; @@ -314,6 +315,7 @@ gsk_vulkan_device_get_for_display (GdkDisplay *display, return NULL; self = g_object_new (GSK_TYPE_VULKAN_DEVICE, NULL); + self->features = display->vulkan_features; vkGetPhysicalDeviceProperties (display->vk_physical_device, &vk_props); gsk_gpu_device_setup (GSK_GPU_DEVICE (self), @@ -332,6 +334,13 @@ gsk_vulkan_device_get_max_descriptors (GskVulkanDevice *self) return DESCRIPTOR_POOL_MAXITEMS; } +gboolean +gsk_vulkan_device_has_feature (GskVulkanDevice *self, + GdkVulkanFeatures feature) +{ + return (self->features & feature) == feature; +} + VkDevice gsk_vulkan_device_get_vk_device (GskVulkanDevice *self) { diff --git a/gsk/gpu/gskvulkandeviceprivate.h b/gsk/gpu/gskvulkandeviceprivate.h index 84a369d9e9..c68bd2bae1 100644 --- a/gsk/gpu/gskvulkandeviceprivate.h +++ b/gsk/gpu/gskvulkandeviceprivate.h @@ -7,6 +7,7 @@ #include "gskvulkanmemoryprivate.h" #include +#include "gdk/gdkdisplayprivate.h" G_BEGIN_DECLS @@ -26,6 +27,8 @@ GskGpuDevice * gsk_vulkan_device_get_for_display (GdkDisp GError **error); gsize gsk_vulkan_device_get_max_descriptors (GskVulkanDevice *self) G_GNUC_PURE; +gboolean gsk_vulkan_device_has_feature (GskVulkanDevice *self, + GdkVulkanFeatures feature) G_GNUC_PURE; VkDevice gsk_vulkan_device_get_vk_device (GskVulkanDevice *self) G_GNUC_PURE; VkPhysicalDevice gsk_vulkan_device_get_vk_physical_device (GskVulkanDevice *self) G_GNUC_PURE;