mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-20 16:00:08 +01:00
panvk: implement AHB image deferred init and memory alloc
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>
This commit is contained in:
parent
33ab9d8320
commit
66bbd9eec8
2 changed files with 217 additions and 0 deletions
|
|
@ -7,10 +7,12 @@
|
|||
|
||||
#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
|
||||
|
|
@ -87,6 +89,8 @@ panvk_android_create_deferred_image(VkDevice device,
|
|||
/* 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) {
|
||||
|
|
@ -176,6 +180,32 @@ panvk_android_get_image_mem_reqs(VkDevice dev_handle, VkImage img_handle,
|
|||
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,
|
||||
|
|
@ -339,3 +369,169 @@ panvk_android_get_wsi_memory(struct panvk_device *dev,
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@ VkResult panvk_android_get_wsi_memory(struct panvk_device *dev,
|
|||
const VkBindImageMemoryInfo *bind_info,
|
||||
VkDeviceMemory *out_mem_handle);
|
||||
|
||||
bool panvk_android_is_ahb_memory(const VkMemoryAllocateInfo *pAllocateInfo);
|
||||
|
||||
VkResult panvk_android_allocate_ahb_memory(
|
||||
VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
|
||||
const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory);
|
||||
|
||||
#else /* VK_USE_PLATFORM_ANDROID_KHR */
|
||||
|
||||
static inline bool
|
||||
|
|
@ -50,6 +56,21 @@ panvk_android_get_wsi_memory(struct panvk_device *dev,
|
|||
return VK_ERROR_FEATURE_NOT_PRESENT;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
panvk_android_is_ahb_memory(const VkMemoryAllocateInfo *pAllocateInfo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline VkResult
|
||||
panvk_android_allocate_ahb_memory(VkDevice device,
|
||||
const VkMemoryAllocateInfo *pAllocateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkDeviceMemory *pMemory)
|
||||
{
|
||||
return VK_ERROR_FEATURE_NOT_PRESENT;
|
||||
}
|
||||
|
||||
#endif /* VK_USE_PLATFORM_ANDROID_KHR */
|
||||
|
||||
#endif /* PANVK_ANDROID_H */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue