From 752ea7f6df0c938d6b132adbf18fbc5ca621ef50 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 6 Aug 2025 04:24:32 +0000 Subject: [PATCH] panvk: resolve ANB (pre spec v8) Before ANB spec v8, all ANB images are created and fully initialized upon panvk_CreateImage. Acked-by: Lars-Ivar Hesselberg Simonsen Reviewed-by: Faith Ekstrand Part-of: --- src/panfrost/vulkan/panvk_android.c | 161 +++++++++++++++++++++++++++- src/panfrost/vulkan/panvk_image.c | 2 +- src/panfrost/vulkan/panvk_image.h | 3 + 3 files changed, 164 insertions(+), 2 deletions(-) diff --git a/src/panfrost/vulkan/panvk_android.c b/src/panfrost/vulkan/panvk_android.c index 363e8130cbb..8df3d506052 100644 --- a/src/panfrost/vulkan/panvk_android.c +++ b/src/panfrost/vulkan/panvk_android.c @@ -5,8 +5,12 @@ #include "panvk_android.h" +#include "panvk_device.h" + #include "vulkan/vk_android_native_buffer.h" +#include "vk_alloc.h" +#include "vk_android.h" #include "vk_util.h" bool @@ -45,12 +49,142 @@ panvk_android_create_deferred_image(VkDevice device, return VK_ERROR_FEATURE_NOT_PRESENT; } +static inline uint32_t +panvk_android_get_fd_mem_type_bits(VkDevice dev_handle, int dma_buf_fd) +{ + VK_FROM_HANDLE(vk_device, dev, dev_handle); + + VkMemoryFdPropertiesKHR fd_props = { + .sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR, + }; + VkResult result = dev->dispatch_table.GetMemoryFdPropertiesKHR( + dev_handle, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, dma_buf_fd, + &fd_props); + return result == VK_SUCCESS ? fd_props.memoryTypeBits : 0; +} + +static VkResult +panvk_android_get_image_mem_reqs(VkDevice dev_handle, VkImage img_handle, + int dma_buf_fd, + VkMemoryRequirements *out_mem_reqs) +{ + VK_FROM_HANDLE(vk_device, dev, dev_handle); + VkMemoryRequirements mem_reqs; + + dev->dispatch_table.GetImageMemoryRequirements(dev_handle, img_handle, + &mem_reqs); + + const uint32_t fd_mem_type_bits = + panvk_android_get_fd_mem_type_bits(dev_handle, dma_buf_fd); + + if (!(mem_reqs.memoryTypeBits & fd_mem_type_bits)) { + return panvk_errorf(dev_handle, VK_ERROR_INVALID_EXTERNAL_HANDLE, + "No compatible mem type: img req (%u), fd req (%u)", + mem_reqs.memoryTypeBits, fd_mem_type_bits); + } + + mem_reqs.memoryTypeBits &= fd_mem_type_bits; + *out_mem_reqs = mem_reqs; + + return VK_SUCCESS; +} + +static VkResult +panvk_android_import_anb_memory(VkDevice dev_handle, VkImage img_handle, + const VkNativeBufferANDROID *anb, + const VkAllocationCallbacks *alloc) +{ + VK_FROM_HANDLE(vk_device, dev, dev_handle); + VK_FROM_HANDLE(panvk_image, img, img_handle); + VkMemoryRequirements mem_reqs; + VkResult result; + + assert(anb && anb->handle && anb->handle->numFds > 0); + + int dma_buf_fd = anb->handle->data[0]; + result = panvk_android_get_image_mem_reqs(dev_handle, img_handle, dma_buf_fd, + &mem_reqs); + if (result != VK_SUCCESS) + return result; + + int dup_fd = os_dupfd_cloexec(dma_buf_fd); + if (dup_fd < 0) { + return (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS + : VK_ERROR_OUT_OF_HOST_MEMORY; + } + + const VkMemoryDedicatedAllocateInfo dedicated_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + .image = img_handle, + }; + const VkImportMemoryFdInfoKHR fd_info = { + .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, + .pNext = &dedicated_info, + .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + .fd = dup_fd, + }; + const VkMemoryAllocateInfo alloc_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = &fd_info, + .allocationSize = mem_reqs.size, + .memoryTypeIndex = ffs(mem_reqs.memoryTypeBits) - 1, + }; + result = dev->dispatch_table.AllocateMemory(dev_handle, &alloc_info, alloc, + &img->vk.anb_memory); + if (result != VK_SUCCESS) { + close(dup_fd); + return result; + } + + return VK_SUCCESS; +} + +static VkResult +panvk_android_anb_init(struct panvk_device *dev, VkImageCreateInfo *create_info, + const VkNativeBufferANDROID *anb, + const VkAllocationCallbacks *alloc, + struct panvk_image *img) +{ + VkResult result; + + VkImageDrmFormatModifierExplicitCreateInfoEXT mod_info; + VkSubresourceLayout layouts[PANVK_MAX_PLANES]; + assert(vk_find_struct_const(create_info->pNext, NATIVE_BUFFER_ANDROID)); + result = vk_android_get_anb_layout(create_info, &mod_info, layouts, + PANVK_MAX_PLANES); + if (result != VK_SUCCESS) + return result; + + mod_info.pNext = create_info->pNext; + const VkExternalMemoryImageCreateInfo external_info = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, + .pNext = &mod_info, + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + }; + + /* create_info is a already local copy from the caller */ + create_info->pNext = &external_info; + result = panvk_image_init(img, create_info); + if (result != VK_SUCCESS) + return result; + + result = panvk_android_import_anb_memory( + panvk_device_to_handle(dev), panvk_image_to_handle(img), anb, alloc); + if (result != VK_SUCCESS) + return result; + + return VK_SUCCESS; +} + VkResult panvk_android_create_gralloc_image(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImage *pImage) { + VK_FROM_HANDLE(panvk_device, dev, device); + VkResult result; + const VkNativeBufferANDROID *anb = vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID); if (!anb) { @@ -58,5 +192,30 @@ panvk_android_create_gralloc_image(VkDevice device, pAllocator, pImage); } - return VK_ERROR_FEATURE_NOT_PRESENT; + struct panvk_image *img = + vk_image_create(&dev->vk, pCreateInfo, pAllocator, sizeof(*img)); + if (!img) + return panvk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + + VkImageCreateInfo create_info = *pCreateInfo; + create_info.tiling = img->vk.tiling = + VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; + + result = panvk_android_anb_init(dev, &create_info, anb, pAllocator, img); + if (result != VK_SUCCESS) { + vk_image_destroy(&dev->vk, pAllocator, &img->vk); + return panvk_error(device, result); + } + + VkImage img_handle = panvk_image_to_handle(img); + result = dev->vk.dispatch_table.BindImageMemory(device, img_handle, + img->vk.anb_memory, 0); + if (result != VK_SUCCESS) { + dev->vk.dispatch_table.DestroyImage(device, img_handle, pAllocator); + return panvk_error(device, result); + } + + *pImage = img_handle; + + return VK_SUCCESS; } diff --git a/src/panfrost/vulkan/panvk_image.c b/src/panfrost/vulkan/panvk_image.c index b4213807ff8..cde42191f48 100644 --- a/src/panfrost/vulkan/panvk_image.c +++ b/src/panfrost/vulkan/panvk_image.c @@ -400,7 +400,7 @@ panvk_image_get_total_size(const struct panvk_image *image) return size; } -static VkResult +VkResult panvk_image_init(struct panvk_image *image, const VkImageCreateInfo *pCreateInfo) { diff --git a/src/panfrost/vulkan/panvk_image.h b/src/panfrost/vulkan/panvk_image.h index b0fc5105db3..e65e0d16e21 100644 --- a/src/panfrost/vulkan/panvk_image.h +++ b/src/panfrost/vulkan/panvk_image.h @@ -62,4 +62,7 @@ panvk_plane_index(VkFormat format, VkImageAspectFlags aspect_mask) } } +VkResult panvk_image_init(struct panvk_image *image, + const VkImageCreateInfo *pCreateInfo); + #endif