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 <[email protected]>
This commit is contained in:
elwrclandClaude Opus 5 committed 2026-08-21 07:06:57 +03:00
1 parent 4caedfb57d
commit a3e191c354
3 files changed
+48 -3

No files matched your search

+36
View File
@@ -291,6 +291,7 @@ get_device_extensions(const struct anv_physical_device *device,
.KHR_video_encode_h264 = video_encode, .KHR_video_encode_h264 = video_encode,
.KHR_video_maintenance1 = video_decode || video_encode, .KHR_video_maintenance1 = video_decode || video_encode,
.KHR_video_maintenance2 = video_decode || video_encode, .KHR_video_maintenance2 = video_decode || video_encode,
.KHR_unified_image_layouts = true,
.KHR_synchronization2 = true, .KHR_synchronization2 = true,
.KHR_timeline_semaphore = true, .KHR_timeline_semaphore = true,
.KHR_internally_synchronized_queues = true, .KHR_internally_synchronized_queues = true,
@@ -734,6 +735,16 @@ get_features(const struct anv_physical_device *pdevice,
/* VK_KHR_video_maintenance2 */ /* VK_KHR_video_maintenance2 */
.videoMaintenance2 = true, .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 */ /* VK_KHR_internally_synchronized_queues */
.internallySynchronizedQueues = true, .internallySynchronizedQueues = true,
}; };
@@ -1258,8 +1269,33 @@ get_properties(const struct anv_physical_device *pdevice,
/* VK_EXT_host_image_copy */ /* 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[] = { static const VkImageLayout host_copy_layouts[] = {
VK_IMAGE_LAYOUT_GENERAL, 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); props->copySrcLayoutCount = ARRAY_SIZE(host_copy_layouts);
+3 -3
View File
@@ -421,9 +421,9 @@ VkResult anv_TransitionImageLayoutEXT(
uint32_t transitionCount, uint32_t transitionCount,
const VkHostImageLayoutTransitionInfoEXT* pTransitions) const VkHostImageLayoutTransitionInfoEXT* pTransitions)
{ {
/* Host copy icin yalnizca aux surface'i olmayan layout'lar /* An image with VK_IMAGE_USAGE_HOST_TRANSFER_BIT is created without an aux
* (VK_IMAGE_LAYOUT_GENERAL) raporlaniyor, dolayisiyla burada * surface, so no layout carries compressed data and there is nothing to
* yapilacak bir is yok. * resolve between them.
*/ */
return VK_SUCCESS; return VK_SUCCESS;
} }
+9
View File
@@ -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) image->vk.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
create_info->isl_extra_usage_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT; 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 = const isl_tiling_flags_t isl_tiling_flags =
choose_isl_tiling_flags(device->info, create_info, isl_mod_info, choose_isl_tiling_flags(device->info, create_info, isl_mod_info,
image->vk.wsi_legacy_scanout); image->vk.wsi_legacy_scanout);