Implement a2b10g10r10_unorm_pack32.

Adds support for a2b10g10r10_unorm_pack32 render targets, and input attachments.

Tests: dEQP-VK.renderpass.dedicated_allocation.formats.a2b10g10r10_unorm_pack32.*
Tests: dEQP-VK.renderpass.suballocation.formats.a2b10g10r10_unorm_pack32.*
Bug: b/131896622
Bug: b/131171141
Change-Id: I925723754858c6b3515d142d0c7abae275685d6d
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31271
Presubmit-Ready: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Pipeline/PixelRoutine.cpp b/src/Pipeline/PixelRoutine.cpp
index 9b9bc7e..c762243 100644
--- a/src/Pipeline/PixelRoutine.cpp
+++ b/src/Pipeline/PixelRoutine.cpp
@@ -1368,6 +1368,19 @@
 		case VK_FORMAT_R16G16B16A16_UNORM:
 			transpose4x4(current.x, current.y, current.z, current.w);
 			break;
+		case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
+		{
+			auto r = Int4(current.x) & Int4(0x3ff);
+			auto g = Int4(current.y) & Int4(0x3ff);
+			auto b = Int4(current.z) & Int4(0x3ff);
+			auto a = Int4(current.w) & Int4(0x3);
+			Int4 packed = (a << 30) | (b << 20) | (g << 10) | r;
+			auto c02 = As<Int2>(Int4(packed.xzzz)); // TODO: auto c02 = packed.xz;
+			auto c13 = As<Int2>(Int4(packed.ywww)); // TODO: auto c13 = packed.yw;
+			current.x = UnpackLow(c02, c13);
+			current.y = UnpackHigh(c02, c13);
+			break;
+		}
 		default:
 			UNIMPLEMENTED("VkFormat: %d", int(state.targetFormat[index]));
 		}
@@ -1662,6 +1675,30 @@
 				}
 			}
 			break;
+			case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
+			{
+				Pointer<Byte> buffer = cBuffer + 4 * x;
+
+				buffer = cBuffer + 4 * x;
+				Int2 value = *Pointer<Int2>(buffer, 16);
+				Int2 mergedMask = *Pointer<Int2>(constants + OFFSET(Constants, maskD01Q) + xMask * 8);
+				if (rgbaWriteMask != 0xF)
+				{
+					mergedMask &= *Pointer<Int2>(constants + OFFSET(Constants, mask10Q[rgbaWriteMask][0]));
+				}
+				*Pointer<Int2>(buffer) = (As<Int2>(current.x) & mergedMask) | (value & ~mergedMask);
+
+				buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
+
+				value = *Pointer<Int2>(buffer, 16);
+				mergedMask = *Pointer<Int2>(constants + OFFSET(Constants, maskD23Q) + xMask * 8);
+				if (rgbaWriteMask != 0xF)
+				{
+					mergedMask &= *Pointer<Int2>(constants + OFFSET(Constants, mask10Q[rgbaWriteMask][0]));
+				}
+				*Pointer<Int2>(buffer) = (As<Int2>(current.y) & mergedMask) | (value & ~mergedMask);
+			}
+			break;
 		default:
 			UNIMPLEMENTED("VkFormat: %d", int(state.targetFormat[index]));
 		}