From 8847a50a04e14116c22698e3456fcb0e4a7ce7d4 Mon Sep 17 00:00:00 2001 From: Marcin Radomski Date: Wed, 26 Jun 2024 15:44:33 +0000 Subject: [PATCH] Enable VK_EXT_image_drm_format_modifier on Linux guests Do not force linear tiling for WSI in vkCreateImage. Allow creating WSI images from DMABUFs with DRM format modifiers. If the extension is supported by host, forward VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT to vkGetPhysicalDeviceImageFormatProperties2 and vkCreateImage. If it's not supported, attempt to support DRM_FORMAT_MOD_LINEAR by mapping it to VK_TILING_LINEAR. Reviewed-by: Aaron Ruby Acked-by: Yonggang Luo Acked-by: Adam Jackson Part-of: --- .../guest/vulkan_enc/ResourceTracker.cpp | 70 +++++++++++++++---- src/gfxstream/guest/vulkan_enc/vk_struct_id.h | 5 ++ 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp b/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp index 4aca2fedeea..62cc3b19eae 100644 --- a/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp +++ b/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp @@ -46,6 +46,10 @@ #include "vk_struct_id.h" #include "vk_util.h" +#if defined(__linux__) +#include +#endif + #if defined(__ANDROID__) || defined(__linux__) || defined(__APPLE__) #include @@ -1893,6 +1897,9 @@ VkResult ResourceTracker::on_vkEnumerateDeviceExtensionProperties( #if !defined(VK_USE_PLATFORM_ANDROID_KHR) && defined(__linux__) filteredExts.push_back(VkExtensionProperties{"VK_KHR_external_memory_fd", 1}); filteredExts.push_back(VkExtensionProperties{"VK_EXT_external_memory_dma_buf", 1}); + // In case the host doesn't support format modifiers, they are emulated + // on guest side. + filteredExts.push_back(VkExtensionProperties{"VK_EXT_image_drm_format_modifier", 1}); #endif } @@ -4224,28 +4231,40 @@ VkResult ResourceTracker::on_vkCreateImage(void* context, VkResult, VkDevice dev #if defined(LINUX_GUEST_BUILD) bool isDmaBufImage = false; + VkImageDrmFormatModifierExplicitCreateInfoEXT localDrmFormatModifierInfo; + if (extImgCiPtr && (extImgCiPtr->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)) { const wsi_image_create_info* wsiImageCi = vk_find_struct(pCreateInfo); - if (wsiImageCi) { - if (!wsiImageCi->scanout) { - mesa_logd( - "gfxstream only supports native DRM image scanout path for Linux WSI " - "(wsi_image_create_info::scanout)"); - return VK_ERROR_INITIALIZATION_FAILED; - } + if (wsiImageCi && wsiImageCi->scanout) { // Linux WSI creates swapchain images with VK_IMAGE_CREATE_ALIAS_BIT. Vulkan spec // states: "If the pNext chain includes a VkExternalMemoryImageCreateInfo or // VkExternalMemoryImageCreateInfoNV structure whose handleTypes member is not 0, it is // as if VK_IMAGE_CREATE_ALIAS_BIT is set." To avoid flag mismatches on host driver, // remove the VK_IMAGE_CREATE_ALIAS_BIT here. localCreateInfo.flags &= ~VK_IMAGE_CREATE_ALIAS_BIT; - // TODO (b/326956485): DRM format modifiers to support client/compositor awareness - // For now, override WSI images to use linear tiling, as compositor will default to - // DRM_FORMAT_MOD_LINEAR. - localCreateInfo.tiling = VK_IMAGE_TILING_LINEAR; } + + const VkImageDrmFormatModifierExplicitCreateInfoEXT* drmFmtMod = + vk_find_struct(pCreateInfo); + if (drmFmtMod) { + if (getHostDeviceExtensionIndex(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME) != + -1) { + // host supports DRM format modifiers => forward the struct + localDrmFormatModifierInfo = vk_make_orphan_copy(*drmFmtMod); + vk_append_struct(&structChainIter, &localDrmFormatModifierInfo); + } else { + // host doesn't support DRM format modifiers, try emulating + if (drmFmtMod->drmFormatModifier == DRM_FORMAT_MOD_LINEAR) { + mesa_logd("emulating DRM_FORMAT_MOD_LINEAR with VK_IMAGE_TILING_LINEAR"); + localCreateInfo.tiling = VK_IMAGE_TILING_LINEAR; + } else { + return VK_ERROR_VALIDATION_FAILED_EXT; + } + } + } + isDmaBufImage = true; } #endif @@ -6680,6 +6699,8 @@ VkResult ResourceTracker::on_vkGetPhysicalDeviceImageFormatProperties2_common( VkEncoder* enc = (VkEncoder*)context; (void)input_result; + VkPhysicalDeviceImageFormatInfo2 localImageFormatInfo = *pImageFormatInfo; + uint32_t supportedHandleType = 0; VkExternalImageFormatProperties* ext_img_properties = vk_find_struct(pImageFormatProperties); @@ -6723,14 +6744,37 @@ VkResult ResourceTracker::on_vkGetPhysicalDeviceImageFormatProperties2_common( } } +#ifdef LINUX_GUEST_BUILD + VkImageDrmFormatModifierExplicitCreateInfoEXT localDrmFormatModifierInfo; + + const VkPhysicalDeviceImageDrmFormatModifierInfoEXT* drmFmtMod = + vk_find_struct(pImageFormatInfo); + if (drmFmtMod) { + if (getHostDeviceExtensionIndex(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME) != -1) { + // Host supports DRM format modifiers => leave the input unchanged. + } else { + // Host doesn't support DRM format modifiers, try emulating. + if (drmFmtMod->drmFormatModifier == DRM_FORMAT_MOD_LINEAR) { + mesa_logd("emulating DRM_FORMAT_MOD_LINEAR with VK_IMAGE_TILING_LINEAR"); + localImageFormatInfo.tiling = VK_IMAGE_TILING_LINEAR; + pImageFormatInfo = &localImageFormatInfo; + // Leave drmFormatMod in the input; it should be ignored when + // tiling is not VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT + } else { + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } + } + } +#endif // LINUX_GUEST_BUILD + VkResult hostRes; if (isKhr) { hostRes = enc->vkGetPhysicalDeviceImageFormatProperties2KHR( - physicalDevice, pImageFormatInfo, pImageFormatProperties, true /* do lock */); + physicalDevice, &localImageFormatInfo, pImageFormatProperties, true /* do lock */); } else { hostRes = enc->vkGetPhysicalDeviceImageFormatProperties2( - physicalDevice, pImageFormatInfo, pImageFormatProperties, true /* do lock */); + physicalDevice, &localImageFormatInfo, pImageFormatProperties, true /* do lock */); } if (hostRes != VK_SUCCESS) return hostRes; diff --git a/src/gfxstream/guest/vulkan_enc/vk_struct_id.h b/src/gfxstream/guest/vulkan_enc/vk_struct_id.h index e7a6e608bfc..e47b7457726 100644 --- a/src/gfxstream/guest/vulkan_enc/vk_struct_id.h +++ b/src/gfxstream/guest/vulkan_enc/vk_struct_id.h @@ -135,6 +135,11 @@ REGISTER_VK_STRUCT_ID(VkTimelineSemaphoreSubmitInfo, #if defined(LINUX_GUEST_BUILD) REGISTER_VK_STRUCT_ID(wsi_image_create_info, VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA); #endif +REGISTER_VK_STRUCT_ID(VkImageDrmFormatModifierExplicitCreateInfoEXT, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT); +REGISTER_VK_STRUCT_ID(VkFormatProperties2, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); +REGISTER_VK_STRUCT_ID(VkPhysicalDeviceImageDrmFormatModifierInfoEXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT); #undef REGISTER_VK_STRUCT_ID