Unify BGRA masks

A few formats require flipping the R and B channels of the channels
mask. This CL centralizes that logic in a single spot.

Bug: b/204322086
Change-Id: I6eef8ba0c831f595ebffa94dfef9a65b64d52101
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/69948
Commit-Queue: Alexis Hétu <sugoi@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/Constants.cpp b/src/Pipeline/Constants.cpp
index 0570609..dda1f39 100644
--- a/src/Pipeline/Constants.cpp
+++ b/src/Pipeline/Constants.cpp
@@ -235,19 +235,17 @@
 
 	for(int i = 0; i < 8; i++)
 	{
-		mask565Q[i] = word4((i & 0x1 ? 0xF800 : 0) | (i & 0x2 ? 0x07E0 : 0) | (i & 0x4 ? 0x001F : 0));
+		mask565Q[i] = word4((i & 0x1 ? 0x001F : 0) | (i & 0x2 ? 0x07E0 : 0) | (i & 0x4 ? 0xF800 : 0));
 		mask11X[i] = dword4((i & 0x1 ? 0x000007FFu : 0) | (i & 0x2 ? 0x003FF800u : 0) | (i & 0x4 ? 0xFFC00000u : 0));
 	}
 
 	for(int i = 0; i < 16; i++)
 	{
-		mask5551Q[i] = word4((i & 0x1 ? 0x7C00 : 0) | (i & 0x2 ? 0x03E0 : 0) | (i & 0x4 ? 0x001F : 0) | (i & 8 ? 0x8000 : 0));
+		mask5551Q[i] = word4((i & 0x1 ? 0x001F : 0) | (i & 0x2 ? 0x03E0 : 0) | (i & 0x4 ? 0x7C00 : 0) | (i & 8 ? 0x8000 : 0));
 		maskr5g5b5a1Q[i] = word4((i & 0x1 ? 0xF800 : 0) | (i & 0x2 ? 0x07C0 : 0) | (i & 0x4 ? 0x003E : 0) | (i & 8 ? 0x0001 : 0));
 		maskb5g5r5a1Q[i] = word4((i & 0x1 ? 0x003E : 0) | (i & 0x2 ? 0x07C0 : 0) | (i & 0x4 ? 0xF800 : 0) | (i & 8 ? 0x0001 : 0));
-		mask4rgbaQ[i] = word4((i & 0x1 ? 0xF000 : 0) | (i & 0x2 ? 0x0F00 : 0) | (i & 0x4 ? 0x00F0 : 0) | (i & 8 ? 0x000F : 0));
-		mask4bgraQ[i] = word4((i & 0x1 ? 0x00F0 : 0) | (i & 0x2 ? 0x0F00 : 0) | (i & 0x4 ? 0xF000 : 0) | (i & 8 ? 0x000F : 0));
-		mask4abgrQ[i] = word4((i & 0x1 ? 0x000F : 0) | (i & 0x2 ? 0x00F0 : 0) | (i & 0x4 ? 0x0F00 : 0) | (i & 8 ? 0xF000 : 0));
-		mask4argbQ[i] = word4((i & 0x1 ? 0x0F00 : 0) | (i & 0x2 ? 0x00F0 : 0) | (i & 0x4 ? 0x000F : 0) | (i & 8 ? 0xF000 : 0));
+		mask4argbQ[i] = word4((i & 0x1 ? 0x00F0 : 0) | (i & 0x2 ? 0x0F00 : 0) | (i & 0x4 ? 0xF000 : 0) | (i & 8 ? 0x000F : 0));
+		mask4rgbaQ[i] = word4((i & 0x1 ? 0x000F : 0) | (i & 0x2 ? 0x00F0 : 0) | (i & 0x4 ? 0x0F00 : 0) | (i & 8 ? 0xF000 : 0));
 	}
 
 	for(int i = 0; i < 4; i++)
diff --git a/src/Pipeline/Constants.hpp b/src/Pipeline/Constants.hpp
index a939a7c..a857747 100644
--- a/src/Pipeline/Constants.hpp
+++ b/src/Pipeline/Constants.hpp
@@ -103,8 +103,6 @@
 	word4 maskr5g5b5a1Q[16];  // 4 bit writemask -> R5G5B5A1 bit patterns, replicated 4x
 	word4 maskb5g5r5a1Q[16];  // 4 bit writemask -> B5G5R5A1 bit patterns, replicated 4x
 	word4 mask4rgbaQ[16];     // 4 bit writemask -> R4G4B4A4 bit patterns, replicated 4x
-	word4 mask4bgraQ[16];     // 4 bit writemask -> B4G4R4A4 bit patterns, replicated 4x
-	word4 mask4abgrQ[16];     // 4 bit writemask -> A4B4G4R4 bit patterns, replicated 4x
 	word4 mask4argbQ[16];     // 4 bit writemask -> A4R4G4B4 bit patterns, replicated 4x
 	dword4 mask11X[8];        // 3 bit writemask -> B10G11R11 bit patterns, replicated 4x
 
diff --git a/src/Pipeline/PixelRoutine.cpp b/src/Pipeline/PixelRoutine.cpp
index 600d65e..1d46605 100644
--- a/src/Pipeline/PixelRoutine.cpp
+++ b/src/Pipeline/PixelRoutine.cpp
@@ -889,7 +889,8 @@
 
 	Int pitchB = *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
 
-	switch(state.colorFormat[index])
+	vk::Format format = state.colorFormat[index];
+	switch(format)
 	{
 	case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
 		buffer += 2 * x;
@@ -1169,7 +1170,7 @@
 		}
 		break;
 	default:
-		UNSUPPORTED("VkFormat %d", int(state.colorFormat[index]));
+		UNSUPPORTED("VkFormat %d", int(format));
 	}
 
 	if(isSRGB(index))
@@ -1185,7 +1186,8 @@
 		linearToSRGB16_12_16(current);
 	}
 
-	switch(state.colorFormat[index])
+	vk::Format format = state.colorFormat[index];
+	switch(format)
 	{
 	case VK_FORMAT_B8G8R8A8_UNORM:
 	case VK_FORMAT_B8G8R8A8_SRGB:
@@ -1235,8 +1237,13 @@
 	}
 
 	int writeMask = state.colorWriteActive(index);
+	if(format.isBGRformat())
+	{
+		// For BGR formats, flip R and B channels in the channels mask
+		writeMask = (writeMask & 0x0000000A) | (writeMask & 0x00000001) << 2 | (writeMask & 0x00000004) >> 2;
+	}
 
-	switch(state.colorFormat[index])
+	switch(format)
 	{
 	case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
 		{
@@ -1438,7 +1445,7 @@
 		}
 		break;
 	default:
-		UNSUPPORTED("VkFormat: %d", int(state.colorFormat[index]));
+		UNSUPPORTED("VkFormat: %d", int(format));
 	}
 
 	Short4 c01 = current.z;
@@ -1463,7 +1470,7 @@
 	Pointer<Byte> buffer = cBuffer;
 	Int pitchB = *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
 
-	switch(state.colorFormat[index])
+	switch(format)
 	{
 	case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
 	case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
@@ -1474,22 +1481,18 @@
 			Int value = *Pointer<Int>(buffer);
 
 			Int channelMask;
-			switch(state.colorFormat[index])
+			switch(format)
 			{
 			case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
-				channelMask = *Pointer<Int>(constants + OFFSET(Constants, mask4rgbaQ[writeMask][0]));
-				break;
 			case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
-				channelMask = *Pointer<Int>(constants + OFFSET(Constants, mask4bgraQ[writeMask][0]));
-				break;
-			case VK_FORMAT_A4R4G4B4_UNORM_PACK16:
 				channelMask = *Pointer<Int>(constants + OFFSET(Constants, mask4argbQ[writeMask][0]));
 				break;
+			case VK_FORMAT_A4R4G4B4_UNORM_PACK16:
 			case VK_FORMAT_A4B4G4R4_UNORM_PACK16:
-				channelMask = *Pointer<Int>(constants + OFFSET(Constants, mask4abgrQ[writeMask][0]));
+				channelMask = *Pointer<Int>(constants + OFFSET(Constants, mask4rgbaQ[writeMask][0]));
 				break;
 			default:
-				UNREACHABLE("Format: %s", vk::Stringify(state.colorFormat[index]).c_str());
+				UNREACHABLE("Format: %s", vk::Stringify(format).c_str());
 			}
 
 			Int c01 = Extract(As<Int2>(current.x), 0);
@@ -1623,8 +1626,6 @@
 	case VK_FORMAT_B8G8R8A8_UNORM:
 	case VK_FORMAT_B8G8R8A8_SRGB:
 		{
-			writeMask = (writeMask & 0x0000000A) | (writeMask & 0x00000001) << 2 | (writeMask & 0x00000004) >> 2;
-
 			buffer += x * 4;
 			Short4 value = *Pointer<Short4>(buffer);
 			Short4 channelMask = *Pointer<Short4>(constants + OFFSET(Constants, maskB4Q[writeMask]));
@@ -1715,8 +1716,6 @@
 		}
 		break;
 	case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
-		writeMask = (writeMask & 0x0000000A) | (writeMask & 0x00000001) << 2 | (writeMask & 0x00000004) >> 2;
-		// [[fallthrough]]
 	case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
 		{
 			buffer += 4 * x;
@@ -1741,7 +1740,7 @@
 		}
 		break;
 	default:
-		UNSUPPORTED("VkFormat: %d", int(state.colorFormat[index]));
+		UNSUPPORTED("VkFormat: %d", int(format));
 	}
 }
 
@@ -2674,6 +2673,11 @@
 	}
 
 	int writeMask = state.colorWriteActive(index);
+	if(format.isBGRformat())
+	{
+		// For BGR formats, flip R and B channels in the channels mask
+		writeMask = (writeMask & 0x0000000A) | (writeMask & 0x00000001) << 2 | (writeMask & 0x00000004) >> 2;
+	}
 
 	Int xMask;  // Combination of all masks
 
@@ -3135,8 +3139,6 @@
 		break;
 	case VK_FORMAT_B8G8R8A8_UNORM:
 	case VK_FORMAT_B8G8R8A8_SRGB:
-		writeMask = (writeMask & 0x0000000A) | (writeMask & 0x00000001) << 2 | (writeMask & 0x00000004) >> 2;
-		// [[fallthrough]]
 	case VK_FORMAT_R8G8B8A8_SINT:
 	case VK_FORMAT_R8G8B8A8_UINT:
 	case VK_FORMAT_A8B8G8R8_UINT_PACK32:
@@ -3258,38 +3260,38 @@
 
 			Int channelMask;
 			Short4 current;
-			switch(state.colorFormat[index])
+			switch(format)
 			{
 			case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
-				channelMask = *Pointer<Int>(constants + OFFSET(Constants, mask4rgbaQ[writeMask][0]));
+				channelMask = *Pointer<Int>(constants + OFFSET(Constants, mask4argbQ[writeMask][0]));
 				current = (UShort4(As<Int4>(color.x)) & UShort4(0xF)) << 12 |
 				          (UShort4(As<Int4>(color.y)) & UShort4(0xF)) << 8 |
 				          (UShort4(As<Int4>(color.z)) & UShort4(0xF)) << 4 |
 				          (UShort4(As<Int4>(color.w)) & UShort4(0xF));
 				break;
 			case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
-				channelMask = *Pointer<Int>(constants + OFFSET(Constants, mask4bgraQ[writeMask][0]));
+				channelMask = *Pointer<Int>(constants + OFFSET(Constants, mask4argbQ[writeMask][0]));
 				current = (UShort4(As<Int4>(color.z)) & UShort4(0xF)) << 12 |
 				          (UShort4(As<Int4>(color.y)) & UShort4(0xF)) << 8 |
 				          (UShort4(As<Int4>(color.x)) & UShort4(0xF)) << 4 |
 				          (UShort4(As<Int4>(color.w)) & UShort4(0xF));
 				break;
 			case VK_FORMAT_A4R4G4B4_UNORM_PACK16:
-				channelMask = *Pointer<Int>(constants + OFFSET(Constants, mask4argbQ[writeMask][0]));
+				channelMask = *Pointer<Int>(constants + OFFSET(Constants, mask4rgbaQ[writeMask][0]));
 				current = (UShort4(As<Int4>(color.w)) & UShort4(0xF)) << 12 |
 				          (UShort4(As<Int4>(color.x)) & UShort4(0xF)) << 8 |
 				          (UShort4(As<Int4>(color.y)) & UShort4(0xF)) << 4 |
 				          (UShort4(As<Int4>(color.z)) & UShort4(0xF));
 				break;
 			case VK_FORMAT_A4B4G4R4_UNORM_PACK16:
-				channelMask = *Pointer<Int>(constants + OFFSET(Constants, mask4abgrQ[writeMask][0]));
+				channelMask = *Pointer<Int>(constants + OFFSET(Constants, mask4rgbaQ[writeMask][0]));
 				current = (UShort4(As<Int4>(color.w)) & UShort4(0xF)) << 12 |
 				          (UShort4(As<Int4>(color.z)) & UShort4(0xF)) << 8 |
 				          (UShort4(As<Int4>(color.y)) & UShort4(0xF)) << 4 |
 				          (UShort4(As<Int4>(color.x)) & UShort4(0xF));
 				break;
 			default:
-				UNREACHABLE("Format: %s", vk::Stringify(state.colorFormat[index]).c_str());
+				UNREACHABLE("Format: %s", vk::Stringify(format).c_str());
 			}
 
 			Int c01 = Extract(As<Int2>(current), 0);
@@ -3437,8 +3439,6 @@
 		break;
 	case VK_FORMAT_B5G6R5_UNORM_PACK16:
 		{
-			writeMask = (writeMask & 0x0000000A) | (writeMask & 0x00000001) << 2 | (writeMask & 0x00000004) >> 2;
-
 			buffer += 2 * x;
 			Int value = *Pointer<Int>(buffer);
 
diff --git a/src/Vulkan/VkFormat.cpp b/src/Vulkan/VkFormat.cpp
index cdf40ac..61a1667 100644
--- a/src/Vulkan/VkFormat.cpp
+++ b/src/Vulkan/VkFormat.cpp
@@ -353,6 +353,40 @@
 	}
 }
 
+bool Format::isBGRformat() const
+{
+	switch(format)
+	{
+	case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
+	case VK_FORMAT_A4R4G4B4_UNORM_PACK16:
+	case VK_FORMAT_R5G6B5_UNORM_PACK16:
+	case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
+	case VK_FORMAT_B8G8R8_UNORM:
+	case VK_FORMAT_B8G8R8_SNORM:
+	case VK_FORMAT_B8G8R8_USCALED:
+	case VK_FORMAT_B8G8R8_SSCALED:
+	case VK_FORMAT_B8G8R8_UINT:
+	case VK_FORMAT_B8G8R8_SINT:
+	case VK_FORMAT_B8G8R8_SRGB:
+	case VK_FORMAT_B8G8R8A8_UNORM:
+	case VK_FORMAT_B8G8R8A8_SNORM:
+	case VK_FORMAT_B8G8R8A8_USCALED:
+	case VK_FORMAT_B8G8R8A8_SSCALED:
+	case VK_FORMAT_B8G8R8A8_UINT:
+	case VK_FORMAT_B8G8R8A8_SINT:
+	case VK_FORMAT_B8G8R8A8_SRGB:
+	case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
+	case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
+	case VK_FORMAT_A2R10G10B10_USCALED_PACK32:
+	case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
+	case VK_FORMAT_A2R10G10B10_UINT_PACK32:
+	case VK_FORMAT_A2R10G10B10_SINT_PACK32:
+		return true;
+	default:
+		return false;
+	}
+}
+
 bool Format::isSRGBformat() const
 {
 	switch(format)
diff --git a/src/Vulkan/VkFormat.hpp b/src/Vulkan/VkFormat.hpp
index 3cff4a0..994e112 100644
--- a/src/Vulkan/VkFormat.hpp
+++ b/src/Vulkan/VkFormat.hpp
@@ -43,6 +43,7 @@
 	VkFormat getClearFormat() const;
 	bool isStencil() const;
 	bool isDepth() const;
+	bool isBGRformat() const;
 	bool isSRGBformat() const;
 	bool isFloatFormat() const;
 	bool isYcbcrFormat() const;