mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-18 22:28:06 +02:00
Implement as a layer on top, and can be resilient to core panvk changes later. e.g. more and strict memory types, need dedicated info, etc. Acked-by: Lars-Ivar Hesselberg Simonsen <lars-ivar.simonsen@arm.com> Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36603>
537 lines
19 KiB
C
537 lines
19 KiB
C
/*
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "panvk_android.h"
|
|
|
|
#include "panvk_device.h"
|
|
|
|
#include "vndk/hardware_buffer.h"
|
|
#include "vulkan/vk_android_native_buffer.h"
|
|
|
|
#include "vk_alloc.h"
|
|
#include "vk_android.h"
|
|
#include "vk_device_memory.h"
|
|
#include "vk_util.h"
|
|
|
|
bool
|
|
panvk_android_is_gralloc_image(const VkImageCreateInfo *pCreateInfo)
|
|
{
|
|
vk_foreach_struct_const(ext, pCreateInfo->pNext) {
|
|
switch ((uint32_t)ext->sType) {
|
|
case VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID:
|
|
return true;
|
|
case VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR: {
|
|
const VkImageSwapchainCreateInfoKHR *swapchain_info = (void *)ext;
|
|
if (swapchain_info->swapchain != VK_NULL_HANDLE)
|
|
return true;
|
|
break;
|
|
}
|
|
case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO: {
|
|
const VkExternalMemoryImageCreateInfo *external_info = (void *)ext;
|
|
if (external_info->handleTypes &
|
|
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
|
|
return true;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
struct panvk_android_deferred_image {
|
|
struct panvk_image base;
|
|
|
|
VkImageCreateInfo *create_info;
|
|
bool initialized;
|
|
};
|
|
|
|
static VkResult
|
|
panvk_android_create_deferred_image(VkDevice device,
|
|
const VkImageCreateInfo *pCreateInfo,
|
|
const VkAllocationCallbacks *pAllocator,
|
|
VkImage *pImage)
|
|
{
|
|
VK_FROM_HANDLE(panvk_device, dev, device);
|
|
|
|
/* collect all dynamic array infos */
|
|
uint32_t queue_family_count = 0;
|
|
uint32_t view_format_count = 0;
|
|
|
|
if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT)
|
|
queue_family_count = pCreateInfo->queueFamilyIndexCount;
|
|
|
|
const VkImageFormatListCreateInfo *raw_list =
|
|
vk_find_struct_const(pCreateInfo->pNext, IMAGE_FORMAT_LIST_CREATE_INFO);
|
|
if (raw_list)
|
|
view_format_count = raw_list->viewFormatCount;
|
|
|
|
/* Extend below when panvk supports more extensions that interact with ANB or
|
|
* AHB. e.g. VK_EXT_image_compression_control
|
|
*/
|
|
VK_MULTIALLOC(ma);
|
|
VK_MULTIALLOC_DECL(&ma, struct panvk_android_deferred_image, deferred, 1);
|
|
VK_MULTIALLOC_DECL(&ma, VkImageCreateInfo, create_info, 1);
|
|
VK_MULTIALLOC_DECL(&ma, VkImageFormatListCreateInfo, list_info, 1);
|
|
VK_MULTIALLOC_DECL(&ma, VkImageStencilUsageCreateInfo, stencil_info, 1);
|
|
VK_MULTIALLOC_DECL(&ma, uint32_t, queue_families, queue_family_count);
|
|
VK_MULTIALLOC_DECL(&ma, uint32_t, view_formats, view_format_count);
|
|
|
|
if (!vk_multialloc_zalloc2(&ma, &dev->vk.alloc, pAllocator,
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
|
|
return panvk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
vk_image_init(&dev->vk, &deferred->base.vk, pCreateInfo);
|
|
|
|
/* prepare the deferred VkImageCreateInfo chain */
|
|
*create_info = *pCreateInfo;
|
|
create_info->pNext = NULL;
|
|
/* Assign resolved AHB external format */
|
|
create_info->format = deferred->base.vk.format;
|
|
create_info->tiling = deferred->base.vk.tiling =
|
|
VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
|
|
if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
|
|
typed_memcpy(queue_families, pCreateInfo->pQueueFamilyIndices,
|
|
pCreateInfo->queueFamilyIndexCount);
|
|
create_info->pQueueFamilyIndices = queue_families;
|
|
}
|
|
|
|
/* Per spec section 12.3. Images
|
|
*
|
|
* - If tiling is VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT and flags contains
|
|
* VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, then the pNext chain must include a
|
|
* VkImageFormatListCreateInfo structure with non-zero viewFormatCount.
|
|
*
|
|
* ANB and aliased ANB always chain proper format list for mutable swapchain
|
|
* image support, but AHB is allowed to mutate without an explicit format
|
|
* list due to legacy spec issue. So we chain a view format of the create
|
|
* format itself to satisfy VK_EXT_image_drm_format_modifier VUs.
|
|
*/
|
|
if (view_format_count ||
|
|
deferred->base.vk.create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
|
|
if (view_format_count) {
|
|
typed_memcpy(view_formats, raw_list->pViewFormats, view_format_count);
|
|
} else {
|
|
view_format_count = 1;
|
|
view_formats = &create_info->format;
|
|
}
|
|
*list_info = (VkImageFormatListCreateInfo){
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
|
|
.viewFormatCount = view_format_count,
|
|
.pViewFormats = view_formats,
|
|
};
|
|
__vk_append_struct(create_info, list_info);
|
|
}
|
|
|
|
if (deferred->base.vk.stencil_usage) {
|
|
*stencil_info = (VkImageStencilUsageCreateInfo){
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO,
|
|
.stencilUsage = deferred->base.vk.stencil_usage,
|
|
};
|
|
__vk_append_struct(create_info, stencil_info);
|
|
}
|
|
|
|
deferred->create_info = create_info;
|
|
*pImage = panvk_image_to_handle(&deferred->base);
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
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_get_buffer_mem_reqs(VkDevice dev_handle, VkBuffer buf_handle,
|
|
int dma_buf_fd,
|
|
VkMemoryRequirements *out_mem_reqs)
|
|
{
|
|
VK_FROM_HANDLE(vk_device, dev, dev_handle);
|
|
VkMemoryRequirements mem_reqs;
|
|
|
|
dev->dispatch_table.GetBufferMemoryRequirements(dev_handle, buf_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: buf 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) {
|
|
return panvk_android_create_deferred_image(device, pCreateInfo,
|
|
pAllocator, pImage);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
VkResult
|
|
panvk_android_get_wsi_memory(struct panvk_device *dev,
|
|
const VkBindImageMemoryInfo *bind_info,
|
|
VkDeviceMemory *out_mem_handle)
|
|
{
|
|
VK_FROM_HANDLE(panvk_image, img, bind_info->image);
|
|
VkResult result;
|
|
|
|
struct panvk_android_deferred_image *deferred =
|
|
container_of(img, struct panvk_android_deferred_image, base);
|
|
assert(deferred->create_info && !deferred->initialized);
|
|
|
|
const VkNativeBufferANDROID *anb =
|
|
vk_find_struct_const(bind_info->pNext, NATIVE_BUFFER_ANDROID);
|
|
|
|
/* Inject ANB into the deferred pNext chain to leverage the existing common
|
|
* Android helper vk_android_get_anb_layout, which could be refactored to
|
|
* take ANB directly instead.
|
|
*/
|
|
VkNativeBufferANDROID local_anb = *anb;
|
|
local_anb.pNext = deferred->create_info->pNext;
|
|
deferred->create_info->pNext = &local_anb;
|
|
result = panvk_android_anb_init(dev, deferred->create_info, anb,
|
|
&dev->vk.alloc, img);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
|
|
deferred->initialized = true;
|
|
*out_mem_handle = img->vk.anb_memory;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
static VkResult
|
|
panvk_android_ahb_image_init(struct AHardwareBuffer *ahb,
|
|
struct panvk_image *img)
|
|
{
|
|
VkResult result;
|
|
|
|
struct panvk_android_deferred_image *deferred =
|
|
container_of(img, struct panvk_android_deferred_image, base);
|
|
assert(deferred->create_info && !deferred->initialized);
|
|
|
|
VkImageDrmFormatModifierExplicitCreateInfoEXT mod_info;
|
|
VkSubresourceLayout layouts[PANVK_MAX_PLANES];
|
|
result =
|
|
vk_android_get_ahb_layout(ahb, &mod_info, layouts, PANVK_MAX_PLANES);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
__vk_append_struct(deferred->create_info, &mod_info);
|
|
|
|
VkExternalMemoryImageCreateInfo external_info = {
|
|
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
|
|
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
|
|
};
|
|
__vk_append_struct(deferred->create_info, &external_info);
|
|
|
|
result = panvk_image_init(img, deferred->create_info);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
|
|
deferred->initialized = true;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
static VkResult
|
|
panvk_android_import_ahb_memory(VkDevice device,
|
|
const VkMemoryAllocateInfo *pAllocateInfo,
|
|
struct AHardwareBuffer *ahb,
|
|
const VkAllocationCallbacks *pAllocator,
|
|
VkDeviceMemory *pMemory)
|
|
{
|
|
VK_FROM_HANDLE(vk_device, dev, device);
|
|
const native_handle_t *handle = AHardwareBuffer_getNativeHandle(ahb);
|
|
assert(handle && handle->numFds > 0);
|
|
int dma_buf_fd = handle->data[0];
|
|
VkResult result;
|
|
|
|
VkImage img_handle = VK_NULL_HANDLE;
|
|
VkBuffer buf_handle = VK_NULL_HANDLE;
|
|
VkMemoryRequirements mem_reqs;
|
|
|
|
/* Fix allocationSize and memoryTypeIndex. */
|
|
const VkMemoryDedicatedAllocateInfo *dedicated_info = vk_find_struct_const(
|
|
pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
|
|
if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
|
|
img_handle = dedicated_info->image;
|
|
VK_FROM_HANDLE(panvk_image, img, img_handle);
|
|
result = panvk_android_ahb_image_init(ahb, img);
|
|
if (result == VK_SUCCESS) {
|
|
result = panvk_android_get_image_mem_reqs(device, img_handle,
|
|
dma_buf_fd, &mem_reqs);
|
|
}
|
|
} else if (dedicated_info && dedicated_info->buffer != VK_NULL_HANDLE) {
|
|
buf_handle = dedicated_info->buffer;
|
|
result = panvk_android_get_buffer_mem_reqs(device, buf_handle, dma_buf_fd,
|
|
&mem_reqs);
|
|
} else {
|
|
mem_reqs.size = pAllocateInfo->allocationSize;
|
|
mem_reqs.memoryTypeBits =
|
|
panvk_android_get_fd_mem_type_bits(device, dma_buf_fd);
|
|
result = mem_reqs.memoryTypeBits ? VK_SUCCESS
|
|
: VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
}
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
|
|
/* Override to a compatible memory type if needed. */
|
|
uint32_t mem_type_index = pAllocateInfo->memoryTypeIndex;
|
|
if (!((1 << mem_type_index) & mem_reqs.memoryTypeBits))
|
|
mem_type_index = ffs(mem_reqs.memoryTypeBits) - 1;
|
|
|
|
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;
|
|
}
|
|
|
|
/* Always chain dedicated info for simplicity, since the spec allows both
|
|
* image and buffer to be VK_NULL_HANDLE.
|
|
*/
|
|
const VkMemoryDedicatedAllocateInfo local_dedicated_info = {
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
|
|
.image = img_handle,
|
|
.buffer = buf_handle,
|
|
};
|
|
const VkImportMemoryFdInfoKHR fd_info = {
|
|
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
|
|
.pNext = &local_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 = mem_type_index,
|
|
};
|
|
result = dev->dispatch_table.AllocateMemory(device, &alloc_info, pAllocator,
|
|
pMemory);
|
|
if (result != VK_SUCCESS)
|
|
close(dup_fd);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
panvk_android_is_ahb_memory(const VkMemoryAllocateInfo *pAllocateInfo)
|
|
{
|
|
vk_foreach_struct_const(ext, pAllocateInfo->pNext) {
|
|
switch (ext->sType) {
|
|
case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID:
|
|
return true;
|
|
case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
|
|
return ((const VkExportMemoryAllocateInfo *)ext)->handleTypes ==
|
|
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
VkResult
|
|
panvk_android_allocate_ahb_memory(VkDevice device,
|
|
const VkMemoryAllocateInfo *pAllocateInfo,
|
|
const VkAllocationCallbacks *pAllocator,
|
|
VkDeviceMemory *pMemory)
|
|
{
|
|
struct AHardwareBuffer *ahb;
|
|
VkResult result;
|
|
|
|
const VkImportAndroidHardwareBufferInfoANDROID *ahb_info =
|
|
vk_find_struct_const(pAllocateInfo->pNext,
|
|
IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID);
|
|
if (ahb_info) {
|
|
ahb = ahb_info->buffer;
|
|
AHardwareBuffer_acquire(ahb);
|
|
} else {
|
|
ahb = vk_alloc_ahardware_buffer(pAllocateInfo);
|
|
if (!ahb)
|
|
return panvk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
}
|
|
|
|
result = panvk_android_import_ahb_memory(device, pAllocateInfo, ahb,
|
|
pAllocator, pMemory);
|
|
if (result != VK_SUCCESS) {
|
|
AHardwareBuffer_release(ahb);
|
|
return panvk_error(device, result);
|
|
}
|
|
|
|
VK_FROM_HANDLE(vk_device_memory, mem, *pMemory);
|
|
assert(!mem->ahardware_buffer);
|
|
mem->ahardware_buffer = ahb;
|
|
|
|
return VK_SUCCESS;
|
|
}
|