From 28ee911ad67192bc7a0683b6061b89e372482faf Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Wed, 27 Jul 2022 14:57:06 -0400 Subject: [PATCH] zink: handle mutable swapchain images with dmabuf if a non-kopper swapchain image supports srgb, add a VkImageFormatListCreateInfo to permit srgb mutability and avoid violating spec cc: mesa-stable Acked-by: Emma Anholt Part-of: --- src/gallium/drivers/zink/zink_resource.c | 84 ++++++++++++++++++------ 1 file changed, 64 insertions(+), 20 deletions(-) diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index cc8da454cd0..5c4bf4ecef6 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -212,6 +212,8 @@ check_ici(struct zink_screen *screen, VkImageCreateInfo *ici, uint64_t modifier) props2.pNext = &ycbcr_props; VkPhysicalDeviceImageFormatInfo2 info; info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2; + /* possibly VkImageFormatListCreateInfo */ + info.pNext = ici->pNext; info.format = ici->format; info.type = ici->imageType; info.tiling = ici->tiling; @@ -221,13 +223,12 @@ check_ici(struct zink_screen *screen, VkImageCreateInfo *ici, uint64_t modifier) VkPhysicalDeviceImageDrmFormatModifierInfoEXT mod_info; if (modifier != DRM_FORMAT_MOD_INVALID) { mod_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT; - mod_info.pNext = NULL; + mod_info.pNext = info.pNext; mod_info.drmFormatModifier = modifier; mod_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; mod_info.queueFamilyIndexCount = 0; info.pNext = &mod_info; - } else - info.pNext = NULL; + } ret = VKSCR(GetPhysicalDeviceImageFormatProperties2)(screen->pdev, &info, &props2); /* this is using VK_IMAGE_CREATE_EXTENDED_USAGE_BIT and can't be validated */ @@ -324,6 +325,30 @@ find_modifier_feats(const struct zink_modifier_prop *prop, uint64_t modifier, ui return 0; } +/* If the driver can't do mutable with this ICI, then try again after removing mutable (and + * thus also the list of formats we might might mutate to) + */ +static bool +double_check_ici(struct zink_screen *screen, VkImageCreateInfo *ici, VkImageUsageFlags usage, uint64_t *mod) +{ + if (!usage) + return false; + + const void *pNext = ici->pNext; + ici->usage = usage; + if (check_ici(screen, ici, *mod)) + return true; + if (pNext) { + ici->pNext = NULL; + ici->flags &= ~VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + if (check_ici(screen, ici, *mod)) + return true; + ici->pNext = pNext; + ici->flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + } + return false; +} + static VkImageUsageFlags get_image_usage(struct zink_screen *screen, VkImageCreateInfo *ici, const struct pipe_resource *templ, unsigned bind, unsigned modifiers_count, const uint64_t *modifiers, uint64_t *mod) { @@ -345,11 +370,8 @@ get_image_usage(struct zink_screen *screen, VkImageCreateInfo *ici, const struct if (feats) { VkImageUsageFlags usage = get_image_usage_for_feats(screen, feats, templ, bind, &need_extended); assert(!need_extended); - if (usage) { - ici->usage = usage; - if (check_ici(screen, ici, *mod)) - return usage; - } + if (double_check_ici(screen, ici, usage, mod)) + return usage; } } /* only try linear if no other options available */ @@ -358,11 +380,8 @@ get_image_usage(struct zink_screen *screen, VkImageCreateInfo *ici, const struct if (feats) { VkImageUsageFlags usage = get_image_usage_for_feats(screen, feats, templ, bind, &need_extended); assert(!need_extended); - if (usage) { - ici->usage = usage; - if (check_ici(screen, ici, *mod)) - return usage; - } + if (double_check_ici(screen, ici, usage, mod)) + return usage; } } } else @@ -377,11 +396,8 @@ get_image_usage(struct zink_screen *screen, VkImageCreateInfo *ici, const struct feats = UINT32_MAX; usage = get_image_usage_for_feats(screen, feats, templ, bind, &need_extended); } - if (usage) { - ici->usage = usage; - if (check_ici(screen, ici, *mod)) - return usage; - } + if (double_check_ici(screen, ici, usage, mod)) + return usage; } *mod = DRM_FORMAT_MOD_INVALID; return 0; @@ -391,11 +407,17 @@ static uint64_t create_ici(struct zink_screen *screen, VkImageCreateInfo *ici, const struct pipe_resource *templ, bool dmabuf, unsigned bind, unsigned modifiers_count, const uint64_t *modifiers, bool *success) { ici->sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - ici->pNext = NULL; + /* pNext may already be set */ if (util_format_get_num_planes(templ->format) > 1) ici->flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; else ici->flags = modifiers_count || dmabuf || bind & (PIPE_BIND_SCANOUT | PIPE_BIND_DEPTH_STENCIL) ? 0 : VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + if (ici->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) + /* unset VkImageFormatListCreateInfo if mutable */ + ici->pNext = NULL; + else if (ici->pNext) + /* add mutable if VkImageFormatListCreateInfo */ + ici->flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; ici->usage = 0; ici->queueFamilyIndexCount = 0; @@ -634,6 +656,27 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t unsigned ici_modifier_count = winsys_modifier ? 1 : modifiers_count; bool success = false; VkImageCreateInfo ici; + enum pipe_format srgb = PIPE_FORMAT_NONE; + if (screen->info.have_KHR_swapchain_mutable_format) { + srgb = util_format_is_srgb(templ->format) ? util_format_linear(templ->format) : util_format_srgb(templ->format); + /* why do these helpers have different default return values? */ + if (srgb == templ->format) + srgb = PIPE_FORMAT_NONE; + } + VkFormat formats[2]; + VkImageFormatListCreateInfo format_list; + if (srgb) { + format_list.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO; + format_list.pNext = NULL; + format_list.viewFormatCount = 2; + format_list.pViewFormats = formats; + + formats[0] = zink_get_format(screen, templ->format); + formats[1] = zink_get_format(screen, srgb); + ici.pNext = &format_list; + } else { + ici.pNext = NULL; + } uint64_t mod = create_ici(screen, &ici, templ, external == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, templ->bind, ici_modifier_count, ici_modifiers, &success); VkExternalMemoryImageCreateInfo emici; @@ -651,6 +694,7 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t goto fail1; obj->render_target = (ici.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0; + const void *pNext = ici.pNext; if (shared || external) { emici.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; @@ -687,7 +731,7 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t ici.pNext = &idfmlci; } else if (ici.tiling == VK_IMAGE_TILING_OPTIMAL) { if (!external) - ici.pNext = NULL; + ici.pNext = pNext; shared = false; } }