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 <aruby@blackberry.com>
Acked-by: Yonggang Luo <luoyonggang@gmail.com>
Acked-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27246>
This commit is contained in:
Marcin Radomski 2024-06-26 15:44:33 +00:00 committed by Marge Bot
parent 048037727f
commit 8847a50a04
2 changed files with 62 additions and 13 deletions

View file

@ -46,6 +46,10 @@
#include "vk_struct_id.h"
#include "vk_util.h"
#if defined(__linux__)
#include <drm_fourcc.h>
#endif
#if defined(__ANDROID__) || defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
@ -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<wsi_image_create_info>(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<VkImageDrmFormatModifierExplicitCreateInfoEXT>(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<VkExternalImageFormatProperties>(pImageFormatProperties);
@ -6723,14 +6744,37 @@ VkResult ResourceTracker::on_vkGetPhysicalDeviceImageFormatProperties2_common(
}
}
#ifdef LINUX_GUEST_BUILD
VkImageDrmFormatModifierExplicitCreateInfoEXT localDrmFormatModifierInfo;
const VkPhysicalDeviceImageDrmFormatModifierInfoEXT* drmFmtMod =
vk_find_struct<VkPhysicalDeviceImageDrmFormatModifierInfoEXT>(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;

View file

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