diff --git a/src/freedreno/vulkan/tu_android.cc b/src/freedreno/vulkan/tu_android.cc index 5775d1939f6..6afeac66066 100644 --- a/src/freedreno/vulkan/tu_android.cc +++ b/src/freedreno/vulkan/tu_android.cc @@ -5,8 +5,10 @@ #include "tu_android.h" +#include #include #include +#include #include "util/u_gralloc/u_gralloc.h" #include "vk_android.h" @@ -78,4 +80,3 @@ tu_hal_close(struct hw_device_t *dev) vk_android_destroy_ugralloc(); return -1; } - diff --git a/src/freedreno/vulkan/tu_device.cc b/src/freedreno/vulkan/tu_device.cc index a60f2f9955c..bf09c58bd01 100644 --- a/src/freedreno/vulkan/tu_device.cc +++ b/src/freedreno/vulkan/tu_device.cc @@ -45,6 +45,7 @@ #if DETECT_OS_ANDROID #include "util/u_gralloc/u_gralloc.h" +#include #endif static int @@ -296,6 +297,7 @@ get_device_extensions(const struct tu_physical_device *device, #if DETECT_OS_ANDROID if (vk_android_get_ugralloc() != NULL) { + ext->ANDROID_external_memory_android_hardware_buffer = true, ext->ANDROID_native_buffer = true; } #endif @@ -2757,12 +2759,6 @@ tu_AllocateMemory(VkDevice _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; - } - struct tu_memory_heap *mem_heap = &device->physical_device->heap; uint64_t mem_heap_used = p_atomic_read(&mem_heap->used); if (mem_heap_used > mem_heap->size) @@ -2773,6 +2769,13 @@ tu_AllocateMemory(VkDevice _device, if (mem == NULL) return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + if (pAllocateInfo->allocationSize == 0 && !mem->vk.ahardware_buffer) { + vk_device_memory_destroy(&device->vk, pAllocator, &mem->vk); + /* Apparently, this is allowed */ + *pMem = VK_NULL_HANDLE; + return VK_SUCCESS; + } + const VkImportMemoryFdInfoKHR *fd_info = vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR); @@ -2793,6 +2796,15 @@ tu_AllocateMemory(VkDevice _device, /* take ownership and close the fd */ close(fd_info->fd); } + } else if (mem->vk.ahardware_buffer) { +#ifdef ANDROID + const native_handle_t *handle = AHardwareBuffer_getNativeHandle(mem->vk.ahardware_buffer); + assert(handle->numFds > 0); + size_t size = lseek(handle->data[0], 0, SEEK_END); + result = tu_bo_init_dmabuf(device, &mem->bo, size, handle->data[0]); +#else + result = VK_ERROR_FEATURE_NOT_PRESENT; +#endif } else { uint64_t client_address = 0; BITMASK_ENUM(tu_bo_alloc_flags) alloc_flags = TU_BO_ALLOC_NO_FLAGS; diff --git a/src/freedreno/vulkan/tu_formats.cc b/src/freedreno/vulkan/tu_formats.cc index e5f085de721..9bad9df3f79 100644 --- a/src/freedreno/vulkan/tu_formats.cc +++ b/src/freedreno/vulkan/tu_formats.cc @@ -8,13 +8,17 @@ #include "fdl/fd6_format_table.h" +#include "vk_android.h" #include "vk_enum_defines.h" #include "vk_util.h" #include "drm-uapi/drm_fourcc.h" +#include "tu_android.h" #include "tu_device.h" #include "tu_image.h" +#include + /* Map non-colorspace-converted YUV formats to RGB pipe formats where we can, * since our hardware doesn't support colorspace conversion. * @@ -685,6 +689,12 @@ tu_get_external_image_format_properties( handleType, pImageFormatInfo->type); } break; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID: + flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT | + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; + compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; + break; case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; @@ -717,6 +727,7 @@ tu_GetPhysicalDeviceImageFormatProperties2( const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL; const VkPhysicalDeviceImageViewImageFormatInfoEXT *image_view_info = NULL; VkExternalImageFormatProperties *external_props = NULL; + VkAndroidHardwareBufferUsageANDROID *android_usage = NULL; VkFilterCubicImageViewImageFormatPropertiesEXT *cubic_props = NULL; VkFormatFeatureFlags format_feature_flags; VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL; @@ -749,6 +760,9 @@ tu_GetPhysicalDeviceImageFormatProperties2( case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES: external_props = (VkExternalImageFormatProperties *) s; break; + case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID: + android_usage = (VkAndroidHardwareBufferUsageANDROID *) s; + break; case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT: cubic_props = (VkFilterCubicImageViewImageFormatPropertiesEXT *) s; break; @@ -789,6 +803,43 @@ tu_GetPhysicalDeviceImageFormatProperties2( } } + if (android_usage) { + /* Don't expect gralloc to be able to allocate anything other than 3D: */ + if (base_info->type != VK_IMAGE_TYPE_2D) { + result = vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED, + "type (%u) unsupported for AHB", base_info->type); + goto fail; + } + VkImageFormatProperties *props = &base_props->imageFormatProperties; + if (!(props->sampleCounts & VK_SAMPLE_COUNT_1_BIT)) { + result = vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED, + "sampleCounts (%x) unsupported for AHB", props->sampleCounts); + goto fail; + } + android_usage->androidHardwareBufferUsage = + vk_image_usage_to_ahb_usage(base_info->flags, base_info->usage); + uint32_t format = vk_image_format_to_ahb_format(base_info->format); + if (!format) { + result = vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED, + "format (%u) unsupported for AHB", base_info->format); + goto fail; + } + /* We can't advertise support for anything that gralloc cannot allocate + * so we are stuck without any better option than attempting a test + * allocation: + */ + if (!vk_ahb_probe_format(base_info->format, base_info->flags, base_info->usage)) { + result = vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED, + "format (%x) with flags (%x) and usage (%x) unsupported for AHB", + base_info->format, base_info->flags, base_info->usage); + goto fail; + } + + /* AHBs with mipmap usage will ignore this property */ + props->maxMipLevels = 1; + props->sampleCounts = VK_SAMPLE_COUNT_1_BIT; + } + if (ycbcr_props) ycbcr_props->combinedImageSamplerDescriptorCount = 1; diff --git a/src/freedreno/vulkan/tu_image.cc b/src/freedreno/vulkan/tu_image.cc index 92837226940..2e7e32de1c1 100644 --- a/src/freedreno/vulkan/tu_image.cc +++ b/src/freedreno/vulkan/tu_image.cc @@ -765,6 +765,15 @@ tu_CreateImage(VkDevice _device, if (result != VK_SUCCESS) goto fail; + /* This section is removed by the optimizer for non-ANDROID builds */ + if (vk_image_is_android_hardware_buffer(&image->vk)) { + /* At this time, an AHB handle is not yet provided. + * Image layout will be filled up during vkBindImageMemory2 + */ + *pImage = tu_image_to_handle(image); + return VK_SUCCESS; + } + result = tu_image_update_layout(device, image, modifier, plane_layouts); if (result != VK_SUCCESS) @@ -841,12 +850,26 @@ tu_BindImageMemory2(VkDevice _device, #endif if (mem) { + VkResult result; + if (vk_image_is_android_hardware_buffer(&image->vk)) { + VkImageDrmFormatModifierExplicitCreateInfoEXT eci; + VkSubresourceLayout a_plane_layouts[TU_MAX_PLANE_COUNT]; + result = vk_android_get_ahb_layout(mem->vk.ahardware_buffer, + &eci, a_plane_layouts, + TU_MAX_PLANE_COUNT); + if (result != VK_SUCCESS) + return result; + + result = tu_image_update_layout(device, image, eci.drmFormatModifier, a_plane_layouts); + if (result != VK_SUCCESS) + return result; + } image->bo = mem->bo; image->iova = mem->bo->iova + pBindInfos[i].memoryOffset; if (image->vk.usage & VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT) { if (!mem->bo->map) { - VkResult result = tu_bo_map(device, mem->bo, NULL); + result = tu_bo_map(device, mem->bo, NULL); if (result != VK_SUCCESS) return result; } diff --git a/src/freedreno/vulkan/tu_image.h b/src/freedreno/vulkan/tu_image.h index 3ade6f8852d..a0597ec47c9 100644 --- a/src/freedreno/vulkan/tu_image.h +++ b/src/freedreno/vulkan/tu_image.h @@ -132,4 +132,8 @@ tu_fragment_density_map_sample(const struct tu_image_view *fdm, uint32_t width, uint32_t height, uint32_t layers, struct tu_frag_area *areas); +VkResult +tu_image_update_layout(struct tu_device *device, struct tu_image *image, + uint64_t modifier, const VkSubresourceLayout *plane_layouts); + #endif /* TU_IMAGE_H */