Add 8-bit YCbCr 420 format info

Bug: b/132437008
Tests: dEQP-VK.*ycbcr*
Change-Id: I91443301702b495ab62eab0cd32f533c8d7a1505
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31621
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Vulkan/VkFormat.cpp b/src/Vulkan/VkFormat.cpp
index 1d5ed01..228782c 100644
--- a/src/Vulkan/VkFormat.cpp
+++ b/src/Vulkan/VkFormat.cpp
@@ -95,7 +95,19 @@
 	if (isDepth()) aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
 	if (isStencil()) aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
 
-	// TODO: YCbCr planar formats have different aspects
+	// YCbCr formats
+	switch(format)
+	{
+	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
+		aspects = VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT;
+		break;
+	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+		aspects = VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT;
+		break;
+	default:
+		ASSERT(!isYcbcrFormat());
+		break;
+	}
 
 	// Anything else is "color".
 	if (!aspects) aspects |= VK_IMAGE_ASPECT_COLOR_BIT;
@@ -106,19 +118,29 @@
 {
 	switch(aspect)
 	{
+	case VK_IMAGE_ASPECT_COLOR_BIT:
+	case (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT):
+	case (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT):
+	case (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT):
+		return format;
+
 	case VK_IMAGE_ASPECT_DEPTH_BIT:
 		switch(format)
 		{
+		case VK_FORMAT_D16_UNORM:
 		case VK_FORMAT_D16_UNORM_S8_UINT:
 			return VK_FORMAT_D16_UNORM;
 		case VK_FORMAT_D24_UNORM_S8_UINT:
-			return VK_FORMAT_X8_D24_UNORM_PACK32; // FIXME: This will allocate an extra byte per pixel
+			return VK_FORMAT_X8_D24_UNORM_PACK32;
+		case VK_FORMAT_D32_SFLOAT:
 		case VK_FORMAT_D32_SFLOAT_S8_UINT:
 			return VK_FORMAT_D32_SFLOAT;
 		default:
+			UNSUPPORTED("format %d", int(format));
 			break;
 		}
 		break;
+
 	case VK_IMAGE_ASPECT_STENCIL_BIT:
 		switch(format)
 		{
@@ -127,10 +149,51 @@
 		case VK_FORMAT_D32_SFLOAT_S8_UINT:
 			return VK_FORMAT_S8_UINT;
 		default:
+			UNSUPPORTED("format %d", int(format));
 			break;
 		}
 		break;
+
+	// YCbCr formats
+	// Vulkan 1.1 section 32.1.1. Compatible formats of planes of multi-planar formats
+	case VK_IMAGE_ASPECT_PLANE_0_BIT:
+		switch(format)
+		{
+		case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
+		case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+			return VK_FORMAT_R8_UNORM;
+		default:
+			UNSUPPORTED("format %d", int(format));
+			break;
+		}
+		break;
+
+	case VK_IMAGE_ASPECT_PLANE_1_BIT:
+		switch(format)
+		{
+		case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
+			return VK_FORMAT_R8_UNORM;
+		case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+			return VK_FORMAT_R8G8_UNORM;
+		default:
+			UNSUPPORTED("format %d", int(format));
+			break;
+		}
+		break;
+
+	case VK_IMAGE_ASPECT_PLANE_2_BIT:
+		switch(format)
+		{
+		case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
+			return VK_FORMAT_R8_UNORM;
+		default:
+			UNSUPPORTED("format %d", int(format));
+			break;
+		}
+		break;
+
 	default:
+		UNSUPPORTED("aspect %x", int(aspect));
 		break;
 	}
 
@@ -331,6 +394,7 @@
 	case VK_FORMAT_S8_UINT:
 	case VK_FORMAT_D16_UNORM_S8_UINT:
 	case VK_FORMAT_D24_UNORM_S8_UINT:
+	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 		return false;
 	case VK_FORMAT_R16_SFLOAT:
@@ -1071,6 +1135,7 @@
 	case VK_FORMAT_R64G64B64_SFLOAT:
 	case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
 	case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
+	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
 	case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
@@ -1213,7 +1278,6 @@
 	case VK_FORMAT_D24_UNORM_S8_UINT:
 	case VK_FORMAT_D32_SFLOAT:
 	case VK_FORMAT_D32_SFLOAT_S8_UINT:
-	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_EAC_R11_UNORM_BLOCK:
 	case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
 	case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
@@ -1248,6 +1312,10 @@
 	case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
 	case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
 	case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
+	// YCbCr formats treated as signed because VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY
+	// expects chroma components to be in range [-0.5, 0.5]
+	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
+	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 		return false;
 	case VK_FORMAT_R8_SNORM:
 	case VK_FORMAT_R8_USCALED:
@@ -1447,9 +1515,9 @@
 	case VK_FORMAT_X8_D24_UNORM_PACK32:       return 4;
 	case VK_FORMAT_D32_SFLOAT:                return 4;
 	case VK_FORMAT_S8_UINT:                   return 1;
-	case VK_FORMAT_D16_UNORM_S8_UINT:         return 2; // Separate depth and stencil planes
-	case VK_FORMAT_D24_UNORM_S8_UINT:         return 4; // Combined depth and stencil planes
-	case VK_FORMAT_D32_SFLOAT_S8_UINT:        return 4; // Separate depth and stencil planes
+	case VK_FORMAT_D16_UNORM_S8_UINT:         return 2; // Separate depth and stencil planes  // TODO: ASSERT to ensure this is only called per-aspect?
+	case VK_FORMAT_D24_UNORM_S8_UINT:         return 4; // Combined depth and stencil planes  // TODO: ASSERT to ensure this is only called per-aspect?
+	case VK_FORMAT_D32_SFLOAT_S8_UINT:        return 4; // Separate depth and stencil planes  // TODO: ASSERT to ensure this is only called per-aspect?
 	// Note: Compressed formats don't return bytes per pixel,
 	//       since these would be fractional. The returned value
 	//       is bytes per pixel for 1 column, so 2 for 64 bit 4x4
@@ -1507,8 +1575,13 @@
 	case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
 	case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
 	case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
-	case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:     return 0; // FIXME
-	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:  return 1; // Y plane only
+	case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+		UNSUPPORTED("format: %d", int(format));
+		return 0;
+	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
+	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+		// TODO: ASSERT to ensure this is only called per-aspect?
+		return 1;  // Y plane only
 	default:
 		UNIMPLEMENTED("Format: %d", int(format));
 	}
@@ -1573,8 +1646,9 @@
 	case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
 	case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
 		return 16 * ((width + 11) / 12);
+	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
-		return sw::align<16>(width);
+		return sw::align<16>(width);  // Y plane only  // TODO: ASSERT to ensure this is only called per-aspect?
 	default:
 		return bytes() * width;
 	}
@@ -1636,6 +1710,10 @@
 	case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
 	case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
 		return pitchB(width, border, target) * ((height + 11) / 12);   // Pitch computed per 12 rows
+	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
+	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+		// "Images in this format must be defined with a width and height that is a multiple of two."
+		return pitchB(width, border, target) * (height + height / 2);  // U and V planes are 1/4 size of Y plane.
 	default:
 		return pitchB(width, border, target) * height;   // Pitch computed per row
 	}
@@ -1846,6 +1924,7 @@
 	case VK_FORMAT_R16G16B16A16_SINT:
 	case VK_FORMAT_R16G16B16A16_UINT:
 	case VK_FORMAT_R16G16B16A16_SFLOAT:
+	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
 	case VK_FORMAT_A2B10G10R10_UINT_PACK32:
@@ -1908,6 +1987,7 @@
 	case VK_FORMAT_R16G16B16A16_SINT:
 	case VK_FORMAT_R16G16B16A16_UINT:
 	case VK_FORMAT_R16G16B16A16_SFLOAT:
+	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
 	case VK_FORMAT_A2B10G10R10_UINT_PACK32:
@@ -1955,6 +2035,7 @@
 	case VK_FORMAT_R32G32_SFLOAT:
 	case VK_FORMAT_R32G32B32A32_SFLOAT:
 	case VK_FORMAT_R8_UNORM:
+	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
 	case VK_FORMAT_A2B10G10R10_UINT_PACK32:
@@ -2025,6 +2106,7 @@
 	case VK_FORMAT_R32G32_SFLOAT:
 	case VK_FORMAT_R32G32B32A32_SFLOAT:
 	case VK_FORMAT_R8_UNORM:
+	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
 	case VK_FORMAT_A2B10G10R10_UINT_PACK32:
@@ -2095,6 +2177,7 @@
 	case VK_FORMAT_R32G32B32A32_SINT:
 	case VK_FORMAT_R32G32B32A32_UINT:
 	case VK_FORMAT_R32G32B32A32_SFLOAT:
+	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
 	case VK_FORMAT_B10G11R11_UFLOAT_PACK32: