[Mesa-dev] [PATCH 3/3] radv: Implement VK_KHR_external_memory

Jason Ekstrand jason at jlekstrand.net
Sat Jul 15 04:50:51 UTC 2017


On Fri, Jul 14, 2017 at 5:08 PM, Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
wrote:

> From: Jason Ekstrand <jason at jlekstrand.net>
>
> This effectively reverts commit 43a171878bb4b5aedb36a.  Technically,
> VK_KHR_get_memory_requirements2 and VK_KHR_dedicated_allocation are
> required for the KHR version but this at least restores the removed
> functionality.  This patch builds but has received zero testing.
>
> Cc: Dave Airlie <airlied at redhat.com>
> (Bas: added plumbing for the dedicated allocation)
>

Those bits look good to me for what it's worth.


> ---
>  src/amd/vulkan/radv_device.c           |  74 +++++++++++++++++++++-
>  src/amd/vulkan/radv_entrypoints_gen.py |   3 +
>  src/amd/vulkan/radv_formats.c          | 112
> +++++++++++++++++++++++++++++++++
>  src/amd/vulkan/radv_image.c            |  11 +++-
>  src/amd/vulkan/radv_private.h          |   2 +
>  5 files changed, 199 insertions(+), 3 deletions(-)
>
> diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
> index 59c4ea8448e..630f35ff7a8 100644
> --- a/src/amd/vulkan/radv_device.c
> +++ b/src/amd/vulkan/radv_device.c
> @@ -98,6 +98,10 @@ static const VkExtensionProperties
> instance_extensions[] = {
>                 .extensionName = VK_KHR_GET_PHYSICAL_DEVICE_
> PROPERTIES_2_EXTENSION_NAME,
>                 .specVersion = 1,
>         },
> +       {
> +               .extensionName = VK_KHR_EXTERNAL_MEMORY_
> CAPABILITIES_EXTENSION_NAME,
> +               .specVersion = 1,
> +       },
>  };
>
>  static const VkExtensionProperties common_device_extensions[] = {
> @@ -145,6 +149,14 @@ static const VkExtensionProperties
> common_device_extensions[] = {
>                 .extensionName = VK_KHR_DEDICATED_ALLOCATION_
> EXTENSION_NAME,
>                 .specVersion = 1,
>         },
> +       {
> +               .extensionName = VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
> +               .specVersion = 1,
> +       },
> +       {
> +               .extensionName = VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
> +               .specVersion = 1,
> +       },
>  };
>
>  static VkResult
> @@ -731,6 +743,7 @@ void radv_GetPhysicalDeviceProperties2KHR(
>         VkPhysicalDevice                            physicalDevice,
>         VkPhysicalDeviceProperties2KHR             *pProperties)
>  {
> +       RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice);
>         radv_GetPhysicalDeviceProperties(physicalDevice,
> &pProperties->properties);
>
>         vk_foreach_struct(ext, pProperties->pNext) {
> @@ -741,6 +754,13 @@ void radv_GetPhysicalDeviceProperties2KHR(
>                         properties->maxPushDescriptors =
> MAX_PUSH_DESCRIPTORS;
>                         break;
>                 }
> +               case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR:
> {
> +                       VkPhysicalDeviceIDPropertiesKHR *properties = (
> VkPhysicalDeviceIDPropertiesKHR*)ext;
> +                       radv_device_get_cache_uuid(0,
> properties->driverUUID);
> +                       memcpy(properties->deviceUUID,
> pdevice->device_uuid, VK_UUID_SIZE);
> +                       properties->deviceLUIDValid = false;
> +                       break;
> +               }
>                 default:
>                         break;
>                 }
> @@ -2076,6 +2096,9 @@ VkResult radv_AllocateMemory(
>                 *pMem = VK_NULL_HANDLE;
>                 return VK_SUCCESS;
>         }
> +
> +       const VkImportMemoryFdInfoKHR *import_info =
> +               vk_find_struct_const(pAllocateInfo->pNext,
> IMPORT_MEMORY_FD_INFO_KHR);
>         const VkMemoryDedicatedAllocateInfoKHR *dedicate_info =
>                 vk_find_struct_const(pAllocateInfo->pNext,
> MEMORY_DEDICATED_ALLOCATE_INFO_KHR);
>
> @@ -2092,6 +2115,18 @@ VkResult radv_AllocateMemory(
>                 mem->buffer = NULL;
>         }
>
> +       if (import_info) {
> +               assert(import_info->handleType ==
> +                      VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR);
> +               mem->bo = device->ws->buffer_from_fd(device->ws,
> import_info->fd,
> +                                                    NULL, NULL);
> +               if (!mem->bo) {
> +                       result = VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR;
> +                       goto fail;
> +               } else
> +                       goto out_success;
> +       }
> +
>         uint64_t alloc_size = align_u64(pAllocateInfo->allocationSize,
> 4096);
>         if (pAllocateInfo->memoryTypeIndex == RADV_MEM_TYPE_GTT_WRITE_COMBINE
> ||
>             pAllocateInfo->memoryTypeIndex == RADV_MEM_TYPE_GTT_CACHED)
> @@ -2115,7 +2150,7 @@ VkResult radv_AllocateMemory(
>                 goto fail;
>         }
>         mem->type_index = pAllocateInfo->memoryTypeIndex;
> -
> +out_success:
>         *pMem = radv_device_memory_to_handle(mem);
>
>         return VK_SUCCESS;
> @@ -2258,12 +2293,14 @@ void radv_GetImageMemoryRequirements2KHR(
>         radv_GetImageMemoryRequirements(device, pInfo->image,
>                                          &pMemoryRequirements->
> memoryRequirements);
>
> +       RADV_FROM_HANDLE(radv_image, image, pInfo->image);
> +
>         vk_foreach_struct(ext, pMemoryRequirements->pNext) {
>                 switch (ext->sType) {
>                 case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR:
> {
>                         VkMemoryDedicatedRequirementsKHR *req =
>                                        (VkMemoryDedicatedRequirementsKHR
> *) ext;
> -                       req->requiresDedicatedAllocation = false;
> +                       req->requiresDedicatedAllocation =
> image->shareable;
>                         req->prefersDedicatedAllocation = req->
> requiresDedicatedAllocation;
>                         break;
>                 }
> @@ -3318,3 +3355,36 @@ vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t
> *pSupportedVersion)
>         *pSupportedVersion = MIN2(*pSupportedVersion, 3u);
>         return VK_SUCCESS;
>  }
> +
> +VkResult radv_GetMemoryFdKHR(VkDevice _device,
> +                            const VkMemoryGetFdInfoKHR *pGetFdInfo,
> +                            int *pFD)
> +{
> +       RADV_FROM_HANDLE(radv_device, device, _device);
> +       RADV_FROM_HANDLE(radv_device_memory, memory, pGetFdInfo->memory);
> +
> +       assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_
> FD_INFO_KHR);
> +
> +       /* We support only one handle type. */
> +       assert(pGetFdInfo->handleType ==
> +              VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR);
> +
> +       bool ret = radv_get_memory_fd(device, memory, pFD);
> +       if (ret == false)
> +               return VK_ERROR_OUT_OF_DEVICE_MEMORY;
> +       return VK_SUCCESS;
> +}
> +
> +VkResult radv_GetMemoryFdPropertiesKHR(VkDevice _device,
> +                                      VkExternalMemoryHandleTypeFlagBitsKHR
> handleType,
> +                                      int fd,
> +                                      VkMemoryFdPropertiesKHR
> *pMemoryFdProperties)
> +{
> +   /* The valid usage section for this function says:
> +    *
> +    *    "handleType must not be one of the handle types defined as
> opaque."
> +    *
> +    * Since we only handle opaque handles for now, there are no FD
> properties.
> +    */
> +   return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR;
> +}
> diff --git a/src/amd/vulkan/radv_entrypoints_gen.py b/src/amd/vulkan/radv_
> entrypoints_gen.py
> index d305a07e7d7..22068a5b02d 100644
> --- a/src/amd/vulkan/radv_entrypoints_gen.py
> +++ b/src/amd/vulkan/radv_entrypoints_gen.py
> @@ -44,6 +44,9 @@ supported_extensions = [
>     'VK_KHR_xlib_surface',
>     'VK_KHR_get_memory_requirements2',
>     'VK_KHR_dedicated_allocation',
> +   'VK_KHR_external_memory_capabilities',
> +   'VK_KHR_external_memory',
> +   'VK_KHR_external_memory_fd',
>  ]
>
>  # We generate a static hash table for entry point lookup
> diff --git a/src/amd/vulkan/radv_formats.c b/src/amd/vulkan/radv_formats.c
> index b740a1a5d9b..4d0aca1490d 100644
> --- a/src/amd/vulkan/radv_formats.c
> +++ b/src/amd/vulkan/radv_formats.c
> @@ -1142,12 +1142,37 @@ VkResult radv_GetPhysicalDeviceImageFormatPr
> operties(
>                                                 pImageFormatProperties);
>  }
>
> +static void
> +get_external_image_format_properties(const VkPhysicalDeviceImageFormatInfo2KHR
> *pImageFormatInfo,
> +                                    VkExternalMemoryPropertiesKHR
> *external_properties)
> +{
> +       VkExternalMemoryFeatureFlagBitsKHR flags = 0;
> +       VkExternalMemoryHandleTypeFlagsKHR export_flags = 0;
> +       VkExternalMemoryHandleTypeFlagsKHR compat_flags = 0;
> +       switch (pImageFormatInfo->type) {
> +       case VK_IMAGE_TYPE_2D:
> +               flags = VK_EXTERNAL_MEMORY_FEATURE_
> DEDICATED_ONLY_BIT_KHR|VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR|VK_
> EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR;
> +               compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_
> TYPE_OPAQUE_FD_BIT_KHR;
> +               break;
> +       default:
> +               break;
> +       }
> +
> +       *external_properties = (VkExternalMemoryPropertiesKHR) {
> +               .externalMemoryFeatures = flags,
> +               .exportFromImportedHandleTypes = export_flags,
> +               .compatibleHandleTypes = compat_flags,
> +       };
> +}
> +
>  VkResult radv_GetPhysicalDeviceImageFormatProperties2KHR(
>         VkPhysicalDevice                            physicalDevice,
>         const VkPhysicalDeviceImageFormatInfo2KHR  *base_info,
>         VkImageFormatProperties2KHR                *base_props)
>  {
>         RADV_FROM_HANDLE(radv_physical_device, physical_device,
> physicalDevice);
> +       const VkPhysicalDeviceExternalImageFormatInfoKHR *external_info =
> NULL;
> +       VkExternalImageFormatPropertiesKHR *external_props = NULL;
>         VkResult result;
>
>         result = radv_get_image_format_properties(physical_device,
> base_info,
> @@ -1155,7 +1180,69 @@ VkResult radv_GetPhysicalDeviceImageFormatPr
> operties2KHR(
>         if (result != VK_SUCCESS)
>                 return result;
>
> +          /* Extract input structs */
> +       vk_foreach_struct_const(s, base_info->pNext) {
> +               switch (s->sType) {
> +               case VK_STRUCTURE_TYPE_PHYSICAL_
> DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR:
> +                       external_info = (const void *) s;
> +                       break;
> +               default:
> +                       break;
> +               }
> +       }
> +
> +       /* Extract output structs */
> +       vk_foreach_struct(s, base_props->pNext) {
> +               switch (s->sType) {
> +               case VK_STRUCTURE_TYPE_EXTERNAL_
> IMAGE_FORMAT_PROPERTIES_KHR:
> +                       external_props = (void *) s;
> +                       break;
> +               default:
> +                       break;
> +               }
> +       }
> +
> +       /* From the Vulkan 1.0.42 spec:
> +        *
> +        *    If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2KHR
> will
> +        *    behave as if VkPhysicalDeviceExternalImageFormatInfoKHR was
> not
> +        *    present and VkExternalImageFormatPropertiesKHR will be
> ignored.
> +        */
> +       if (external_info && external_info->handleType != 0) {
> +               switch (external_info->handleType) {
> +               case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
> +                       get_external_image_format_properties(base_info,
> &external_props->externalMemoryProperties);
> +                       break;
> +               default:
> +                       /* From the Vulkan 1.0.42 spec:
> +                        *
> +                        *    If handleType is not compatible with the
> [parameters] specified
> +                        *    in VkPhysicalDeviceImageFormatInfo2KHR, then
> +                        *    vkGetPhysicalDeviceImageFormatProperties2KHR
> returns
> +                        *    VK_ERROR_FORMAT_NOT_SUPPORTED.
> +                        */
> +                       result = vk_errorf(VK_ERROR_FORMAT_NOT_SUPPORTED,
> +                                          "unsupported
> VkExternalMemoryTypeFlagBitsKHR 0x%x",
> +                                          external_info->handleType);
> +                       goto fail;
> +               }
> +       }
> +
>         return VK_SUCCESS;
> +
> +fail:
> +       if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
> +               /* From the Vulkan 1.0.42 spec:
> +                *
> +                *    If the combination of parameters to
> +                *    vkGetPhysicalDeviceImageFormatProperties2KHR is not
> supported by
> +                *    the implementation for use in vkCreateImage, then
> all members of
> +                *    imageFormatProperties will be filled with zero.
> +                */
> +               base_props->imageFormatProperties =
> (VkImageFormatProperties) {0};
> +       }
> +
> +       return result;
>  }
>
>  void radv_GetPhysicalDeviceSparseImageFormatProperties(
> @@ -1181,3 +1268,28 @@ void radv_GetPhysicalDeviceSparseImageFo
> rmatProperties2KHR(
>         /* Sparse images are not yet supported. */
>         *pPropertyCount = 0;
>  }
> +
> +void radv_GetPhysicalDeviceExternalBufferPropertiesKHR(
> +       VkPhysicalDevice                            physicalDevice,
> +       const VkPhysicalDeviceExternalBufferInfoKHR *pExternalBufferInfo,
> +       VkExternalBufferPropertiesKHR
>  *pExternalBufferProperties)
> +{
> +       VkExternalMemoryFeatureFlagBitsKHR flags = 0;
> +       VkExternalMemoryHandleTypeFlagsKHR export_flags = 0;
> +       VkExternalMemoryHandleTypeFlagsKHR compat_flags = 0;
> +       switch(pExternalBufferInfo->handleType) {
> +       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
> +               flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR
> |
> +                       VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR |
> +                       VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR;
> +               compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_
> TYPE_OPAQUE_FD_BIT_KHR;
> +               break;
> +       default:
> +               break;
> +       }
> +       pExternalBufferProperties->externalMemoryProperties = (VkExternalMemoryPropertiesKHR)
> {
> +               .externalMemoryFeatures = flags,
> +               .exportFromImportedHandleTypes = export_flags,
> +               .compatibleHandleTypes = compat_flags,
> +       };
> +}
> diff --git a/src/amd/vulkan/radv_image.c b/src/amd/vulkan/radv_image.c
> index fc00d019d1d..17ee74b5f5b 100644
> --- a/src/amd/vulkan/radv_image.c
> +++ b/src/amd/vulkan/radv_image.c
> @@ -27,6 +27,7 @@
>
>  #include "radv_private.h"
>  #include "vk_format.h"
> +#include "vk_util.h"
>  #include "radv_radeon_winsys.h"
>  #include "sid.h"
>  #include "gfx9d.h"
> @@ -783,9 +784,15 @@ radv_image_create(VkDevice _device,
>         image->exclusive = pCreateInfo->sharingMode ==
> VK_SHARING_MODE_EXCLUSIVE;
>         if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
>                 for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount;
> ++i)
> -                       image->queue_family_mask |= 1u << pCreateInfo->
> pQueueFamilyIndices[i];
> +                       if (pCreateInfo->pQueueFamilyIndices[i] ==
> VK_QUEUE_FAMILY_EXTERNAL_KHR)
> +                               image->queue_family_mask |= (1u <<
> RADV_MAX_QUEUE_FAMILIES) - 1u;
> +                       else
> +                               image->queue_family_mask |= 1u <<
> pCreateInfo->pQueueFamilyIndices[i];
>         }
>
> +       image->shareable = vk_find_struct_const(pCreateInfo->pNext,
> +
>  EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR) != NULL;
> +
>         radv_init_surface(device, &image->surface, create_info);
>
>         device->ws->surface_init(device->ws, &image->info,
> &image->surface);
> @@ -962,6 +969,8 @@ unsigned radv_image_queue_family_mask(const struct
> radv_image *image, uint32_t f
>  {
>         if (!image->exclusive)
>                 return image->queue_family_mask;
> +       if (family == VK_QUEUE_FAMILY_EXTERNAL_KHR)
> +               return (1u << RADV_MAX_QUEUE_FAMILIES) - 1u;
>         if (family == VK_QUEUE_FAMILY_IGNORED)
>                 return 1u << queue_family;
>         return 1u << family;
> diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
> index a8bc5c96586..2f633b4dbd9 100644
> --- a/src/amd/vulkan/radv_private.h
> +++ b/src/amd/vulkan/radv_private.h
> @@ -1205,6 +1205,8 @@ struct radv_image {
>         bool exclusive;
>         unsigned queue_family_mask;
>
> +       bool shareable;
> +
>         /* Set when bound */
>         struct radeon_winsys_bo *bo;
>         VkDeviceSize offset;
> --
> 2.13.2
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170714/6b31327c/attachment-0001.html>


More information about the mesa-dev mailing list