On Tue, Aug 21, 2018 at 3:27 AM Tapani Pälli <tapani.pa...@intel.com> wrote:
> v2: add support for non-image buffers (AHARDWAREBUFFER_FORMAT_BLOB) > v3: properly handle usage bits when creating from image > > Signed-off-by: Tapani Pälli <tapani.pa...@intel.com> > --- > src/intel/vulkan/anv_android.c | 149 > +++++++++++++++++++++++++++++++++++++++++ > src/intel/vulkan/anv_device.c | 46 ++++++++++++- > src/intel/vulkan/anv_private.h | 18 +++++ > 3 files changed, 212 insertions(+), 1 deletion(-) > > diff --git a/src/intel/vulkan/anv_android.c > b/src/intel/vulkan/anv_android.c > index 7d0eb588e2b..6f90649847d 100644 > --- a/src/intel/vulkan/anv_android.c > +++ b/src/intel/vulkan/anv_android.c > @@ -195,6 +195,155 @@ anv_GetAndroidHardwareBufferPropertiesANDROID( > return VK_SUCCESS; > } > > +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 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; > + format = android_format_from_vk(image->vk_format); > + > + /* Construct usage mask from image usage bits, see > + * 'AHardwareBuffer Usage Equivalence' in spec. > + */ > + if (image->usage & VK_IMAGE_USAGE_SAMPLED_BIT) > + usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; > + > + if (image->usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) > + usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; > + > + if (image->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) > + usage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT; > + > + if (image->create_flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) > + usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP; > + > + if (image->create_flags & VK_IMAGE_CREATE_PROTECTED_BIT) > + usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT; > + > + /* No usage bits set, set at least one GPU usage. */ > + if (usage == 0) > + usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; > + > + } 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 = 1, > + .format = format, > + .usage = usage, > + .stride = 0, > If the image is linear (not sure if that's possible), we could give them a valid stride. > + }; > + > + 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 d8b67b54d63..54919112d08 100644 > --- a/src/intel/vulkan/anv_device.c > +++ b/src/intel/vulkan/anv_device.c > @@ -2161,14 +2161,53 @@ VkResult anv_AllocateMemory( > > if (pdevice->use_softpin) > bo_flags |= EXEC_OBJECT_PINNED; > + mem->ahw = NULL; > + > + /* Check if we need to support Android HW buffer export. If so, > + * create AHardwareBuffer and import memory from it. > + */ > + bool android_export = false; > + const VkExportMemoryAllocateInfo *export_info = > + vk_find_struct_const(pAllocateInfo->pNext, > + EXPORT_MEMORY_ALLOCATE_INFO); > + > + 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_info = > + vk_find_struct_const(pAllocateInfo->pNext, > + IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID); > > const VkImportMemoryFdInfoKHR *fd_info = > vk_find_struct_const(pAllocateInfo->pNext, > IMPORT_MEMORY_FD_INFO_KHR); > > + /* Android export support required. */ > + if (android_export) { > +#ifdef ANDROID > + 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; > +#endif > + } else if (ahw_info) { > +#ifdef ANDROID > + > + result = anv_import_ahw_memory(_device, mem, ahw_info); > + if (result != VK_SUCCESS) > + goto fail; > /* The Vulkan spec permits handleType to be 0, in which case the > struct is > * ignored. > */ > - if (fd_info && fd_info->handleType) { > +#endif > + } else if (fd_info && fd_info->handleType) { > Two comments here. First, I think this would be cleaner if we only had one #ifdef: if (android_export || ahw_info) { #ifdef ANDROID #else assert(!"Mesa was not built with android support"); #endif } Second, I think you want the order the other way around so it's if (ahw_info) { } else if (android_export) { } else { unreachable(); } Otherwise, if they import a ANativeHardwareBuffer that they intend to re-export, they'll end up with both ahw_info != NULL and android_export and it'll choose to create a new one instead of importing. > /* At the moment, we support only the below handle types. */ > assert(fd_info->handleType == > VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT || > @@ -2313,6 +2352,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 e6984e84afa..56dee607dbe 100644 > --- a/src/intel/vulkan/anv_private.h > +++ b/src/intel/vulkan/anv_private.h > @@ -85,6 +85,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 > * ========================= > * > @@ -1354,6 +1359,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; > }; > > /** > @@ -3043,6 +3053,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); > #endif > > const struct anv_surface * > -- > 2.14.4 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev