From 83a012b60316c80ab8f4f882338cc797b9bd04ec Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Wed, 10 Jul 2019 14:45:01 +0200 Subject: [PATCH] radv/android: Add android hardware buffer import/export. Support does not include images yet. Reviewed-by: Samuel Pitoiset --- src/amd/vulkan/radv_android.c | 126 ++++++++++++++++++++++++++++++++++ src/amd/vulkan/radv_device.c | 26 +++++-- src/amd/vulkan/radv_private.h | 11 +++ 3 files changed, 156 insertions(+), 7 deletions(-) diff --git a/src/amd/vulkan/radv_android.c b/src/amd/vulkan/radv_android.c index 7833e6d8922..f2fbeab459d 100644 --- a/src/amd/vulkan/radv_android.c +++ b/src/amd/vulkan/radv_android.c @@ -415,6 +415,27 @@ vk_format_from_android(unsigned android_format, unsigned android_usage) } } +static inline unsigned +android_format_from_vk(unsigned vk_format) +{ + switch (vk_format) { + case VK_FORMAT_R8G8B8A8_UNORM: + return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; + case VK_FORMAT_R8G8B8_UNORM: + return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM; + case VK_FORMAT_R5G6B5_UNORM_PACK16: + return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM; + case VK_FORMAT_R16G16B16A16_SFLOAT: + return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT; + case VK_FORMAT_A2B10G10R10_UNORM_PACK32: + return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM; + case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: + return AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420; + default: + return AHARDWAREBUFFER_FORMAT_BLOB; + } +} + uint64_t radv_ahb_usage_from_vk_usage(const VkImageCreateFlags vk_create, const VkImageUsageFlags vk_usage) @@ -599,3 +620,108 @@ radv_select_android_external_format(const void *next, VkFormat default_format) return default_format; } + + +VkResult +radv_import_ahb_memory(struct radv_device *device, + struct radv_device_memory *mem, + unsigned priority, + const VkImportAndroidHardwareBufferInfoANDROID *info) +{ +#if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER + /* Import from AHardwareBuffer to radv_device_memory. */ + const native_handle_t *handle = + AHardwareBuffer_getNativeHandle(info->buffer); + + /* NOTE - We support buffers with only one handle but do not error on + * multiple handle case. Reason is that we want to support YUV formats + * where we have many logical planes but they all point to the same + * buffer, like is the case with VK_FORMAT_G8_B8R8_2PLANE_420_UNORM. + */ + int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1; + if (dma_buf < 0) + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + + mem->bo = device->ws->buffer_from_fd(device->ws, dma_buf, + priority); + if (!mem->bo) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + /* "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->android_hardware_buffer = info->buffer; + + return VK_SUCCESS; +#else /* RADV_SUPPORT_ANDROID_HARDWARE_BUFFER */ + return VK_ERROR_EXTENSION_NOT_PRESENT; +#endif +} + +VkResult +radv_create_ahb_memory(struct radv_device *device, + struct radv_device_memory *mem, + unsigned priority, + const VkMemoryAllocateInfo *pAllocateInfo) +{ +#if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER + 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) { + RADV_FROM_HANDLE(radv_image, image, dedicated_info->image); + w = image->info.width; + h = image->info.height; + layers = image->info.array_size; + format = android_format_from_vk(image->vk_format); + usage = radv_ahb_usage_from_vk_usage(image->flags, image->usage); + } else if (dedicated_info && dedicated_info->buffer) { + RADV_FROM_HANDLE(radv_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 *android_hardware_buffer = NULL; + struct AHardwareBuffer_Desc desc = { + .width = w, + .height = h, + .layers = layers, + .format = format, + .usage = usage, + }; + + if (AHardwareBuffer_allocate(&desc, &android_hardware_buffer) != 0) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + mem->android_hardware_buffer = android_hardware_buffer; + + const struct VkImportAndroidHardwareBufferInfoANDROID import_info = { + .buffer = mem->android_hardware_buffer, + }; + + VkResult result = radv_import_ahb_memory(device, mem, priority, &import_info); + if (result != VK_SUCCESS) + AHardwareBuffer_release(mem->android_hardware_buffer); + return result; +#else /* RADV_SUPPORT_ANDROID_HARDWARE_BUFFER */ + return VK_ERROR_EXTENSION_NOT_PRESENT; +#endif +} diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index b953f63e216..b44b5cc6a9d 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -3454,24 +3454,28 @@ static VkResult radv_alloc_memory(struct radv_device *device, assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO); - if (pAllocateInfo->allocationSize == 0) { - /* Apparently, this is allowed */ - *pMem = VK_NULL_HANDLE; - return VK_SUCCESS; - } - const VkImportMemoryFdInfoKHR *import_info = vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR); const VkMemoryDedicatedAllocateInfo *dedicate_info = vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO); const VkExportMemoryAllocateInfo *export_info = vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO); + const struct VkImportAndroidHardwareBufferInfoANDROID *ahb_import_info = + vk_find_struct_const(pAllocateInfo->pNext, + IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID); const VkImportMemoryHostPointerInfoEXT *host_ptr_info = vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_HOST_POINTER_INFO_EXT); const struct wsi_memory_allocate_info *wsi_info = vk_find_struct_const(pAllocateInfo->pNext, WSI_MEMORY_ALLOCATE_INFO_MESA); + if (pAllocateInfo->allocationSize == 0 && !ahb_import_info && + !(export_info && (export_info->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID))) { + /* Apparently, this is allowed */ + *pMem = VK_NULL_HANDLE; + return VK_SUCCESS; + } + mem = vk_zalloc2(&device->alloc, pAllocator, sizeof(*mem), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (mem == NULL) @@ -3505,7 +3509,15 @@ static VkResult radv_alloc_memory(struct radv_device *device, mem->android_hardware_buffer = NULL; #endif - if (import_info) { + if (ahb_import_info) { + result = radv_import_ahb_memory(device, mem, priority, ahb_import_info); + if (result != VK_SUCCESS) + goto fail; + } else if(export_info && (export_info->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)) { + result = radv_create_ahb_memory(device, mem, priority, pAllocateInfo); + if (result != VK_SUCCESS) + goto fail; + } else if (import_info) { assert(import_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT || import_info->handleType == diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index f0a5fc19604..51b7d7953ef 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -76,6 +76,7 @@ typedef uint32_t xcb_window_t; #include #include +#include #include #include @@ -1927,6 +1928,16 @@ radv_image_from_gralloc(VkDevice device_h, uint64_t radv_ahb_usage_from_vk_usage(const VkImageCreateFlags vk_create, const VkImageUsageFlags vk_usage); +VkResult +radv_import_ahb_memory(struct radv_device *device, + struct radv_device_memory *mem, + unsigned priority, + const VkImportAndroidHardwareBufferInfoANDROID *info); +VkResult +radv_create_ahb_memory(struct radv_device *device, + struct radv_device_memory *mem, + unsigned priority, + const VkMemoryAllocateInfo *pAllocateInfo); VkFormat radv_select_android_external_format(const void *next, VkFormat default_format); -- 2.30.2