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 <emma@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17773>
This commit is contained in:
Mike Blumenkrantz
2022-07-27 14:57:06 -04:00
committed by Marge Bot
parent 0a4e599918
commit 28ee911ad6

View File

@@ -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;
}
}