Handle VkExternalFormatANDROID in VkCreateImage

Images for YUV-format AHBs will have VK_FORMAT_UNDEFINED in
their VkImageCreateInfo->format and will have a
VkExternalFormatANDROID with externalFormat containing the
AHARDWAREBUFFER_FORMAT_*. Translate this AHB_FORMAT_* back to
VK_FORMAT_* during image and image view creation.

Bug: b/175132241
Test: launch Cuttlefish w/ SwANGLE and open Camera
Change-Id: If2e6cd88d6e8f35fe972bd1a5873ed16b0c95b39
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/51049
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 66737e8..569c83c 100644
--- a/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp
+++ b/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp
@@ -59,46 +59,6 @@
 	}
 }
 
-VkFormat GetVkFormatFromAHBFormat(uint32_t ahbFormat)
-{
-	switch(ahbFormat)
-	{
-		case AHARDWAREBUFFER_FORMAT_BLOB:
-			return VK_FORMAT_UNDEFINED;
-		case AHARDWAREBUFFER_FORMAT_D16_UNORM:
-			return VK_FORMAT_D16_UNORM;
-		case AHARDWAREBUFFER_FORMAT_D24_UNORM:
-			UNSUPPORTED("AHardwareBufferExternalMemory::AndroidHardwareBuffer_Format AHARDWAREBUFFER_FORMAT_D24_UNORM");
-			return VK_FORMAT_X8_D24_UNORM_PACK32;
-		case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
-			UNSUPPORTED("AHardwareBufferExternalMemory::AndroidHardwareBuffer_Format AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT");
-			return VK_FORMAT_X8_D24_UNORM_PACK32;
-		case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
-			return VK_FORMAT_D32_SFLOAT;
-		case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
-			return VK_FORMAT_D32_SFLOAT_S8_UINT;
-		case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
-			return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
-		case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
-			return VK_FORMAT_R16G16B16A16_SFLOAT;
-		case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
-			return VK_FORMAT_R5G6B5_UNORM_PACK16;
-		case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
-			return VK_FORMAT_R8G8B8A8_UNORM;
-		case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
-			return VK_FORMAT_R8G8B8A8_UNORM;
-		case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
-			return VK_FORMAT_R8G8B8_UNORM;
-		case AHARDWAREBUFFER_FORMAT_S8_UINT:
-			return VK_FORMAT_S8_UINT;
-		case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
-			return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
-		default:
-			UNSUPPORTED("AHardwareBufferExternalMemory::AHardwareBuffer_Format %d", int(ahbFormat));
-			return VK_FORMAT_UNDEFINED;
-	}
-}
-
 uint64_t GetAHBLockUsageFromVkImageUsageFlags(VkImageUsageFlags flags)
 {
 	uint64_t usage = 0;
@@ -186,7 +146,7 @@
 {
 	VkFormatFeatureFlags features = 0;
 
-	VkFormat format = GetVkFormatFromAHBFormat(ahbFormat);
+	VkFormat format = AHardwareBufferExternalMemory::GetVkFormatFromAHBFormat(ahbFormat);
 	VkFormatProperties formatProperties;
 	vk::PhysicalDevice::GetFormatProperties(vk::Format(format), &formatProperties);
 
@@ -384,6 +344,46 @@
 	return VK_SUCCESS;
 }
 
+VkFormat AHardwareBufferExternalMemory::GetVkFormatFromAHBFormat(uint32_t ahbFormat)
+{
+	switch(ahbFormat)
+	{
+		case AHARDWAREBUFFER_FORMAT_BLOB:
+			return VK_FORMAT_UNDEFINED;
+		case AHARDWAREBUFFER_FORMAT_D16_UNORM:
+			return VK_FORMAT_D16_UNORM;
+		case AHARDWAREBUFFER_FORMAT_D24_UNORM:
+			UNSUPPORTED("AHardwareBufferExternalMemory::AndroidHardwareBuffer_Format AHARDWAREBUFFER_FORMAT_D24_UNORM");
+			return VK_FORMAT_X8_D24_UNORM_PACK32;
+		case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
+			UNSUPPORTED("AHardwareBufferExternalMemory::AndroidHardwareBuffer_Format AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT");
+			return VK_FORMAT_X8_D24_UNORM_PACK32;
+		case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
+			return VK_FORMAT_D32_SFLOAT;
+		case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
+			return VK_FORMAT_D32_SFLOAT_S8_UINT;
+		case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
+			return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
+		case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
+			return VK_FORMAT_R16G16B16A16_SFLOAT;
+		case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
+			return VK_FORMAT_R5G6B5_UNORM_PACK16;
+		case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
+			return VK_FORMAT_R8G8B8A8_UNORM;
+		case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
+			return VK_FORMAT_R8G8B8A8_UNORM;
+		case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
+			return VK_FORMAT_R8G8B8_UNORM;
+		case AHARDWAREBUFFER_FORMAT_S8_UINT:
+			return VK_FORMAT_S8_UINT;
+		case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
+			return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
+		default:
+			UNSUPPORTED("AHardwareBufferExternalMemory::AHardwareBuffer_Format %d", int(ahbFormat));
+			return VK_FORMAT_UNDEFINED;
+	}
+}
+
 VkResult AHardwareBufferExternalMemory::GetAndroidHardwareBufferFormatProperties(const AHardwareBuffer_Desc &ahbDesc, VkAndroidHardwareBufferFormatPropertiesANDROID *pFormat)
 {
 	pFormat->sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
diff --git a/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp b/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp
index 6d25add..74a53c4 100644
--- a/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp
+++ b/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp
@@ -63,6 +63,7 @@
 
 	void setDevicePtr(vk::Device *pDevice) override { device = pDevice; }
 
+	static VkFormat GetVkFormatFromAHBFormat(uint32_t ahbFormat);
 	static VkResult GetAndroidHardwareBufferFormatProperties(const AHardwareBuffer_Desc &ahbDesc, VkAndroidHardwareBufferFormatPropertiesANDROID *pFormat);
 	static VkResult GetAndroidHardwareBufferProperties(VkDevice &device, const AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties);
 
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index 545a3e1..53150d5 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -17,6 +17,7 @@
 #include "VkBuffer.hpp"
 #include "VkDevice.hpp"
 #include "VkDeviceMemory.hpp"
+#include "VkStringify.hpp"
 #include "Device/ASTC_Decoder.hpp"
 #include "Device/BC_Decoder.hpp"
 #include "Device/Blitter.hpp"
@@ -24,6 +25,7 @@
 
 #ifdef __ANDROID__
 #	include "System/GrallocAndroid.hpp"
+#	include "VkDeviceMemoryExternalAndroid.hpp"
 #endif
 
 #include <cstring>
@@ -121,6 +123,41 @@
 	}
 }
 
+VkFormat GetImageFormat(const VkImageCreateInfo *pCreateInfo)
+{
+	auto nextInfo = reinterpret_cast<VkBaseInStructure const *>(pCreateInfo->pNext);
+	while(nextInfo)
+	{
+		switch(nextInfo->sType)
+		{
+#ifdef __ANDROID__
+			case VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID:
+			{
+				const VkExternalFormatANDROID *externalFormatAndroid = reinterpret_cast<const VkExternalFormatANDROID *>(nextInfo);
+
+				// VkExternalFormatANDROID: "If externalFormat is zero, the effect is as if the VkExternalFormatANDROID structure was not present."
+				if(externalFormatAndroid->externalFormat == 0)
+				{
+					break;
+				}
+
+				const VkFormat correspondingVkFormat = AHardwareBufferExternalMemory::GetVkFormatFromAHBFormat(externalFormatAndroid->externalFormat);
+				ASSERT(pCreateInfo->format == VK_FORMAT_UNDEFINED || pCreateInfo->format == correspondingVkFormat);
+				return correspondingVkFormat;
+			}
+			break;
+#endif
+			default:
+				LOG_TRAP("pCreateInfo->pNext->sType = %s", vk::Stringify(nextInfo->sType).c_str());
+				break;
+		}
+
+		nextInfo = nextInfo->pNext;
+	}
+
+	return pCreateInfo->format;
+}
+
 }  // anonymous namespace
 
 namespace vk {
@@ -129,7 +166,7 @@
     : device(device)
     , flags(pCreateInfo->flags)
     , imageType(pCreateInfo->imageType)
-    , format(pCreateInfo->format)
+    , format(GetImageFormat(pCreateInfo))
     , extent(pCreateInfo->extent)
     , mipLevels(pCreateInfo->mipLevels)
     , arrayLayers(pCreateInfo->arrayLayers)
diff --git a/src/Vulkan/VkImageView.cpp b/src/Vulkan/VkImageView.cpp
index 0a51516..b58b35d 100644
--- a/src/Vulkan/VkImageView.cpp
+++ b/src/Vulkan/VkImageView.cpp
@@ -20,6 +20,21 @@
 #include <climits>
 
 namespace vk {
+namespace {
+
+Format GetImageViewFormat(const VkImageViewCreateInfo *pCreateInfo)
+{
+	// VkImageViewCreateInfo: "If image has an external format, format must be VK_FORMAT_UNDEFINED"
+	// In that case, obtain the format from the underlying image.
+	if(pCreateInfo->format != VK_FORMAT_UNDEFINED)
+	{
+		return Format(pCreateInfo->format);
+	}
+
+	return vk::Cast(pCreateInfo->image)->getFormat();
+}
+
+}  // anonymous namespace
 
 VkComponentMapping ResolveIdentityMapping(VkComponentMapping mapping)
 {
@@ -83,7 +98,7 @@
 ImageView::ImageView(const VkImageViewCreateInfo *pCreateInfo, void *mem, const vk::SamplerYcbcrConversion *ycbcrConversion)
     : image(vk::Cast(pCreateInfo->image))
     , viewType(pCreateInfo->viewType)
-    , format(pCreateInfo->format)
+    , format(GetImageViewFormat(pCreateInfo))
     , components(ResolveComponentMapping(pCreateInfo->components, format))
     , subresourceRange(ResolveRemainingLevelsLayers(pCreateInfo->subresourceRange, image))
     , ycbcrConversion(ycbcrConversion)