diff options
Diffstat (limited to 'src/amd/vulkan/radv_android.c')
-rw-r--r-- | src/amd/vulkan/radv_android.c | 504 |
1 files changed, 172 insertions, 332 deletions
diff --git a/src/amd/vulkan/radv_android.c b/src/amd/vulkan/radv_android.c index 066cae971e6..e9505378737 100644 --- a/src/amd/vulkan/radv_android.c +++ b/src/amd/vulkan/radv_android.c @@ -1,27 +1,18 @@ /* * Copyright © 2017, Google Inc. * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. + * SPDX-License-Identifier: MIT */ -#ifdef ANDROID +#include "radv_android.h" +#include "radv_buffer.h" +#include "radv_device.h" +#include "radv_device_memory.h" +#include "radv_entrypoints.h" +#include "radv_image.h" +#include "radv_physical_device.h" + +#if DETECT_OS_ANDROID #include <libsync.h> #include <hardware/gralloc.h> #include <hardware/hardware.h> @@ -32,23 +23,20 @@ #if ANDROID_API_LEVEL >= 26 #include <hardware/gralloc1.h> #endif -#endif +#endif /* DETECT_OS_ANDROID */ #include "util/os_file.h" -#include "radv_private.h" +#include "vk_android.h" +#include "vk_log.h" #include "vk_util.h" -#ifdef ANDROID +#if DETECT_OS_ANDROID static int radv_hal_open(const struct hw_module_t *mod, const char *id, struct hw_device_t **dev); static int radv_hal_close(struct hw_device_t *dev); -static void UNUSED -static_asserts(void) -{ - STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC); -} +static_assert(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC, ""); PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = { .common = @@ -111,17 +99,18 @@ radv_hal_close(struct hw_device_t *dev) VkResult radv_image_from_gralloc(VkDevice device_h, const VkImageCreateInfo *base_info, - const VkNativeBufferANDROID *gralloc_info, - const VkAllocationCallbacks *alloc, VkImage *out_image_h) + const VkNativeBufferANDROID *gralloc_info, const VkAllocationCallbacks *alloc, + VkImage *out_image_h) { - RADV_FROM_HANDLE(radv_device, device, device_h); + VK_FROM_HANDLE(radv_device, device, device_h); + const struct radv_physical_device *pdev = radv_device_physical(device); VkImage image_h = VK_NULL_HANDLE; struct radv_image *image = NULL; VkResult result; if (gralloc_info->handle->numFds != 1) { - return vk_errorf(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE, + return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE, "VkNativeBufferANDROID::handle::numFds is %d, " "expected 1", gralloc_info->handle->numFds); @@ -143,10 +132,10 @@ radv_image_from_gralloc(VkDevice device_h, const VkImageCreateInfo *base_info, /* Find the first VRAM memory type, or GART for PRIME images. */ int memory_type_index = -1; - for (int i = 0; i < device->physical_device->memory_properties.memoryTypeCount; ++i) { - bool is_local = !!(device->physical_device->memory_properties.memoryTypes[i].propertyFlags & - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - if (is_local) { + for (int i = 0; i < pdev->memory_properties.memoryTypeCount; ++i) { + bool is_local = !!(pdev->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + bool is_32bit = !!(pdev->memory_types_32bit & (1u << i)); + if (is_local && !is_32bit) { memory_type_index = i; break; } @@ -187,7 +176,7 @@ radv_image_from_gralloc(VkDevice device_h, const VkImageCreateInfo *base_info, .no_metadata_planes = true, .bo_metadata = &md, }, - alloc, &image_h); + alloc, &image_h, false); if (result != VK_SUCCESS) goto fail_create_image; @@ -196,7 +185,11 @@ radv_image_from_gralloc(VkDevice device_h, const VkImageCreateInfo *base_info, radv_image_override_offset_stride(device, image, 0, gralloc_info->stride); - radv_BindImageMemory(device_h, image_h, memory_h, 0); + VkBindImageMemoryInfo bind_info = {.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, + .image = image_h, + .memory = memory_h, + .memoryOffset = 0}; + radv_BindImageMemory2(device_h, 1, &bind_info); image->owned_memory = memory_h; /* Don't clobber the out-parameter until success is certain. */ @@ -210,12 +203,12 @@ fail_create_image: } VkResult -radv_GetSwapchainGrallocUsageANDROID(VkDevice device_h, VkFormat format, - VkImageUsageFlags imageUsage, int *grallocUsage) +radv_GetSwapchainGrallocUsageANDROID(VkDevice device_h, VkFormat format, VkImageUsageFlags imageUsage, + int *grallocUsage) { - RADV_FROM_HANDLE(radv_device, device, device_h); - struct radv_physical_device *phys_dev = device->physical_device; - VkPhysicalDevice phys_dev_h = radv_physical_device_to_handle(phys_dev); + VK_FROM_HANDLE(radv_device, device, device_h); + struct radv_physical_device *pdev = radv_device_physical(device); + VkPhysicalDevice pdev_h = radv_physical_device_to_handle(pdev); VkResult result; *grallocUsage = 0; @@ -246,10 +239,9 @@ radv_GetSwapchainGrallocUsageANDROID(VkDevice device_h, VkFormat format, }; /* Check that requested format and usage are supported. */ - result = radv_GetPhysicalDeviceImageFormatProperties2(phys_dev_h, &image_format_info, - &image_format_props); + result = radv_GetPhysicalDeviceImageFormatProperties2(pdev_h, &image_format_info, &image_format_props); if (result != VK_SUCCESS) { - return vk_errorf(device->instance, result, + return vk_errorf(device, result, "radv_GetPhysicalDeviceImageFormatProperties2 failed " "inside %s", __func__); @@ -258,15 +250,15 @@ radv_GetSwapchainGrallocUsageANDROID(VkDevice device_h, VkFormat format, if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) *grallocUsage |= GRALLOC_USAGE_HW_RENDER; - if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | - VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) + if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) *grallocUsage |= GRALLOC_USAGE_HW_TEXTURE; /* All VkImageUsageFlags not explicitly checked here are unsupported for * gralloc swapchains. */ if (imageUsage != 0) { - return vk_errorf(device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED, + return vk_errorf(device, VK_ERROR_FORMAT_NOT_SUPPORTED, "unsupported VkImageUsageFlags(0x%x) for gralloc " "swapchain", imageUsage); @@ -278,8 +270,7 @@ radv_GetSwapchainGrallocUsageANDROID(VkDevice device_h, VkFormat format, * what we need for 30-bit colors. */ if (format == VK_FORMAT_B8G8R8A8_UNORM || format == VK_FORMAT_B5G6R5_UNORM_PACK16) { - *grallocUsage |= - GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_EXTERNAL_DISP; + *grallocUsage |= GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_EXTERNAL_DISP; } if (*grallocUsage == 0) @@ -289,25 +280,23 @@ radv_GetSwapchainGrallocUsageANDROID(VkDevice device_h, VkFormat format, } VkResult -radv_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h, VkFormat format, - VkImageUsageFlags imageUsage, +radv_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, - uint64_t *grallocConsumerUsage, - uint64_t *grallocProducerUsage) + uint64_t *grallocConsumerUsage, uint64_t *grallocProducerUsage) { /* Before level 26 (Android 8.0/Oreo) the loader uses * vkGetSwapchainGrallocUsageANDROID. */ #if ANDROID_API_LEVEL >= 26 - RADV_FROM_HANDLE(radv_device, device, device_h); - struct radv_physical_device *phys_dev = device->physical_device; - VkPhysicalDevice phys_dev_h = radv_physical_device_to_handle(phys_dev); + VK_FROM_HANDLE(radv_device, device, device_h); + struct radv_physical_device *pdev = radv_device_physical(device); + VkPhysicalDevice pdev_h = radv_physical_device_to_handle(pdev); VkResult result; *grallocConsumerUsage = 0; *grallocProducerUsage = 0; if (swapchainImageUsage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID) - return vk_errorf(device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED, + return vk_errorf(device, VK_ERROR_FORMAT_NOT_SUPPORTED, "The Vulkan loader tried to query shared presentable image support"); const VkPhysicalDeviceImageFormatInfo2 image_format_info = { @@ -323,28 +312,26 @@ radv_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h, VkFormat format, }; /* Check that requested format and usage are supported. */ - result = radv_GetPhysicalDeviceImageFormatProperties2(phys_dev_h, &image_format_info, - &image_format_props); + result = radv_GetPhysicalDeviceImageFormatProperties2(pdev_h, &image_format_info, &image_format_props); if (result != VK_SUCCESS) { - return vk_errorf(device->instance, result, + return vk_errorf(device, result, "radv_GetPhysicalDeviceImageFormatProperties2 failed " "inside %s", __func__); } - if (unmask32(&imageUsage, - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) { + if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) { *grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET; *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET; } - if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | - VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) { + if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) { *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE; } if (imageUsage != 0) { - return vk_errorf(device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED, + return vk_errorf(device, VK_ERROR_FORMAT_NOT_SUPPORTED, "unsupported VkImageUsageFlags(0x%x) for gralloc " "swapchain", imageUsage); @@ -370,227 +357,55 @@ radv_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h, VkFormat format, return VK_ERROR_FORMAT_NOT_SUPPORTED; #endif } - -VkResult -radv_AcquireImageANDROID(VkDevice device_h, VkImage image_h, int nativeFenceFd, VkSemaphore semaphore, - VkFence fence) -{ - RADV_FROM_HANDLE(radv_device, device, device_h); - VkResult result = VK_SUCCESS; - - /* From https://source.android.com/devices/graphics/implement-vulkan : - * - * "The driver takes ownership of the fence file descriptor and closes - * the fence file descriptor when no longer needed. The driver must do - * so even if neither a semaphore or fence object is provided, or even - * if vkAcquireImageANDROID fails and returns an error." - * - * The Vulkan spec for VkImportFence/SemaphoreFdKHR(), however, requires - * the file descriptor to be left alone on failure. - */ - int semaphore_fd = -1, fence_fd = -1; - if (nativeFenceFd >= 0) { - if (semaphore != VK_NULL_HANDLE && fence != VK_NULL_HANDLE) { - /* We have both so we have to import the sync file twice. One of - * them needs to be a dup. - */ - semaphore_fd = nativeFenceFd; - fence_fd = dup(nativeFenceFd); - if (fence_fd < 0) { - VkResult err = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS : - VK_ERROR_OUT_OF_HOST_MEMORY; - close(nativeFenceFd); - return vk_error(device->instance, err); - } - } else if (semaphore != VK_NULL_HANDLE) { - semaphore_fd = nativeFenceFd; - } else if (fence != VK_NULL_HANDLE) { - fence_fd = nativeFenceFd; - } else { - /* Nothing to import into so we have to close the file */ - close(nativeFenceFd); - } - } - - if (semaphore != VK_NULL_HANDLE) { - const VkImportSemaphoreFdInfoKHR info = { - .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, - .semaphore = semaphore, - .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, - .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, - .fd = semaphore_fd, - }; - result = radv_ImportSemaphoreFdKHR(device_h, &info); - if (result == VK_SUCCESS) - semaphore_fd = -1; /* RADV took ownership */ - } - - if (result == VK_SUCCESS && fence != VK_NULL_HANDLE) { - const VkImportFenceFdInfoKHR info = { - .sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR, - .fence = fence, - .flags = VK_FENCE_IMPORT_TEMPORARY_BIT, - .handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, - .fd = fence_fd, - }; - result = radv_ImportFenceFdKHR(device_h, &info); - if (result == VK_SUCCESS) - fence_fd = -1; /* RADV took ownership */ - } - - if (semaphore_fd >= 0) - close(semaphore_fd); - if (fence_fd >= 0) - close(fence_fd); - - return result; -} - -VkResult -radv_QueueSignalReleaseImageANDROID(VkQueue _queue, uint32_t waitSemaphoreCount, - const VkSemaphore *pWaitSemaphores, VkImage image, - int *pNativeFenceFd) -{ - RADV_FROM_HANDLE(radv_queue, queue, _queue); - VkResult result = VK_SUCCESS; - - if (waitSemaphoreCount == 0) { - if (pNativeFenceFd) - *pNativeFenceFd = -1; - return VK_SUCCESS; - } - - int fd = -1; - - for (uint32_t i = 0; i < waitSemaphoreCount; ++i) { - int tmp_fd; - result = - radv_GetSemaphoreFdKHR(radv_device_to_handle(queue->device), - &(VkSemaphoreGetFdInfoKHR){ - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, - .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, - .semaphore = pWaitSemaphores[i], - }, - &tmp_fd); - if (result != VK_SUCCESS) { - if (fd >= 0) - close(fd); - return result; - } - - if (fd < 0) - fd = tmp_fd; - else if (tmp_fd >= 0) { - sync_accumulate("radv", &fd, tmp_fd); - close(tmp_fd); - } - } - - if (pNativeFenceFd) { - *pNativeFenceFd = fd; - } else if (fd >= 0) { - close(fd); - /* We still need to do the exports, to reset the semaphores, but - * otherwise we don't wait on them. */ - } - return VK_SUCCESS; -} -#endif +#endif /* DETECT_OS_ANDROID */ #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER enum { /* Usage bit equal to GRALLOC_USAGE_HW_CAMERA_MASK */ - AHARDWAREBUFFER_USAGE_CAMERA_MASK = 0x00060000U, + BUFFER_USAGE_CAMERA_MASK = 0x00060000U, }; static inline VkFormat vk_format_from_android(unsigned android_format, unsigned android_usage) { switch (android_format) { - case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM: - case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM: - return VK_FORMAT_R8G8B8A8_UNORM; - case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM: - return VK_FORMAT_R8G8B8_UNORM; - case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM: - return VK_FORMAT_R5G6B5_UNORM_PACK16; - case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT: - return VK_FORMAT_R16G16B16A16_SFLOAT; - case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM: - return VK_FORMAT_A2B10G10R10_UNORM_PACK32; case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; case AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED: - if (android_usage & AHARDWAREBUFFER_USAGE_CAMERA_MASK) + if (android_usage & BUFFER_USAGE_CAMERA_MASK) return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; else return VK_FORMAT_R8G8B8_UNORM; - case AHARDWAREBUFFER_FORMAT_BLOB: default: - return VK_FORMAT_UNDEFINED; + return vk_ahb_format_to_image_format(android_format); } } -static inline unsigned -android_format_from_vk(unsigned vk_format) +unsigned +radv_ahb_format_for_vk_format(VkFormat 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; + return vk_image_format_to_ahb_format(vk_format); } } -uint64_t -radv_ahb_usage_from_vk_usage(const VkImageCreateFlags vk_create, const VkImageUsageFlags vk_usage) -{ - uint64_t ahb_usage = 0; - if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT) - ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; - - if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) - ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; - - if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) - ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT; - - if (vk_create & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) - ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP; - - if (vk_create & VK_IMAGE_CREATE_PROTECTED_BIT) - ahb_usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT; - - /* No usage bits set - set at least one GPU usage. */ - if (ahb_usage == 0) - ahb_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; - return ahb_usage; -} - static VkResult get_ahb_buffer_format_properties(VkDevice device_h, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferFormatPropertiesANDROID *pProperties) { - RADV_FROM_HANDLE(radv_device, device, device_h); + VK_FROM_HANDLE(radv_device, device, device_h); + struct radv_physical_device *pdev = radv_device_physical(device); /* Get a description of buffer contents . */ AHardwareBuffer_Desc desc; AHardwareBuffer_describe(buffer, &desc); /* Verify description. */ - const uint64_t gpu_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | - AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | + const uint64_t gpu_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER; /* "Buffer must be a valid Android hardware buffer object with at least @@ -605,14 +420,14 @@ get_ahb_buffer_format_properties(VkDevice device_h, const struct AHardwareBuffer p->format = vk_format_from_android(desc.format, desc.usage); p->externalFormat = (uint64_t)(uintptr_t)p->format; - VkFormatProperties format_properties; - radv_GetPhysicalDeviceFormatProperties(radv_physical_device_to_handle(device->physical_device), - p->format, &format_properties); + VkFormatProperties2 format_properties = {.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2}; + + radv_GetPhysicalDeviceFormatProperties2(radv_physical_device_to_handle(pdev), p->format, &format_properties); if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) - p->formatFeatures = format_properties.linearTilingFeatures; + p->formatFeatures = format_properties.formatProperties.linearTilingFeatures; else - p->formatFeatures = format_properties.optimalTilingFeatures; + p->formatFeatures = format_properties.formatProperties.optimalTilingFeatures; /* "Images can be created with an external format even if the Android hardware * buffer has a format which has an equivalent Vulkan format to enable @@ -651,13 +466,85 @@ get_ahb_buffer_format_properties(VkDevice device_h, const struct AHardwareBuffer return VK_SUCCESS; } +static VkResult +get_ahb_buffer_format_properties2(VkDevice device_h, const struct AHardwareBuffer *buffer, + VkAndroidHardwareBufferFormatProperties2ANDROID *pProperties) +{ + VK_FROM_HANDLE(radv_device, device, device_h); + struct radv_physical_device *pdev = radv_device_physical(device); + + /* Get a description of buffer contents . */ + AHardwareBuffer_Desc desc; + AHardwareBuffer_describe(buffer, &desc); + + /* Verify description. */ + const uint64_t gpu_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | + AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER; + + /* "Buffer must be a valid Android hardware buffer object with at least + * one of the AHARDWAREBUFFER_USAGE_GPU_* usage flags." + */ + if (!(desc.usage & (gpu_usage))) + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + + /* Fill properties fields based on description. */ + VkAndroidHardwareBufferFormatProperties2ANDROID *p = pProperties; + + p->format = vk_format_from_android(desc.format, desc.usage); + p->externalFormat = (uint64_t)(uintptr_t)p->format; + + VkFormatProperties2 format_properties = {.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2}; + + radv_GetPhysicalDeviceFormatProperties2(radv_physical_device_to_handle(pdev), p->format, &format_properties); + + if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) + p->formatFeatures = format_properties.formatProperties.linearTilingFeatures; + else + p->formatFeatures = format_properties.formatProperties.optimalTilingFeatures; + + /* "Images can be created with an external format even if the Android hardware + * buffer has a format which has an equivalent Vulkan format to enable + * consistent handling of images from sources that might use either category + * of format. However, all images created with an external format are subject + * to the valid usage requirements associated with external formats, even if + * the Android hardware buffer’s format has a Vulkan equivalent." + * + * "The formatFeatures member *must* include + * VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT and at least one of + * VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT or + * VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT" + */ + assert(p->formatFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT); + + p->formatFeatures |= VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT; + + /* "Implementations may not always be able to determine the color model, + * numerical range, or chroma offsets of the image contents, so the values + * in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions. + * Applications should treat these values as sensible defaults to use in + * the absence of more reliable information obtained through some other + * means." + */ + p->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_IDENTITY; + p->samplerYcbcrConversionComponents.g = VK_COMPONENT_SWIZZLE_IDENTITY; + p->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY; + p->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY; + + p->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601; + p->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; + + p->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT; + p->suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT; + + return VK_SUCCESS; +} + VkResult -radv_GetAndroidHardwareBufferPropertiesANDROID(VkDevice device_h, - const struct AHardwareBuffer *buffer, +radv_GetAndroidHardwareBufferPropertiesANDROID(VkDevice device_h, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties) { - RADV_FROM_HANDLE(radv_device, dev, device_h); - struct radv_physical_device *pdevice = dev->physical_device; + VK_FROM_HANDLE(radv_device, dev, device_h); + struct radv_physical_device *pdev = radv_device_physical(dev); VkAndroidHardwareBufferFormatPropertiesANDROID *format_prop = vk_find_struct(pProperties->pNext, ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID); @@ -666,6 +553,11 @@ radv_GetAndroidHardwareBufferPropertiesANDROID(VkDevice device_h, if (format_prop) get_ahb_buffer_format_properties(device_h, buffer, format_prop); + VkAndroidHardwareBufferFormatProperties2ANDROID *format_prop2 = + vk_find_struct(pProperties->pNext, ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID); + if (format_prop2) + get_ahb_buffer_format_properties2(device_h, buffer, format_prop2); + /* 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 @@ -677,20 +569,19 @@ radv_GetAndroidHardwareBufferPropertiesANDROID(VkDevice device_h, return VK_ERROR_INVALID_EXTERNAL_HANDLE; /* All memory types. */ - uint32_t memory_types = (1u << pdevice->memory_properties.memoryTypeCount) - 1; + uint32_t memory_types = (1u << pdev->memory_properties.memoryTypeCount) - 1; pProperties->allocationSize = lseek(dma_buf, 0, SEEK_END); - pProperties->memoryTypeBits = memory_types; + pProperties->memoryTypeBits = memory_types & ~pdev->memory_types_32bit; return VK_SUCCESS; } VkResult -radv_GetMemoryAndroidHardwareBufferANDROID(VkDevice device_h, - const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo, +radv_GetMemoryAndroidHardwareBufferANDROID(VkDevice device_h, const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo, struct AHardwareBuffer **pBuffer) { - RADV_FROM_HANDLE(radv_device_memory, mem, pInfo->memory); + VK_FROM_HANDLE(radv_device_memory, mem, pInfo->memory); /* This should always be set due to the export handle types being set on * allocation. */ @@ -718,8 +609,7 @@ VkFormat radv_select_android_external_format(const void *next, VkFormat default_format) { #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER - const VkExternalFormatANDROID *android_format = - vk_find_struct_const(next, EXTERNAL_FORMAT_ANDROID); + const VkExternalFormatANDROID *android_format = vk_find_struct_const(next, EXTERNAL_FORMAT_ANDROID); if (android_format && android_format->externalFormat) { return (VkFormat)android_format->externalFormat; @@ -730,8 +620,8 @@ radv_select_android_external_format(const void *next, VkFormat default_format) } VkResult -radv_import_ahb_memory(struct radv_device *device, struct radv_device_memory *mem, - unsigned priority, const VkImportAndroidHardwareBufferInfoANDROID *info) +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. */ @@ -747,8 +637,7 @@ radv_import_ahb_memory(struct radv_device *device, struct radv_device_memory *me return VK_ERROR_INVALID_EXTERNAL_HANDLE; uint64_t alloc_size = 0; - VkResult result = - device->ws->buffer_from_fd(device->ws, dma_buf, priority, &mem->bo, &alloc_size); + VkResult result = device->ws->buffer_from_fd(device->ws, dma_buf, priority, &mem->bo, &alloc_size); if (result != VK_SUCCESS) return result; @@ -756,24 +645,23 @@ radv_import_ahb_memory(struct radv_device *device, struct radv_device_memory *me struct radeon_bo_metadata metadata; device->ws->buffer_get_metadata(device->ws, mem->bo, &metadata); - struct radv_image_create_info create_info = {.no_metadata_planes = true, - .bo_metadata = &metadata}; + struct radv_image_create_info create_info = {.no_metadata_planes = true, .bo_metadata = &metadata}; - VkResult result = radv_image_create_layout(device, create_info, NULL, mem->image); + result = radv_image_create_layout(device, create_info, NULL, NULL, mem->image); if (result != VK_SUCCESS) { - device->ws->buffer_destroy(device->ws, mem->bo); + radv_bo_destroy(device, NULL, mem->bo); mem->bo = NULL; return result; } if (alloc_size < mem->image->size) { - device->ws->buffer_destroy(device->ws, mem->bo); + radv_bo_destroy(device, NULL, mem->bo); mem->bo = NULL; return VK_ERROR_INVALID_EXTERNAL_HANDLE; } } else if (mem->buffer) { - if (alloc_size < mem->buffer->size) { - device->ws->buffer_destroy(device->ws, mem->bo); + if (alloc_size < mem->buffer->vk.size) { + radv_bo_destroy(device, NULL, mem->bo); mem->bo = NULL; return VK_ERROR_INVALID_EXTERNAL_HANDLE; } @@ -794,52 +682,14 @@ radv_import_ahb_memory(struct radv_device *device, struct radv_device_memory *me } VkResult -radv_create_ahb_memory(struct radv_device *device, struct radv_device_memory *mem, - unsigned priority, const VkMemoryAllocateInfo *pAllocateInfo) +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) + mem->android_hardware_buffer = vk_alloc_ahardware_buffer(pAllocateInfo); + if (mem->android_hardware_buffer == NULL) return VK_ERROR_OUT_OF_HOST_MEMORY; - mem->android_hardware_buffer = android_hardware_buffer; - const struct VkImportAndroidHardwareBufferInfoANDROID import_info = { .buffer = mem->android_hardware_buffer, }; @@ -859,21 +709,11 @@ bool radv_android_gralloc_supports_format(VkFormat format, VkImageUsageFlagBits usage) { #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER - /* Ideally we check Gralloc for what it supports and then merge that with the radv - format support, but there is no easy gralloc query besides just creating an image. - That seems a bit on the expensive side, so just hardcode for now. */ - /* TODO: Add multi-plane formats after confirming everything works between radeonsi - and radv. */ - switch (format) { - case VK_FORMAT_R8G8B8A8_UNORM: - case VK_FORMAT_R5G6B5_UNORM_PACK16: - return true; - case VK_FORMAT_R8_UNORM: - case VK_FORMAT_R8G8_UNORM: - return !(usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); - default: - return false; - } + /* Ideally we check AHardwareBuffer_isSupported. But that test-allocates on most platforms and + * seems a bit on the expensive side. Return true as long as it is a format we understand. + */ + (void)usage; + return radv_ahb_format_for_vk_format(format); #else (void)format; (void)usage; |