From a3e191c354d8078c587d37650efe1034bd579a8b Mon Sep 17 00:00:00 2001 From: elwrcl Date: Fri, 21 Aug 2026 07:06:57 +0300 Subject: [PATCH] hasvk: Support VK_KHR_unified_image_layouts. VK_IMAGE_LAYOUT_GENERAL already lands on the conservative aux choice for every usage, since anv_layout_to_aux_state() derives that from the layout's usage flags and GENERAL reports all of them, and video images carry no aux at all. So the layout itself needed no work; what the extension does add is a requirement that the host image copy layout lists name every layout it declares interchangeable with GENERAL. Those layouts can only be offered if a host copy is safe in each of them, and the CPU cannot resolve an aux surface on its way to the image. Create images that carry VK_IMAGE_USAGE_HOST_TRANSFER_BIT without one, which makes every layout equivalent for them and vkTransitionImageLayoutEXT a genuine no-op rather than one justified by only ever offering GENERAL. dEQP-VK.video.encode.h264 goes from 18 to 36 passes out of 120, still with no failures: the general_layout variants were the whole gap. dEQP-VK.image.host_image_copy goes from 2037 passes and one failure to 19140 passes and none, the failure having been the properties test checking exactly this list. Co-Authored-By: Claude Opus 5 --- src/intel/vulkan_hasvk/anv_device.c | 36 ++++++++++++++++++++ src/intel/vulkan_hasvk/anv_host_image_copy.c | 6 ++-- src/intel/vulkan_hasvk/anv_image.c | 9 +++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/intel/vulkan_hasvk/anv_device.c b/src/intel/vulkan_hasvk/anv_device.c index 93fb80e..c242132 100644 --- a/src/intel/vulkan_hasvk/anv_device.c +++ b/src/intel/vulkan_hasvk/anv_device.c @@ -291,6 +291,7 @@ get_device_extensions(const struct anv_physical_device *device, .KHR_video_encode_h264 = video_encode, .KHR_video_maintenance1 = video_decode || video_encode, .KHR_video_maintenance2 = video_decode || video_encode, + .KHR_unified_image_layouts = true, .KHR_synchronization2 = true, .KHR_timeline_semaphore = true, .KHR_internally_synchronized_queues = true, @@ -734,6 +735,16 @@ get_features(const struct anv_physical_device *pdevice, /* VK_KHR_video_maintenance2 */ .videoMaintenance2 = true, + /* VK_KHR_unified_image_layouts + * + * Aux usage is derived from the layout's usage flags, and GENERAL simply + * reports every usage the image was created with, so it already lands on + * the conservative choice for each one. Video images carry no aux at + * all, which makes their transitions no-ops either way. + */ + .unifiedImageLayouts = true, + .unifiedImageLayoutsVideo = true, + /* VK_KHR_internally_synchronized_queues */ .internallySynchronizedQueues = true, }; @@ -1258,8 +1269,33 @@ get_properties(const struct anv_physical_device *pdevice, /* VK_EXT_host_image_copy */ { + /* An image usable by host copy carries no aux surface (see + * anv_image_init), so every layout is equivalent for it and all of them + * can be offered. VK_KHR_unified_image_layouts requires the layouts it + * declares interchangeable with GENERAL to appear here. + */ static const VkImageLayout host_copy_layouts[] = { VK_IMAGE_LAYOUT_GENERAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, + VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, + VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, + VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, + VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, + VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, }; props->copySrcLayoutCount = ARRAY_SIZE(host_copy_layouts); diff --git a/src/intel/vulkan_hasvk/anv_host_image_copy.c b/src/intel/vulkan_hasvk/anv_host_image_copy.c index bf6b56c..1d6bb54 100644 --- a/src/intel/vulkan_hasvk/anv_host_image_copy.c +++ b/src/intel/vulkan_hasvk/anv_host_image_copy.c @@ -421,9 +421,9 @@ VkResult anv_TransitionImageLayoutEXT( uint32_t transitionCount, const VkHostImageLayoutTransitionInfoEXT* pTransitions) { - /* Host copy icin yalnizca aux surface'i olmayan layout'lar - * (VK_IMAGE_LAYOUT_GENERAL) raporlaniyor, dolayisiyla burada - * yapilacak bir is yok. + /* An image with VK_IMAGE_USAGE_HOST_TRANSFER_BIT is created without an aux + * surface, so no layout carries compressed data and there is nothing to + * resolve between them. */ return VK_SUCCESS; } \ No newline at end of file diff --git a/src/intel/vulkan_hasvk/anv_image.c b/src/intel/vulkan_hasvk/anv_image.c index 345f983..1f98d8c 100644 --- a/src/intel/vulkan_hasvk/anv_image.c +++ b/src/intel/vulkan_hasvk/anv_image.c @@ -1392,6 +1392,15 @@ anv_image_init(struct anv_device *device, struct anv_image *image, image->vk.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) create_info->isl_extra_usage_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT; + /* Host image copy reaches the surface with the CPU and cannot resolve an + * aux surface on the way, so an image it can touch must carry none. That + * also makes every layout equivalent for such an image, which is what lets + * pCopySrc/DstLayouts list more than VK_IMAGE_LAYOUT_GENERAL and + * vkTransitionImageLayoutEXT stay a no-op. + */ + if (image->vk.usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT) + create_info->isl_extra_usage_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT; + const isl_tiling_flags_t isl_tiling_flags = choose_isl_tiling_flags(device->info, create_info, isl_mod_info, image->vk.wsi_legacy_scanout);