From 08f3965ad004f2a6a7342a9baa81baed1c044c69 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 28 Aug 2024 11:50:09 -0400 Subject: [PATCH] aux/vk: handle extFormatResolve in create_image Part-of: --- src/xrt/auxiliary/vk/vk_helpers.c | 64 +++++++++++++++-------- src/xrt/auxiliary/vk/vk_helpers.h | 13 ++--- src/xrt/auxiliary/vk/vk_image_allocator.c | 38 +++++++++++--- 3 files changed, 76 insertions(+), 39 deletions(-) diff --git a/src/xrt/auxiliary/vk/vk_helpers.c b/src/xrt/auxiliary/vk/vk_helpers.c index f7086b489..062181738 100644 --- a/src/xrt/auxiliary/vk/vk_helpers.c +++ b/src/xrt/auxiliary/vk/vk_helpers.c @@ -804,28 +804,15 @@ vk_get_memory_type(struct vk_bundle *vk, uint32_t type_bits, VkMemoryPropertyFla XRT_CHECK_RESULT VkResult vk_alloc_and_bind_image_memory(struct vk_bundle *vk, VkImage image, - size_t max_size, + const VkMemoryRequirements *requirements, const void *pNext_for_allocate, const char *caller_name, - VkDeviceMemory *out_mem, - VkDeviceSize *out_size) + VkDeviceMemory *out_mem) { - VkMemoryRequirements memory_requirements; - vk->vkGetImageMemoryRequirements(vk->device, image, &memory_requirements); - - if (max_size > 0 && memory_requirements.size > max_size) { - VK_ERROR(vk, "(%s) vkGetImageMemoryRequirements: Requested more memory (%u) then given (%u)\n", - caller_name, (uint32_t)memory_requirements.size, (uint32_t)max_size); - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - if (out_size != NULL) { - *out_size = memory_requirements.size; - } - uint32_t memory_type_index = UINT32_MAX; bool bret = vk_get_memory_type( // vk, // vk_bundle - memory_requirements.memoryTypeBits, // type_bits + requirements->memoryTypeBits, // type_bits VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, // memory_props &memory_type_index); // out_type_id if (!bret) { @@ -836,7 +823,7 @@ vk_alloc_and_bind_image_memory(struct vk_bundle *vk, VkMemoryAllocateInfo alloc_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .pNext = pNext_for_allocate, - .allocationSize = memory_requirements.size, + .allocationSize = requirements->size, .memoryTypeIndex = memory_type_index, }; @@ -901,14 +888,16 @@ create_image_simple(struct vk_bundle *vk, return ret; } + VkMemoryRequirements requirements = {0}; + vk->vkGetImageMemoryRequirements(vk->device, image, &requirements); + ret = vk_alloc_and_bind_image_memory( // vk, // vk_bundle image, // image - SIZE_MAX, // max_size + &requirements, // max_size NULL, // pNext_for_allocate __func__, // caller_name - out_mem, // out_mem - NULL); // out_size + out_mem); // out_mem if (ret != VK_SUCCESS) { // Clean up image vk->vkDestroyImage(vk->device, image, NULL); @@ -1154,18 +1143,37 @@ vk_create_image_from_native(struct vk_bundle *vk, // Nothing to cleanup return ret; } + + VkMemoryRequirements requirements = {0}; + vk->vkGetImageMemoryRequirements(vk->device, image, &requirements); + #if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD) VkImportMemoryFdInfoKHR import_memory_info = { .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR, .fd = image_native->handle, }; + + // TODO memoryTypeBits from VkMemoryFdPropertiesKHR #elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER) VkImportAndroidHardwareBufferInfoANDROID import_memory_info = { .sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, .pNext = NULL, .buffer = image_native->handle, }; + + VkAndroidHardwareBufferPropertiesANDROID ahb_props = { + .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, + }; + + ret = vk->vkGetAndroidHardwareBufferPropertiesANDROID(vk->device, image_native->handle, &ahb_props); + if (ret != VK_SUCCESS) { + VK_ERROR(vk, "vkGetAndroidHardwareBufferPropertiesANDROID: %s", vk_result_string(ret)); + return ret; + } + + requirements.size = ahb_props.allocationSize; + requirements.memoryTypeBits = ahb_props.memoryTypeBits; #elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_WIN32_HANDLE) VkImportMemoryWin32HandleInfoKHR import_memory_info = { .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, @@ -1173,9 +1181,20 @@ vk_create_image_from_native(struct vk_bundle *vk, .handleType = handle_type, .handle = image_native->handle, }; + + // TODO memoryTypeBits from VkMemoryWin32HandlePropertiesKHR #else #error "need port" #endif + if (requirements.size > image_native->size) { + VK_ERROR(vk, "size mismatch, exported %" PRIu64 " but requires %" PRIu64, image_native->size, + requirements.size); + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } else if (requirements.size < image_native->size) { + VK_WARN(vk, "size mismatch, exported %" PRIu64 " but requires %" PRIu64, image_native->size, + requirements.size); + } + VkMemoryDedicatedAllocateInfoKHR dedicated_memory_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, .pNext = &import_memory_info, @@ -1186,11 +1205,10 @@ vk_create_image_from_native(struct vk_bundle *vk, ret = vk_alloc_and_bind_image_memory( // vk, // vk_bundle image, // image - image_native->size, // max_size + &requirements, // requirements &dedicated_memory_info, // pNext_for_allocate __func__, // caller_name - out_mem, // out_mem - NULL); // out_size + out_mem); // out_mem #if defined(XRT_GRAPHICS_BUFFER_HANDLE_CONSUMED_BY_VULKAN_IMPORT) // We have consumed this fd now, make sure it's not freed again. diff --git a/src/xrt/auxiliary/vk/vk_helpers.h b/src/xrt/auxiliary/vk/vk_helpers.h index cddf67a4b..2d2e3558b 100644 --- a/src/xrt/auxiliary/vk/vk_helpers.h +++ b/src/xrt/auxiliary/vk/vk_helpers.h @@ -1082,9 +1082,7 @@ vk_get_memory_type(struct vk_bundle *vk, uint32_t type_bits, VkMemoryPropertyFla * * @param vk Vulkan bundle * @param image The VkImage to allocate for and bind. - * @param max_size The maximum value you'll allow for - * VkMemoryRequirements::size. Pass SIZE_MAX if you will accept any size - * that works. + * @param requirements Memory requirements used for finding the memory type and the size. * @param pNext_for_allocate (Optional) a pointer to use in the pNext chain of * VkMemoryAllocateInfo. * @param caller_name Used for error printing, this function is called from @@ -1104,11 +1102,10 @@ vk_get_memory_type(struct vk_bundle *vk, uint32_t type_bits, VkMemoryPropertyFla XRT_CHECK_RESULT VkResult vk_alloc_and_bind_image_memory(struct vk_bundle *vk, VkImage image, - size_t max_size, + const VkMemoryRequirements *requirements, const void *pNext_for_allocate, const char *caller_name, - VkDeviceMemory *out_mem, - VkDeviceSize *out_size); + VkDeviceMemory *out_mem); /*! * @@ -1564,9 +1561,7 @@ vk_csci_get_image_external_support(struct vk_bundle *vk, * CSCI = Compositor SwapChain Images. */ bool -vk_csci_is_format_supported(struct vk_bundle *vk, - VkFormat format, - enum xrt_swapchain_usage_bits xbits); +vk_csci_is_format_supported(struct vk_bundle *vk, VkFormat format, enum xrt_swapchain_usage_bits xbits); /* * diff --git a/src/xrt/auxiliary/vk/vk_image_allocator.c b/src/xrt/auxiliary/vk/vk_image_allocator.c index 9fb06b619..b1315f91f 100644 --- a/src/xrt/auxiliary/vk/vk_image_allocator.c +++ b/src/xrt/auxiliary/vk/vk_image_allocator.c @@ -108,7 +108,6 @@ create_image(struct vk_bundle *vk, const struct xrt_swapchain_create_info *info, VkDeviceMemory device_memory = VK_NULL_HANDLE; VkImage image = VK_NULL_HANDLE; VkResult ret = VK_SUCCESS; - VkDeviceSize size; #if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER) /* @@ -187,9 +186,8 @@ create_image(struct vk_bundle *vk, const struct xrt_swapchain_create_info *info, }; CHAIN(format_android); - // Android can't allocate native sRGB. - // Use UNORM and correct gamma later. if (image_format == VK_FORMAT_R8G8B8A8_SRGB) { + // Some versions of Android can't allocate native sRGB, use UNORM and correct gamma later. image_format = VK_FORMAT_R8G8B8A8_UNORM; // https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkImageViewCreateInfo-image-01019 @@ -203,6 +201,20 @@ create_image(struct vk_bundle *vk, const struct xrt_swapchain_create_info *info, add_format_non_dup(&flh, VK_FORMAT_R8G8B8A8_UNORM); add_format_non_dup(&flh, VK_FORMAT_R8G8B8A8_SRGB); } + + if (vk_csci_is_format_supported(vk, image_format, info->bits)) { + // Format is supported, no need for VkExternalFormatANDROID + format_android.externalFormat = 0; + assert(a_buffer_format_props.format != VK_FORMAT_UNDEFINED); // Make sure there is a Vulkan format. + } else if (image_usage != VK_IMAGE_USAGE_SAMPLED_BIT && !vk->has_ANDROID_external_format_resolve) { + // VUID-VkImageCreateInfo-pNext-09457 + VK_ERROR( + vk, "VK_ANDROID_external_format_resolve not supported, only VK_IMAGE_USAGE_SAMPLED_BIT is allowed"); + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } else { + VK_ERROR(vk, "Format not supported"); + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } #endif #ifdef VK_KHR_image_format_list @@ -270,7 +282,20 @@ create_image(struct vk_bundle *vk, const struct xrt_swapchain_create_info *info, .pNext = &memory_dedicated_requirements, }; + VkMemoryRequirements *requirements; +#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER) + // VUID-VkImageMemoryRequirementsInfo2-image-01897 + // VUID-VkMemoryAllocateInfo-pNext-01874 + // Use the requirements from the VkAndroidHardwareBufferPropertiesANDROID instead of querying them + VkMemoryRequirements android_memory_requirements = { + .size = a_buffer_props.allocationSize, + .memoryTypeBits = a_buffer_props.memoryTypeBits, + }; + requirements = &android_memory_requirements; +#else vk->vkGetImageMemoryRequirements2(vk->device, &memory_requirements_info, &memory_requirements); + requirements = &memory_requirements.memoryRequirements; +#endif /* * On tegra we must not use dedicated allocation when it is only preferred to avoid black textures and driver @@ -312,11 +337,10 @@ create_image(struct vk_bundle *vk, const struct xrt_swapchain_create_info *info, ret = vk_alloc_and_bind_image_memory( // vk, // vk_bundle image, // image - SIZE_MAX, // max_size + requirements, // requirements &export_alloc_info, // pNext_for_allocate "vk_image_allocator::create_image", // caller_name - &device_memory, // out_mem - &size); // out_size + &device_memory); // out_mem if (ret != VK_SUCCESS) { vk->vkDestroyImage(vk->device, image, NULL); return ret; @@ -324,7 +348,7 @@ create_image(struct vk_bundle *vk, const struct xrt_swapchain_create_info *info, out_image->handle = image; out_image->memory = device_memory; - out_image->size = size; + out_image->size = memory_requirements.memoryRequirements.size; out_image->use_dedicated_allocation = use_dedicated_allocation; return ret;