[vulkan] Improved implementation of VK_FUCHSIA_buffer_collection
Adds support for memory import from buffer collections.
Change-Id: Ic1ef3eabd9e390c7d39f991a468d4c1ff85f8cff
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index e81db4a..01ad42b 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -33,6 +33,17 @@
uint32_t handle;
} VkImportMemoryZirconHandleInfoFUCHSIA;
+typedef uint32_t VkBufferCollectionFUCHSIA;
+
+typedef struct VkImportMemoryBufferCollectionFUCHSIA {
+ VkStructureType sType;
+ const void* pNext;
+ VkBufferCollectionFUCHSIA collection;
+ uint32_t index;
+} VkImportMemoryBufferCollectionFUCHSIA;
+
+#define VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA \
+ ((VkStructureType)1001000000)
#define VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA \
((VkStructureType)1001000000)
#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA \
@@ -1487,9 +1498,9 @@
VkImportColorBufferGOOGLE importCbInfo = {
VK_STRUCTURE_TYPE_IMPORT_COLOR_BUFFER_GOOGLE, 0,
};
- VkImportPhysicalAddressGOOGLE importPhysAddrInfo = {
- VK_STRUCTURE_TYPE_IMPORT_PHYSICAL_ADDRESS_GOOGLE, 0,
- };
+ // VkImportPhysicalAddressGOOGLE importPhysAddrInfo = {
+ // VK_STRUCTURE_TYPE_IMPORT_PHYSICAL_ADDRESS_GOOGLE, 0,
+ // };
vk_struct_common* structChain =
structChain = vk_init_struct_chain(
@@ -1504,7 +1515,11 @@
(VkImportAndroidHardwareBufferInfoANDROID*)vk_find_struct((vk_struct_common*)pAllocateInfo,
VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID);
- VkImportMemoryZirconHandleInfoFUCHSIA* importPhysAddrInfoPtr =
+ VkImportMemoryBufferCollectionFUCHSIA* importBufferCollectionInfoPtr =
+ (VkImportMemoryBufferCollectionFUCHSIA*)vk_find_struct((vk_struct_common*)pAllocateInfo,
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA);
+
+ VkImportMemoryZirconHandleInfoFUCHSIA* importVmoInfoPtr =
(VkImportMemoryZirconHandleInfoFUCHSIA*)vk_find_struct((vk_struct_common*)pAllocateInfo,
VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA);
@@ -1515,13 +1530,14 @@
bool shouldPassThroughDedicatedAllocInfo =
!exportAllocateInfoPtr &&
!importAhbInfoPtr &&
- !importPhysAddrInfoPtr &&
+ !importBufferCollectionInfoPtr &&
+ !importVmoInfoPtr &&
!isHostVisibleMemoryTypeIndexForGuest(
&mHostVisibleMemoryVirtInfo,
pAllocateInfo->memoryTypeIndex);
if (!exportAllocateInfoPtr &&
- (importAhbInfoPtr || importPhysAddrInfoPtr) &&
+ (importAhbInfoPtr || importBufferCollectionInfoPtr || importVmoInfoPtr) &&
dedicatedAllocInfoPtr &&
isHostVisibleMemoryTypeIndexForGuest(
&mHostVisibleMemoryVirtInfo,
@@ -1543,11 +1559,11 @@
// State needed for import/export.
bool exportAhb = false;
- bool exportPhysAddr = false;
+ bool exportVmo = false;
bool importAhb = false;
- bool importPhysAddr = false;
- (void)exportPhysAddr;
- (void)importPhysAddr;
+ bool importBufferCollection = false;
+ bool importVmo = false;
+ (void)exportVmo;
// Even if we export allocate, the underlying operation
// for the host is always going to be an import operation.
@@ -1566,13 +1582,15 @@
exportAhb =
exportAllocateInfoPtr->handleTypes &
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
- exportPhysAddr =
+ exportVmo =
exportAllocateInfoPtr->handleTypes &
VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA;
} else if (importAhbInfoPtr) {
importAhb = true;
- } else if (importPhysAddrInfoPtr) {
- importPhysAddr = true;
+ } else if (importBufferCollectionInfoPtr) {
+ importBufferCollection = true;
+ } else if (importVmoInfoPtr) {
+ importVmo = true;
}
if (exportAhb) {
@@ -1653,8 +1671,33 @@
vk_append_struct(structChain, (vk_struct_common*)(&importCbInfo));
}
- if (importPhysAddr) {
- vmo_handle = importPhysAddrInfoPtr->handle;
+ if (importBufferCollection) {
+
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ auto collection = reinterpret_cast<fuchsia::sysmem::BufferCollectionSyncPtr*>(
+ importBufferCollectionInfoPtr->collection);
+ fuchsia::sysmem::BufferCollectionInfo_2 info;
+ zx_status_t status2;
+ zx_status_t status = (*collection)->WaitForBuffersAllocated(&status2, &info);
+ if (status != ZX_OK || status2 != ZX_OK) {
+ ALOGE("WaitForBuffersAllocated failed: %d %d", status);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+ uint32_t index = importBufferCollectionInfoPtr->index;
+ if (info.buffer_count < index) {
+ ALOGE("Invalid buffer index: %d %d", index);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+ vmo_handle = info.buffers[index].vmo.release();
+#endif
+
+ }
+
+ if (importVmo) {
+ vmo_handle = importVmoInfoPtr->handle;
+ }
+
+ if (vmo_handle != ZX_HANDLE_INVALID) {
uint64_t cb = 0;
#ifdef VK_USE_PLATFORM_FUCHSIA
@@ -1668,7 +1711,7 @@
}
}
- // TODO if (exportPhysAddr) { }
+ // TODO if (exportVmo) { }
if (!isHostVisibleMemoryTypeIndexForGuest(
&mHostVisibleMemoryVirtInfo,
@@ -1739,12 +1782,12 @@
// Host visible memory with direct mapping via
// VkImportPhysicalAddressGOOGLE
- if (importPhysAddr) {
+ // if (importPhysAddr) {
// vkAllocateMemory(device, &finalAllocInfo, pAllocator, pMemory);
// host maps the host pointer to the guest physical address
// TODO: the host side page offset of the
// host pointer needs to be returned somehow.
- }
+ // }
// Host visible memory with direct mapping
AutoLock lock(mLock);
@@ -2059,6 +2102,12 @@
vk_find_struct(
(vk_struct_common*)pCreateInfo_mut,
VK_STRUCTURE_TYPE_FUCHSIA_IMAGE_FORMAT_FUCHSIA);
+
+ VkBufferCollectionImageCreateInfoFUCHSIA* extBufferCollectionPtr =
+ (VkBufferCollectionImageCreateInfoFUCHSIA*)
+ vk_find_struct(
+ (vk_struct_common*)pCreateInfo_mut,
+ VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA);
#endif
vk_struct_common* structChain =
@@ -2111,7 +2160,22 @@
abort();
}
pCreateInfo_mut->pNext = &native_info;
- if (extFuchsiaImageFormatPtr) {
+
+ bool is_physically_contiguous = false;
+ if (extBufferCollectionPtr) {
+ auto collection = reinterpret_cast<fuchsia::sysmem::BufferCollectionSyncPtr*>(
+ extBufferCollectionPtr->collection);
+ fuchsia::sysmem::BufferCollectionInfo_2 info;
+ zx_status_t status2;
+ zx_status_t status = (*collection)->WaitForBuffersAllocated(&status2, &info);
+ if (status == ZX_OK && status2 == ZX_OK) {
+ is_physically_contiguous =
+ info.settings.has_image_format_constraints &&
+ info.settings.buffer_settings.is_physically_contiguous;
+ } else {
+ ALOGE("WaitForBuffersAllocated failed: %d %d", status, status2);
+ }
+ } else if (extFuchsiaImageFormatPtr) {
auto imageFormat = static_cast<const uint8_t*>(
extFuchsiaImageFormatPtr->imageFormat);
size_t imageFormatSize =
@@ -2134,14 +2198,17 @@
fuchsia::sysmem::SingleBufferSettings settings;
fuchsia::sysmem::SingleBufferSettings::Decode(
&decoder, &settings, 0);
- if (settings.buffer_settings.is_physically_contiguous) {
- // Replace the local image pCreateInfo_mut format
- // with the color buffer format if physically contiguous
- // and a potential display layer candidate.
- // TODO(reveman): Remove this after adding BGRA color
- // buffer support.
- pCreateInfo_mut->format = VK_FORMAT_R8G8B8A8_UNORM;
- }
+ is_physically_contiguous =
+ settings.buffer_settings.is_physically_contiguous;
+ }
+
+ if (is_physically_contiguous) {
+ // Replace the local image pCreateInfo_mut format
+ // with the color buffer format if physically contiguous
+ // and a potential display layer candidate.
+ // TODO(reveman): Remove this after adding BGRA color
+ // buffer support.
+ pCreateInfo_mut->format = VK_FORMAT_R8G8B8A8_UNORM;
}
}
#endif