Handle suballocated AHB buffers

VkBuffers backed by AHBs do not require dedicated allocations.
As such, update SupportsAllocateInfo() to report supported as
long as a VkImportAndroidHardwareBufferInfoANDROID or a
VkExportMemoryAllocateInfo with AHB bit was found.

Updates allocateAndroidHardwareBuffer() to treat the lack of a
dedicated buffer or image as a request to allocate a blob AHB.

Bug: b/147316305
Bug: b/169796031
Test: cts -m CtsNativeHardwareTestCases
Test: cts -m CtsDeqpTestCases -t
  dEQP-VK.api.external.memory.android_hardware_buffer.*
Change-Id: Ica2782b4570bd4d4c1e5585b696b40314a267b2f
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/51248
Presubmit-Ready: Jason Macnak <natsu@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Jason Macnak <natsu@google.com>
Commit-Queue: Jason Macnak <natsu@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp b/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp
index f353e8a..729a9d0 100644
--- a/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp
+++ b/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp
@@ -194,16 +194,16 @@
 			break;
 			case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO:
 			{
-				// AHB requires dedicated allocation -- for images, the gralloc gets to decide the image layout,
-				// not us.
 				const auto *dedicatedAllocateInfo = reinterpret_cast<const VkMemoryDedicatedAllocateInfo *>(createInfo);
-				imageHandle = vk::Cast(dedicatedAllocateInfo->image);
-				bufferHandle = vk::Cast(dedicatedAllocateInfo->buffer);
+				dedicatedImageHandle = vk::Cast(dedicatedAllocateInfo->image);
+				dedicatedBufferHandle = vk::Cast(dedicatedAllocateInfo->buffer);
 			}
 			break;
-
 			default:
-				WARN("VkMemoryAllocateInfo->pNext sType = %s", vk::Stringify(createInfo->sType).c_str());
+			{
+				LOG_TRAP("VkMemoryAllocateInfo->pNext sType = %s", vk::Stringify(createInfo->sType).c_str());
+			}
+			break;
 		}
 		createInfo = createInfo->pNext;
 	}
@@ -221,7 +221,7 @@
 }
 
 // VkAllocateMemory
-VkResult AHardwareBufferExternalMemory::allocate(size_t /*size*/, void **pBuffer)
+VkResult AHardwareBufferExternalMemory::allocate(size_t size, void **pBuffer)
 {
 	if(allocateInfo.importAhb)
 	{
@@ -230,7 +230,7 @@
 	else
 	{
 		ASSERT(allocateInfo.exportAhb);
-		return allocateAndroidHardwareBuffer(pBuffer);
+		return allocateAndroidHardwareBuffer(size, pBuffer);
 	}
 }
 
@@ -255,12 +255,11 @@
 	return lockAndroidHardwareBuffer(pBuffer);
 }
 
-VkResult AHardwareBufferExternalMemory::allocateAndroidHardwareBuffer(void **pBuffer)
+VkResult AHardwareBufferExternalMemory::allocateAndroidHardwareBuffer(size_t size, void **pBuffer)
 {
-	if(allocateInfo.imageHandle)
+	if(allocateInfo.dedicatedImageHandle)
 	{
-		vk::Image *image = allocateInfo.imageHandle;
-		ASSERT(image != nullptr);
+		vk::Image *image = allocateInfo.dedicatedImageHandle;
 		ASSERT(image->getArrayLayers() == 1);
 
 		VkExtent3D extent = image->getExtent();
@@ -271,10 +270,9 @@
 		ahbDesc.format = GetAHBFormatFromVkFormat(image->getFormat());
 		ahbDesc.usage = GetAHBUsageFromVkImageFlags(image->getFlags(), image->getUsage());
 	}
-	else
+	else if(allocateInfo.dedicatedBufferHandle)
 	{
-		vk::Buffer *buffer = allocateInfo.bufferHandle;
-		ASSERT(buffer != nullptr);
+		vk::Buffer *buffer = allocateInfo.dedicatedBufferHandle;
 
 		ahbDesc.width = static_cast<uint32_t>(buffer->getSize());
 		ahbDesc.height = 1;
@@ -282,6 +280,18 @@
 		ahbDesc.format = AHARDWAREBUFFER_FORMAT_BLOB;
 		ahbDesc.usage = GetAHBUsageFromVkBufferFlags(buffer->getFlags(), buffer->getUsage());
 	}
+	else
+	{
+		// Android Hardware Buffer Buffer Resources: "Android hardware buffers with a format of
+		// AHARDWAREBUFFER_FORMAT_BLOB and usage that includes AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER can
+		// be used as the backing store for VkBuffer objects. Such Android hardware buffers have a size
+		// in bytes specified by their width; height and layers are both 1."
+		ahbDesc.width = static_cast<uint32_t>(size);
+		ahbDesc.height = 1;
+		ahbDesc.layers = 1;
+		ahbDesc.format = AHARDWAREBUFFER_FORMAT_BLOB;
+		ahbDesc.usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
+	}
 
 	int ret = AHardwareBuffer_allocate(&ahbDesc, &ahb);
 	if(ret != 0)
@@ -297,13 +307,17 @@
 VkResult AHardwareBufferExternalMemory::lockAndroidHardwareBuffer(void **pBuffer)
 {
 	uint64_t usage = 0;
-	if(allocateInfo.imageHandle)
+	if(allocateInfo.dedicatedImageHandle)
 	{
-		usage = GetAHBLockUsageFromVkImageUsageFlags(allocateInfo.imageHandle->getUsage());
+		usage = GetAHBLockUsageFromVkImageUsageFlags(allocateInfo.dedicatedImageHandle->getUsage());
+	}
+	else if(allocateInfo.dedicatedBufferHandle)
+	{
+		usage = GetAHBLockUsageFromVkBufferUsageFlags(allocateInfo.dedicatedBufferHandle->getUsage());
 	}
 	else
 	{
-		usage = GetAHBLockUsageFromVkBufferUsageFlags(allocateInfo.bufferHandle->getUsage());
+		usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
 	}
 
 	// Empty fence, lock immedietly.
@@ -465,6 +479,8 @@
 
 int AHardwareBufferExternalMemory::externalImageRowPitchBytes(VkImageAspectFlagBits aspect) const
 {
+	ASSERT(allocateInfo.dedicatedImageHandle != nullptr);
+
 	switch(ahbDesc.format)
 	{
 		case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
@@ -490,6 +506,8 @@
 
 VkDeviceSize AHardwareBufferExternalMemory::externalImageMemoryOffset(VkImageAspectFlagBits aspect) const
 {
+	ASSERT(allocateInfo.dedicatedImageHandle != nullptr);
+
 	switch(ahbDesc.format)
 	{
 		case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
diff --git a/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp b/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp
index 74a53c4..df46548 100644
--- a/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp
+++ b/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp
@@ -34,8 +34,8 @@
 		bool importAhb = false;
 		bool exportAhb = false;
 		AHardwareBuffer *ahb = nullptr;
-		vk::Image *imageHandle = nullptr;
-		vk::Buffer *bufferHandle = nullptr;
+		vk::Image *dedicatedImageHandle = nullptr;
+		vk::Buffer *dedicatedBufferHandle = nullptr;
 
 		AllocateInfo() = default;
 
@@ -48,7 +48,7 @@
 	static bool SupportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
 	{
 		AllocateInfo info(pAllocateInfo);
-		return (info.importAhb || info.exportAhb) && (info.bufferHandle || info.imageHandle);
+		return info.importAhb || info.exportAhb;
 	}
 
 	explicit AHardwareBufferExternalMemory(const VkMemoryAllocateInfo *pAllocateInfo);
@@ -81,7 +81,7 @@
 
 private:
 	VkResult importAndroidHardwareBuffer(AHardwareBuffer *buffer, void **pBuffer);
-	VkResult allocateAndroidHardwareBuffer(void **pBuffer);
+	VkResult allocateAndroidHardwareBuffer(size_t size, void **pBuffer);
 	VkResult lockAndroidHardwareBuffer(void **pBuffer);
 	VkResult unlockAndroidHardwareBuffer();