turnip: Support AHardwareBuffer

Signed-off-by: tarsin <yuanqingxiang233@163.com>
[rob: various fixes for android-cts failures]

Signed-off-by: Rob Clark <robdclark@chromium.org>
Reviewed-by: Roman Stratiienko <r.stratiienko@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29090>
This commit is contained in:
tarsin
2023-10-01 18:48:57 +08:00
committed by Marge Bot
parent 4b024a15f2
commit 99753001f3
5 changed files with 99 additions and 8 deletions

View File

@@ -5,8 +5,10 @@
#include "tu_android.h"
#include <android/hardware_buffer.h>
#include <hardware/hardware.h>
#include <hardware/hwvulkan.h>
#include <stdbool.h>
#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;
}

View File

@@ -45,6 +45,7 @@
#if DETECT_OS_ANDROID
#include "util/u_gralloc/u_gralloc.h"
#include <vndk/hardware_buffer.h>
#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;

View File

@@ -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 <vulkan/vulkan_android.h>
/* 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;

View File

@@ -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;
}

View File

@@ -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 */