From fd4548bb93af7e26f52a9ca266da3af78b17bf93 Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Sat, 21 Oct 2023 21:29:46 -0400 Subject: [PATCH] render/vulkan: detect which _UNORM formats support _SRGB views --- include/render/vulkan.h | 2 ++ render/vulkan/pixel_format.c | 70 ++++++++++++++++++++++++++++++++---- render/vulkan/vulkan.c | 4 +-- 3 files changed, 67 insertions(+), 9 deletions(-) diff --git a/include/render/vulkan.h b/include/render/vulkan.h index 17f1c3bb..c0ba9b20 100644 --- a/include/render/vulkan.h +++ b/include/render/vulkan.h @@ -101,6 +101,7 @@ const struct wlr_vk_format *vulkan_get_format_from_drm(uint32_t drm_format); struct wlr_vk_format_modifier_props { VkDrmFormatModifierPropertiesEXT props; VkExtent2D max_extent; + bool has_mutable_srgb; }; struct wlr_vk_format_props { @@ -109,6 +110,7 @@ struct wlr_vk_format_props { struct { VkExtent2D max_extent; VkFormatFeatureFlags features; + bool has_mutable_srgb; } shm; struct { diff --git a/render/vulkan/pixel_format.c b/render/vulkan/pixel_format.c index 61fb6e39..3dd9c4d3 100644 --- a/render/vulkan/pixel_format.c +++ b/render/vulkan/pixel_format.c @@ -258,16 +258,28 @@ static const VkFormatFeatureFlags ycbcr_tex_features = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT | VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT; +// vk_format_variant should be set to 0=VK_FORMAT_UNDEFINED when not used static bool query_modifier_usage_support(struct wlr_vk_device *dev, VkFormat vk_format, - VkImageUsageFlags usage, const VkDrmFormatModifierPropertiesEXT *m, + VkFormat vk_format_variant, VkImageUsageFlags usage, + const VkDrmFormatModifierPropertiesEXT *m, struct wlr_vk_format_modifier_props *out, const char **errmsg) { VkResult res; *errmsg = NULL; + VkFormat view_formats[2] = { + vk_format, + vk_format_variant, + }; + VkImageFormatListCreateInfoKHR listi = { + .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR, + .pViewFormats = view_formats, + .viewFormatCount = vk_format_variant ? 2 : 1, + }; VkPhysicalDeviceImageDrmFormatModifierInfoEXT modi = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, .drmFormatModifier = m->drmFormatModifier, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .pNext = &listi, }; VkPhysicalDeviceExternalImageFormatInfo efmti = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, @@ -279,6 +291,7 @@ static bool query_modifier_usage_support(struct wlr_vk_device *dev, VkFormat vk_ .type = VK_IMAGE_TYPE_2D, .format = vk_format, .usage = usage, + .flags = vk_format_variant ? VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT : 0, .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, .pNext = &efmti, }; @@ -316,18 +329,29 @@ static bool query_modifier_usage_support(struct wlr_vk_device *dev, VkFormat vk_ } static bool query_shm_support(struct wlr_vk_device *dev, VkFormat vk_format, - VkImageFormatProperties *out, const char **errmsg) { + VkFormat vk_format_variant, VkImageFormatProperties *out, + const char **errmsg) { VkResult res; *errmsg = NULL; + VkFormat view_formats[2] = { + vk_format, + vk_format_variant, + }; + VkImageFormatListCreateInfoKHR listi = { + .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR, + .pViewFormats = view_formats, + .viewFormatCount = vk_format_variant ? 2 : 1, + .pNext = NULL, + }; VkPhysicalDeviceImageFormatInfo2 fmti = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, .type = VK_IMAGE_TYPE_2D, .format = vk_format, .tiling = VK_IMAGE_TILING_OPTIMAL, .usage = vulkan_shm_tex_usage, - .flags = 0, - .pNext = NULL, + .flags = vk_format_variant ? VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT : 0, + .pNext = &listi, }; VkImageFormatProperties2 ifmtp = { .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, @@ -390,7 +414,18 @@ static bool query_modifier_support(struct wlr_vk_device *dev, if ((m.drmFormatModifierTilingFeatures & render_features) == render_features && !props->format.is_ycbcr) { struct wlr_vk_format_modifier_props p = {0}; - if (query_modifier_usage_support(dev, props->format.vk, vulkan_render_usage, &m, &p, &errmsg)) { + bool supported = false; + if (query_modifier_usage_support(dev, props->format.vk, + props->format.vk_srgb, vulkan_render_usage, &m, &p, &errmsg)) { + supported = true; + p.has_mutable_srgb = props->format.vk_srgb != 0; + } + if (!supported && props->format.vk_srgb) { + supported = query_modifier_usage_support(dev, props->format.vk, + 0, vulkan_render_usage, &m, &p, &errmsg); + } + + if (supported) { props->dmabuf.render_mods[props->dmabuf.render_mod_count++] = p; wlr_drm_format_set_add(&dev->dmabuf_render_formats, props->format.drm, m.drmFormatModifier); @@ -413,7 +448,18 @@ static bool query_modifier_support(struct wlr_vk_device *dev, } if ((m.drmFormatModifierTilingFeatures & features) == features) { struct wlr_vk_format_modifier_props p = {0}; - if (query_modifier_usage_support(dev, props->format.vk, vulkan_dma_tex_usage, &m, &p, &errmsg)) { + bool supported = false; + if (query_modifier_usage_support(dev, props->format.vk, + props->format.vk_srgb, vulkan_dma_tex_usage, &m, &p, &errmsg)) { + supported = true; + p.has_mutable_srgb = props->format.vk_srgb != 0; + } + if (!supported && props->format.vk_srgb) { + supported = query_modifier_usage_support(dev, props->format.vk, + 0, vulkan_dma_tex_usage, &m, &p, &errmsg); + } + + if (supported) { props->dmabuf.texture_mods[props->dmabuf.texture_mod_count++] = p; wlr_drm_format_set_add(&dev->dmabuf_texture_formats, props->format.drm, m.drmFormatModifier); @@ -473,10 +519,20 @@ void vulkan_format_props_query(struct wlr_vk_device *dev, if ((fmtp.formatProperties.optimalTilingFeatures & shm_tex_features) == shm_tex_features && !format->is_ycbcr && format_info != NULL) { VkImageFormatProperties ifmtp; - if (query_shm_support(dev, format->vk, &ifmtp, &errmsg)) { + bool supported = false, has_mutable_srgb = false; + if (query_shm_support(dev, format->vk, format->vk_srgb, &ifmtp, &errmsg)) { + supported = true; + has_mutable_srgb = format->vk_srgb != 0; + } + if (!supported && format->vk_srgb) { + supported = query_shm_support(dev, format->vk, 0, &ifmtp, &errmsg); + } + + if (supported) { props.shm.max_extent.width = ifmtp.maxExtent.width; props.shm.max_extent.height = ifmtp.maxExtent.height; props.shm.features = fmtp.formatProperties.optimalTilingFeatures; + props.shm.has_mutable_srgb = has_mutable_srgb; dev->shm_formats[dev->shm_format_count] = format->drm; ++dev->shm_format_count; diff --git a/render/vulkan/vulkan.c b/render/vulkan/vulkan.c index b8ba0b48..8e9d9288 100644 --- a/render/vulkan/vulkan.c +++ b/render/vulkan/vulkan.c @@ -455,8 +455,8 @@ struct wlr_vk_device *vulkan_device_create(struct wlr_vk_instance *ini, dev->drm_fd = -1; // For dmabuf import we require at least the external_memory_fd, - // external_memory_dma_buf, queue_family_foreign and - // image_drm_format_modifier extensions. + // external_memory_dma_buf, queue_family_foreign, + // image_drm_format_modifier, and image_format_list extensions. // The size is set to a large number to allow for other conditional // extensions before the device is created const char *extensions[32] = {0};