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)