[Mesa-dev] [PATCH 08/15] anv/android: support import/export of AHardwareBuffer objects
Lionel Landwerlin
lionel.g.landwerlin at intel.com
Tue Nov 6 10:07:49 UTC 2018
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?
> 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