[Mesa-dev] [PATCH 08/15] anv/android: support import/export of AHardwareBuffer objects

Tapani Pälli tapani.palli at intel.com
Wed Dec 12 08:34:13 UTC 2018



On 12/11/18 3:05 PM, Lionel Landwerlin wrote:
> On 27/11/2018 10:53, Tapani Pälli wrote:
>> v2: add support for non-image buffers (AHARDWAREBUFFER_FORMAT_BLOB)
>> v3: properly handle usage bits when creating from image
>> v4: refactor, code cleanup (Jason)
>> v5: rebase to b43f955037c changes,
>>      initialize bo flags as ANV_BO_EXTERNAL (Lionel)
>>
>> Signed-off-by: Tapani Pälli <tapani.palli at intel.com>
> 
> 
> Just a couple of suggestions below, otherwise :
> 
> 
> Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
> 
> 
>> ---
>>   src/intel/vulkan/anv_android.c       | 123 +++++++++++++++++++++++++++
>>   src/intel/vulkan/anv_android.h       |  10 +++
>>   src/intel/vulkan/anv_android_stubs.c |  16 ++++
>>   src/intel/vulkan/anv_device.c        |  45 +++++++++-
>>   src/intel/vulkan/anv_private.h       |   5 ++
>>   5 files changed, 197 insertions(+), 2 deletions(-)
>>
>> diff --git a/src/intel/vulkan/anv_android.c 
>> b/src/intel/vulkan/anv_android.c
>> index f2dd16212c1..bdc720214c4 100644
>> --- a/src/intel/vulkan/anv_android.c
>> +++ b/src/intel/vulkan/anv_android.c
>> @@ -233,6 +233,129 @@ anv_ahw_usage_from_vk_usage(const 
>> VkImageCreateFlags vk_create,
>>      return ahw_usage;
>>   }
>> +VkResult
>> +anv_GetMemoryAndroidHardwareBufferANDROID(
>> +   VkDevice device_h,
>> +   const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo,
>> +   struct AHardwareBuffer **pBuffer)
>> +{
>> +   ANV_FROM_HANDLE(anv_device_memory, mem, pInfo->memory);
>> +
>> +   /* Some quotes from Vulkan spec:
>> +    *
>> +    * "If the device memory was created by importing an Android hardware
>> +    * buffer, vkGetMemoryAndroidHardwareBufferANDROID must return 
>> that same
>> +    * Android hardware buffer object."
>> +    *
>> +    * 
>> "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID must
>> +    * have been included in 
>> VkExportMemoryAllocateInfoKHR::handleTypes when
>> +    * memory was created."
>> +    */
>> +   if (mem->ahw) {
>> +      *pBuffer = mem->ahw;
>> +      /* Increase refcount. */
>> +      AHardwareBuffer_acquire(mem->ahw);
>> +      return VK_SUCCESS;
>> +   }
>> +
>> +   return VK_ERROR_OUT_OF_HOST_MEMORY;
>> +}
>> +
>> +/*
>> + * Called from anv_AllocateMemory when import AHardwareBuffer.
>> + */
>> +VkResult
>> +anv_import_ahw_memory(VkDevice device_h,
>> +                      struct anv_device_memory *mem,
>> +                      const VkImportAndroidHardwareBufferInfoANDROID 
>> *info)
>> +{
>> +   ANV_FROM_HANDLE(anv_device, device, device_h);
>> +
>> +   /* Import from AHardwareBuffer to anv_device_memory. */
>> +   const native_handle_t *handle =
>> +      AHardwareBuffer_getNativeHandle(info->buffer);
>> +
>> +   int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
> 
> 
> Maybe assert(handle->numFds == 1) so we don't forget to update this when 
> we add support for multiple BOs later.

Perhaps I should have added some comment or warning here ... I'm 
actually letting in buffers with multiple fds now because thing is that 
we do get 2 fds with 'HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL' as we have 2 
logical planes but really just one buffer (both point to the same). I 
was considering to add some special case/check for that but maybe just a 
comment for now?


> 
>> +   if (dma_buf < 0)
>> +      return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR;
>> +
>> +   uint64_t bo_flags = ANV_BO_EXTERNAL;
>> +   if (device->instance->physicalDevice.supports_48bit_addresses)
>> +      bo_flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
>> +   if (device->instance->physicalDevice.use_softpin)
>> +      bo_flags |= EXEC_OBJECT_PINNED;
>> +
>> +   VkResult result = anv_bo_cache_import(device, &device->bo_cache,
>> +                                dma_buf, bo_flags, &mem->bo);
>> +   if (result != VK_SUCCESS)
>> +      return result;
>> +
>> +   /* "If the vkAllocateMemory command succeeds, the implementation must
>> +    * acquire a reference to the imported hardware buffer, which it must
>> +    * release when the device memory object is freed. If the command 
>> fails,
>> +    * the implementation must not retain a reference."
>> +    */
>> +   AHardwareBuffer_acquire(info->buffer);
>> +   mem->ahw = info->buffer;
>> +
>> +   return VK_SUCCESS;
>> +}
>> +
>> +VkResult
>> +anv_create_ahw_memory(VkDevice device_h,
>> +                      struct anv_device_memory *mem,
>> +                      const VkMemoryAllocateInfo *pAllocateInfo)
>> +{
>> +   ANV_FROM_HANDLE(anv_device, dev, device_h);
>> +
>> +   const VkMemoryDedicatedAllocateInfo *dedicated_info =
>> +      vk_find_struct_const(pAllocateInfo->pNext,
>> +                           MEMORY_DEDICATED_ALLOCATE_INFO);
>> +
>> +   uint32_t w = 0;
>> +   uint32_t h = 1;
>> +   uint32_t layers = 1;
>> +   uint32_t format = 0;
>> +   uint64_t usage = 0;
>> +
>> +   /* If caller passed dedicated information. */
>> +   if (dedicated_info && dedicated_info->image) {
>> +      ANV_FROM_HANDLE(anv_image, image, dedicated_info->image);
>> +      w = image->extent.width;
>> +      h = image->extent.height;
>> +      layers = image->array_size;
>> +      format = android_format_from_vk(image->vk_format);
>> +      usage = anv_ahw_usage_from_vk_usage(image->create_flags, 
>> image->usage);
>> +   } else if (dedicated_info && dedicated_info->buffer) {
>> +      ANV_FROM_HANDLE(anv_buffer, buffer, dedicated_info->buffer);
>> +      w = buffer->size;
>> +      format = AHARDWAREBUFFER_FORMAT_BLOB;
>> +      usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
>> +              AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
>> +   } else {
>> +      w = pAllocateInfo->allocationSize;
>> +      format = AHARDWAREBUFFER_FORMAT_BLOB;
>> +      usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
>> +              AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
>> +   }
>> +
>> +   struct AHardwareBuffer *ahw = NULL;
>> +   struct AHardwareBuffer_Desc desc = {
>> +      .width = w,
>> +      .height = h,
>> +      .layers = layers,
>> +      .format = format,
>> +      .usage = usage,
>> +    };
>> +
>> +   if (AHardwareBuffer_allocate(&desc, &ahw) != 0)
>> +      return VK_ERROR_OUT_OF_HOST_MEMORY;
>> +
>> +   mem->ahw = ahw;
>> +
>> +   return VK_SUCCESS;
>> +}
>> +
>>   VkResult
>>   anv_image_from_gralloc(VkDevice device_h,
>>                          const VkImageCreateInfo *base_info,
>> diff --git a/src/intel/vulkan/anv_android.h 
>> b/src/intel/vulkan/anv_android.h
>> index 8d748cecc39..01f0e856291 100644
>> --- a/src/intel/vulkan/anv_android.h
>> +++ b/src/intel/vulkan/anv_android.h
>> @@ -28,6 +28,8 @@
>>   #include <vulkan/vulkan_android.h>
>>   #include <vulkan/vk_android_native_buffer.h>
>> +struct anv_device_memory;
>> +
>>   VkResult anv_image_from_gralloc(VkDevice device_h,
>>                                   const VkImageCreateInfo *base_info,
>>                                   const VkNativeBufferANDROID 
>> *gralloc_info,
>> @@ -36,4 +38,12 @@ VkResult anv_image_from_gralloc(VkDevice device_h,
>>   uint64_t anv_ahw_usage_from_vk_usage(const VkImageCreateFlags 
>> vk_create,
>>                                        const VkImageUsageFlags vk_usage);
>> +
>> +VkResult anv_import_ahw_memory(VkDevice device_h,
>> +                               struct anv_device_memory *mem,
>> +                               const 
>> VkImportAndroidHardwareBufferInfoANDROID *info);
>> +
>> +VkResult anv_create_ahw_memory(VkDevice device_h,
>> +                               struct anv_device_memory *mem,
>> +                               const VkMemoryAllocateInfo 
>> *pAllocateInfo);
>>   #endif /* ANV_ANDROID_H */
>> diff --git a/src/intel/vulkan/anv_android_stubs.c 
>> b/src/intel/vulkan/anv_android_stubs.c
>> index 0671d5635ee..ccc16500494 100644
>> --- a/src/intel/vulkan/anv_android_stubs.c
>> +++ b/src/intel/vulkan/anv_android_stubs.c
>> @@ -39,3 +39,19 @@ anv_ahw_usage_from_vk_usage(const 
>> VkImageCreateFlags vk_create,
>>   {
>>      return 0;
>>   }
>> +
>> +VkResult
>> +anv_import_ahw_memory(VkDevice device_h,
>> +                      struct anv_device_memory *mem,
>> +                      const VkImportAndroidHardwareBufferInfoANDROID 
>> *info)
>> +{
>> +   return VK_ERROR_EXTENSION_NOT_PRESENT;
>> +}
>> +
>> +VkResult
>> +anv_create_ahw_memory(VkDevice device_h,
>> +                      struct anv_device_memory *mem,
>> +                      const VkMemoryAllocateInfo *pAllocateInfo)
>> +{
>> +   return VK_ERROR_EXTENSION_NOT_PRESENT;
>> +}
>> diff --git a/src/intel/vulkan/anv_device.c 
>> b/src/intel/vulkan/anv_device.c
>> index 0cbbaeca3b3..a1ee9315956 100644
>> --- a/src/intel/vulkan/anv_device.c
>> +++ b/src/intel/vulkan/anv_device.c
>> @@ -2268,6 +2268,7 @@ VkResult anv_AllocateMemory(
>>      mem->type = &pdevice->memory.types[pAllocateInfo->memoryTypeIndex];
>>      mem->map = NULL;
>>      mem->map_size = 0;
>> +   mem->ahw = NULL;
>>      uint64_t bo_flags = 0;
>> @@ -2290,6 +2291,43 @@ VkResult anv_AllocateMemory(
>>      if (pdevice->use_softpin)
>>         bo_flags |= EXEC_OBJECT_PINNED;
>> +   const VkExportMemoryAllocateInfo *export_info =
>> +      vk_find_struct_const(pAllocateInfo->pNext, 
>> EXPORT_MEMORY_ALLOCATE_INFO);
>> +
>> +   /* Check if we need to support Android HW buffer export. If so,
>> +    * create AHardwareBuffer and import memory from it.
>> +    */
>> +   bool android_export = false;
>> +   if (export_info && export_info->handleTypes &
>> +       
>> VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
>> +      android_export = true;
>> +
>> +   /* Android memory import. */
>> +   const struct VkImportAndroidHardwareBufferInfoANDROID 
>> *ahw_import_info =
>> +      vk_find_struct_const(pAllocateInfo->pNext,
>> +                           IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID);
>> +
>> +   if (ahw_import_info) {
>> +      result = anv_import_ahw_memory(_device, mem, ahw_import_info);
>> +      if (result != VK_SUCCESS)
>> +         goto fail;
>> +
>> +      goto success;
>> +   } else if (android_export) {
>> +      result = anv_create_ahw_memory(_device, mem, pAllocateInfo);
>> +      if (result != VK_SUCCESS)
>> +         goto fail;
>> +
>> +      const struct VkImportAndroidHardwareBufferInfoANDROID 
>> import_info = {
>> +         .buffer = mem->ahw,
>> +      };
>> +      result = anv_import_ahw_memory(_device, mem, &import_info);
>> +      if (result != VK_SUCCESS)
>> +         goto fail;
> 
> 
> I wonder if we can ever fail importing the buffer we've just allocated.
> 
> If we do, then we might need to free the buffer before exiting, 
> otherwise just assert(result == VK_SUCCESS); ?

In theory we shouldn't fail .. I'll add assert here!

> 
> 
>> +
>> +      goto success;
>> +   }
>> +
>>      const VkImportMemoryFdInfoKHR *fd_info =
>>         vk_find_struct_const(pAllocateInfo->pNext, 
>> IMPORT_MEMORY_FD_INFO_KHR);
>> @@ -2345,8 +2383,6 @@ VkResult anv_AllocateMemory(
>>      /* Regular allocate (not importing memory). */
>> -   const VkExportMemoryAllocateInfoKHR *export_info =
>> -      vk_find_struct_const(pAllocateInfo->pNext, 
>> EXPORT_MEMORY_ALLOCATE_INFO_KHR);
>>      if (export_info && export_info->handleTypes)
>>         bo_flags |= ANV_BO_EXTERNAL;
>> @@ -2450,6 +2486,11 @@ void anv_FreeMemory(
>>      anv_bo_cache_release(device, &device->bo_cache, mem->bo);
>> +#ifdef ANDROID
>> +   if (mem->ahw)
>> +      AHardwareBuffer_release(mem->ahw);
>> +#endif
>> +
>>      vk_free2(&device->alloc, pAllocator, mem);
>>   }
>> diff --git a/src/intel/vulkan/anv_private.h 
>> b/src/intel/vulkan/anv_private.h
>> index c855f9e4b0d..bd899dcb828 100644
>> --- a/src/intel/vulkan/anv_private.h
>> +++ b/src/intel/vulkan/anv_private.h
>> @@ -1413,6 +1413,11 @@ struct anv_device_memory {
>>      struct anv_memory_type *                     type;
>>      VkDeviceSize                                 map_size;
>>      void *                                       map;
>> +
>> +   /* If set, we are holding reference to AHardwareBuffer
>> +    * which we must release when memory is freed.
>> +    */
>> +   struct AHardwareBuffer *                     ahw;
>>   };
>>   /**
> 
> 


More information about the mesa-dev mailing list