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