[Mesa-dev] [PATCH 08/15] anv/android: support import/export of AHardwareBuffer objects
Lionel Landwerlin
lionel.g.landwerlin at intel.com
Wed Dec 12 10:47:27 UTC 2018
On 12/12/2018 08:34, Tapani Pälli wrote:
>
>
> 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?
I see, where is the offset for each plane?
>
>
>>
>>> + 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