anv/image: Fix VkExternalMemoryProperties for images (v5)

In vkGetPhysicalDeviceImageFormatProperties2, we advertised support for
VK_IMAGE_TILING_LINEAR and VK_IMAGE_TILING_OPTIMAL for all memory
handles.

However, when importing or exporting an image, there must exist a method
that enables the app and driver to agree on the image's memory layout.
If no method exists, then we should reject image creation.

v2:
  - Reduce copy-paste for Lionel.
v3:
  - Treat tiling LINEAR and DRM_FORMAT_MODIFIER as identical when
    determing compatible memory handles.
  - Improve comments.
v4:
  - Remove DMA_BUF from opaque_fd_only_props.
v5:
  - Minor changes to code style for `if`. (for jekstrand)

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> (v4)
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> (v4)
This commit is contained in:
Chad Versace 2020-08-08 12:59:21 -07:00
parent a2aa56905c
commit 57d416d423
1 changed files with 115 additions and 7 deletions

View File

@ -1151,11 +1151,23 @@ VkResult anv_GetPhysicalDeviceImageFormatProperties(
pImageFormatProperties, NULL);
}
static const VkExternalMemoryProperties prime_fd_props = {
/* If we can handle external, then we can both import and export it. */
.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT,
/* For the moment, let's not support mixing and matching */
/* Supports opaque fd but not dma_buf. */
static const VkExternalMemoryProperties opaque_fd_only_props = {
.externalMemoryFeatures =
VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT,
.exportFromImportedHandleTypes =
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
.compatibleHandleTypes =
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
};
/* Supports opaque fd and dma_buf. */
static const VkExternalMemoryProperties opaque_fd_dma_buf_props = {
.externalMemoryFeatures =
VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT,
.exportFromImportedHandleTypes =
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
@ -1197,6 +1209,7 @@ VkResult anv_GetPhysicalDeviceImageFormatProperties2(
VkImageFormatProperties2* base_props)
{
ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
struct anv_instance *instance = physical_device->instance;
const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
VkExternalImageFormatProperties *external_props = NULL;
VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
@ -1263,17 +1276,112 @@ VkResult anv_GetPhysicalDeviceImageFormatProperties2(
* present and VkExternalImageFormatProperties will be ignored.
*/
if (external_info && external_info->handleType != 0) {
/* Does there exist a method for app and driver to explicitly communicate
* to each other the image's memory layout?
*/
bool tiling_has_explicit_layout;
switch (base_info->tiling) {
default:
unreachable("bad VkImageTiling");
case VK_IMAGE_TILING_LINEAR:
/* The app can query the image's memory layout with
* vkGetImageSubresourceLayout.
*/
tiling_has_explicit_layout = true;
break;
case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT:
/* The app can provide the image's memory layout with
* VkImageDrmFormatModifierExplicitCreateInfoEXT;
* or the app can query it with vkGetImageSubresourceLayout.
*/
tiling_has_explicit_layout = true;
break;
case VK_IMAGE_TILING_OPTIMAL:
/* The app can neither query nor provide the image's memory layout. */
tiling_has_explicit_layout = false;
break;
}
/* Compatibility between tiling and external memory handles
* --------------------------------------------------------
* When importing or exporting an image, there must exist a method that
* enables the app and driver to agree on the image's memory layout. If no
* method exists, then we reject image creation here.
*
* If the memory handle requires matching
* VkPhysicalDeviceIDPropertiesKHR::driverUUID and ::deviceUUID, then the
* match-requirement guarantees that all users of the image agree on the
* image's memory layout.
*
* If the memory handle does not require matching
* VkPhysicalDeviceIDPropertiesKHR::driverUUID nor ::deviceUUID, then we
* require that the app and driver be able to explicitly communicate to
* each other the image's memory layout.
*
* (For restrictions on driverUUID and deviceUUID, see the Vulkan 1.2.149
* spec, Table 73 "External memory handle types").
*/
switch (external_info->handleType) {
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
if (external_props) {
if (tiling_has_explicit_layout) {
/* With an explicit memory layout, we don't care which type of fd
* the image belongs too. Both OPAQUE_FD and DMA_BUF are
* interchangeable here.
*/
external_props->externalMemoryProperties = opaque_fd_dma_buf_props;
} else {
/* With an implicit memory layout, we must rely on deviceUUID
* and driverUUID to determine the layout. Therefore DMA_BUF is
* incompatible here.
*/
external_props->externalMemoryProperties = opaque_fd_only_props;
}
}
break;
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
/* This memory handle has no restrictions on driverUUID nor deviceUUID,
* and therefore requires explicit memory layout.
*/
if (!tiling_has_explicit_layout) {
result = vk_errorfi(instance, physical_device,
VK_ERROR_FORMAT_NOT_SUPPORTED,
"VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT "
"requires VK_IMAGE_TILING_LINEAR or "
"VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT");
goto fail;
}
/* With an explicit memory layout, we don't care which type of fd
* the image belongs too. Both OPAQUE_FD and DMA_BUF are
* interchangeable here.
*/
if (external_props)
external_props->externalMemoryProperties = prime_fd_props;
external_props->externalMemoryProperties = opaque_fd_dma_buf_props;
break;
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
/* This memory handle has no restrictions on driverUUID nor deviceUUID,
* and therefore requires explicit memory layout.
*/
if (!tiling_has_explicit_layout) {
result = vk_errorfi(instance, physical_device,
VK_ERROR_FORMAT_NOT_SUPPORTED,
"VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT "
"requires VK_IMAGE_TILING_LINEAR or "
"VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT");
goto fail;
}
if (external_props)
external_props->externalMemoryProperties = userptr_props;
break;
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
/* This memory handle is magic. The Vulkan spec says it has no
* requirements regarding deviceUUID nor driverUUID, but Android still
* requires support for VK_IMAGE_TILING_OPTIMAL. Android systems
* communicate the image's memory layout through backdoor channels.
*/
if (ahw_supported && external_props) {
external_props->externalMemoryProperties = android_image_props;
break;
@ -1361,7 +1469,7 @@ void anv_GetPhysicalDeviceExternalBufferProperties(
switch (pExternalBufferInfo->handleType) {
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
pExternalBufferProperties->externalMemoryProperties = prime_fd_props;
pExternalBufferProperties->externalMemoryProperties = opaque_fd_dma_buf_props;
return;
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
pExternalBufferProperties->externalMemoryProperties = userptr_props;