[Mesa-dev] [PATCH 08/15] anv/android: support import/export of AHardwareBuffer objects
Tapani Pälli
tapani.palli at intel.com
Tue Nov 6 12:42:50 UTC 2018
On 11/6/18 12:07 PM, Lionel Landwerlin wrote:
> On 30/10/2018 05:26, 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)
>>
>> Signed-off-by: Tapani Pälli <tapani.palli at intel.com>
>> ---
>> src/intel/vulkan/anv_android.c | 128 +++++++++++++++++++++++++++++++++
>> src/intel/vulkan/anv_device.c | 47 +++++++++++-
>> src/intel/vulkan/anv_private.h | 18 +++++
>> 3 files changed, 191 insertions(+), 2 deletions(-)
>>
>> diff --git a/src/intel/vulkan/anv_android.c
>> b/src/intel/vulkan/anv_android.c
>> index d0a20dd85c5..42fa050af93 100644
>> --- a/src/intel/vulkan/anv_android.c
>> +++ b/src/intel/vulkan/anv_android.c
>> @@ -232,6 +232,134 @@ 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_INVALID_EXTERNAL_HANDLE_KHR;
>> +}
>> +
>> +/*
>> + * 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);
>> +
>> + /* Get a description of buffer contents. */
>> + AHardwareBuffer_Desc desc;
>> + AHardwareBuffer_describe(info->buffer, &desc);
>> + VkResult result = VK_SUCCESS;
>> +
>> + /* 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;
>> + if (dma_buf < 0)
>> + return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR;
>> +
>> + uint64_t bo_flags = 0;
>> + 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;
>> +
>> + 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 result;
>> +}
>> +
>> +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_device.c
>> b/src/intel/vulkan/anv_device.c
>> index 383182312e2..37f923ab3d0 100644
>> --- a/src/intel/vulkan/anv_device.c
>> +++ b/src/intel/vulkan/anv_device.c
>> @@ -2261,6 +2261,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;
>> @@ -2283,6 +2284,44 @@ 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);
>> +
>> +#ifdef ANDROID
>> + /* 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;
>> +
>> + goto success;
>> + }
>> +#else
>
>
> Did you really meant to disable VK_KHR_external_memory_fd on Android?
>
Yeah that was conscious as it's not used on Android but now I realized
it's being exposed currently so I probably should just leave it as is.
Will put #endif here instead of #else.
>> const VkImportMemoryFdInfoKHR *fd_info =
>> vk_find_struct_const(pAllocateInfo->pNext,
>> IMPORT_MEMORY_FD_INFO_KHR);
>> @@ -2335,11 +2374,10 @@ VkResult anv_AllocateMemory(
>> close(fd_info->fd);
>> goto success;
>> }
>> +#endif
>> /* 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;
>> @@ -2443,6 +2481,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 bec3c457f68..f99e70bfc4f 100644
>> --- a/src/intel/vulkan/anv_private.h
>> +++ b/src/intel/vulkan/anv_private.h
>> @@ -86,6 +86,11 @@ struct gen_l3_config;
>> #include "common/intel_log.h"
>> #include "wsi_common.h"
>> +#ifdef ANDROID
>> +#include <vndk/hardware_buffer.h>
>> +#include "vulkan/vulkan_android.h"
>> +#endif
>> +
>> /* anv Virtual Memory Layout
>> * =========================
>> *
>> @@ -1413,6 +1418,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;
>> };
>> /**
>> @@ -3108,6 +3118,14 @@ VkResult anv_image_from_gralloc(VkDevice device_h,
>> const VkNativeBufferANDROID
>> *gralloc_info,
>> const VkAllocationCallbacks *alloc,
>> VkImage *pImage);
>> +
>> +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);
>> uint64_t
>> anv_ahw_usage_from_vk_usage(const VkImageCreateFlags vk_create,
>> const VkImageUsageFlags vk_usage);
>
>
More information about the mesa-dev
mailing list