diff --git a/src/virtio/vulkan/vn_android.c b/src/virtio/vulkan/vn_android.c index 72c483833ce..8ddf4c9c068 100644 --- a/src/virtio/vulkan/vn_android.c +++ b/src/virtio/vulkan/vn_android.c @@ -935,7 +935,8 @@ vn_android_device_import_ahb(struct vn_device *dev, struct vn_device_memory *mem, const VkMemoryAllocateInfo *alloc_info, const VkAllocationCallbacks *alloc, - struct AHardwareBuffer *ahb) + struct AHardwareBuffer *ahb, + bool internal_ahb) { VkDevice device = vn_device_to_handle(dev); const VkMemoryDedicatedAllocateInfo *dedicated_info = @@ -945,6 +946,7 @@ vn_android_device_import_ahb(struct vn_device *dev, int dup_fd = -1; uint64_t alloc_size = 0; uint32_t mem_type_bits = 0; + uint32_t mem_type_index = alloc_info->memoryTypeIndex; bool force_unmappable = false; VkResult result = VK_SUCCESS; @@ -958,12 +960,6 @@ vn_android_device_import_ahb(struct vn_device *dev, if (result != VK_SUCCESS) return result; - if (((1 << alloc_info->memoryTypeIndex) & mem_type_bits) == 0) { - vn_log(dev->instance, "memoryTypeIndex(%u) mem_type_bits(0x%X)", - alloc_info->memoryTypeIndex, mem_type_bits); - return VK_ERROR_INVALID_EXTERNAL_HANDLE; - } - /* If ahb is for an image, finish the deferred image creation first */ if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) { struct vn_image *img = vn_image_from_handle(dedicated_info->image); @@ -989,6 +985,23 @@ vn_android_device_import_ahb(struct vn_device *dev, alloc_size = mem_req.size; + /* XXX Workaround before spec issue #2762 gets resolved. If importing an + * internally allocated AHB from the exportable path, memoryTypeIndex is + * undefined while defaulting to zero, which can be incompatible with + * the queried memoryTypeBits from the combined memory requirement and + * dma_buf fd properties. Thus we override the requested memoryTypeIndex + * to an applicable one if existed. + */ + if (internal_ahb) { + if ((mem_type_bits & mem_req.memoryTypeBits) == 0) { + vn_log(dev->instance, "memoryTypeBits: img(0x%X) fd(0x%X)", + mem_req.memoryTypeBits, mem_type_bits); + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } + + mem_type_index = ffs(mem_type_bits & mem_req.memoryTypeBits) - 1; + } + /* XXX Workaround before we use cross-domain backend in minigbm. The * blob_mem allocated from virgl backend can have a queried guest mappable * size smaller than the size returned from image memory requirement. @@ -1008,8 +1021,12 @@ vn_android_device_import_ahb(struct vn_device *dev, } alloc_size = mem_req.size; + + assert((1 << mem_type_index) & mem_req.memoryTypeBits); } + assert((1 << mem_type_index) & mem_type_bits); + errno = 0; dup_fd = os_dupfd_cloexec(dma_buf_fd); if (dup_fd < 0) @@ -1031,7 +1048,7 @@ vn_android_device_import_ahb(struct vn_device *dev, .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .pNext = dedicated_info, .allocationSize = alloc_size, - .memoryTypeIndex = alloc_info->memoryTypeIndex, + .memoryTypeIndex = mem_type_index, }; result = vn_device_memory_import_dma_buf(dev, mem, &local_alloc_info, force_unmappable, dup_fd); @@ -1091,7 +1108,7 @@ vn_android_device_allocate_ahb(struct vn_device *dev, return VK_ERROR_OUT_OF_HOST_MEMORY; VkResult result = - vn_android_device_import_ahb(dev, mem, alloc_info, alloc, ahb); + vn_android_device_import_ahb(dev, mem, alloc_info, alloc, ahb, true); /* ahb alloc has already acquired a ref and import will acquire another, * must release one here to avoid leak. diff --git a/src/virtio/vulkan/vn_android.h b/src/virtio/vulkan/vn_android.h index 038aec35840..327ff7a674a 100644 --- a/src/virtio/vulkan/vn_android.h +++ b/src/virtio/vulkan/vn_android.h @@ -55,7 +55,8 @@ vn_android_device_import_ahb(struct vn_device *dev, struct vn_device_memory *mem, const VkMemoryAllocateInfo *alloc_info, const VkAllocationCallbacks *alloc, - struct AHardwareBuffer *ahb); + struct AHardwareBuffer *ahb, + bool internal_ahb); VkResult vn_android_device_allocate_ahb(struct vn_device *dev, @@ -125,7 +126,8 @@ vn_android_device_import_ahb(UNUSED struct vn_device *dev, UNUSED struct vn_device_memory *mem, UNUSED const VkMemoryAllocateInfo *alloc_info, UNUSED const VkAllocationCallbacks *alloc, - UNUSED struct AHardwareBuffer *ahb) + UNUSED struct AHardwareBuffer *ahb, + UNUSED bool internal_ahb) { return VK_ERROR_OUT_OF_HOST_MEMORY; } diff --git a/src/virtio/vulkan/vn_device_memory.c b/src/virtio/vulkan/vn_device_memory.c index 5a38cb416f9..44e9054687c 100644 --- a/src/virtio/vulkan/vn_device_memory.c +++ b/src/virtio/vulkan/vn_device_memory.c @@ -354,7 +354,7 @@ vn_AllocateMemory(VkDevice device, VkResult result; if (import_ahb_info) { result = vn_android_device_import_ahb(dev, mem, pAllocateInfo, alloc, - import_ahb_info->buffer); + import_ahb_info->buffer, false); } else if (export_ahb) { result = vn_android_device_allocate_ahb(dev, mem, pAllocateInfo, alloc); } else if (import_fd_info) {