Use custom normalization for SNORM formats in sampler

Previously we replicated the high bits into the low
and from that point on treated these values as 16 bits.

Unfortunately, that causes a snorm channel value of 0xff
to yield -1/32767 rather than the expected -1/127.

Bug: b/129523279
Test: dEQP-VK.image.mutable.*snorm*
Change-Id: I6e329490f92562d6edac86043e80fef978682c88
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31728
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp
index 6f22309..02c5462 100644
--- a/src/Pipeline/SamplerCore.cpp
+++ b/src/Pipeline/SamplerCore.cpp
@@ -137,36 +137,38 @@
 		{
 			c = sampleFloatFilter(texture, uuuu, vvvv, wwww, qqqq, offset, lod, anisotropy, uDelta, vDelta, face, function);
 
-			if(!hasFloatTexture() && !hasUnnormalizedIntegerTexture() && !state.compareEnable)
+			if (!hasFloatTexture() && !hasUnnormalizedIntegerTexture() && !state.compareEnable)
 			{
-				if(has16bitTextureFormat())
+				switch (state.textureFormat)
 				{
-					switch(state.textureFormat)
-					{
-					case VK_FORMAT_R5G6B5_UNORM_PACK16:
-						c.x *= Float4(1.0f / 0xF800);
-						c.y *= Float4(1.0f / 0xFC00);
-						c.z *= Float4(1.0f / 0xF800);
-						break;
-					case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
-						c.x *= Float4(1.0f / 0xF000);
-						c.y *= Float4(1.0f / 0xF000);
-						c.z *= Float4(1.0f / 0xF000);
-						c.w *= Float4(1.0f / 0xF000);
-						break;
-					case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
-						c.x *= Float4(1.0f / 0xF800);
-						c.y *= Float4(1.0f / 0xF800);
-						c.z *= Float4(1.0f / 0xF800);
-						c.w *= Float4(1.0f / 0x8000);
-						break;
-					default:
-						ASSERT(false);
-					}
-				}
-				else
-				{
-					for(int component = 0; component < textureComponentCount(); component++)
+				case VK_FORMAT_R5G6B5_UNORM_PACK16:
+					c.x *= Float4(1.0f / 0xF800);
+					c.y *= Float4(1.0f / 0xFC00);
+					c.z *= Float4(1.0f / 0xF800);
+					break;
+				case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
+					c.x *= Float4(1.0f / 0xF000);
+					c.y *= Float4(1.0f / 0xF000);
+					c.z *= Float4(1.0f / 0xF000);
+					c.w *= Float4(1.0f / 0xF000);
+					break;
+				case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
+					c.x *= Float4(1.0f / 0xF800);
+					c.y *= Float4(1.0f / 0xF800);
+					c.z *= Float4(1.0f / 0xF800);
+					c.w *= Float4(1.0f / 0x8000);
+					break;
+				case VK_FORMAT_R8_SNORM:
+				case VK_FORMAT_R8G8_SNORM:
+				case VK_FORMAT_R8G8B8A8_SNORM:
+				case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
+					c.x *= Float4(1.0f / 0x7F00);
+					c.y *= Float4(1.0f / 0x7F00);
+					c.z *= Float4(1.0f / 0x7F00);
+					c.w *= Float4(1.0f / 0x7F00);
+					break;
+				default:
+					for (int component = 0; component < textureComponentCount(); component++)
 					{
 						c[component] *= Float4(hasUnsignedTextureComponent(component) ? 1.0f / 0xFFFF : 1.0f / 0x7FFF);
 					}
@@ -177,28 +179,35 @@
 		{
 			Vector4s cs = sampleFilter(texture, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
 
-			if(state.textureFormat == VK_FORMAT_R5G6B5_UNORM_PACK16)
+			switch (state.textureFormat)
 			{
+			case VK_FORMAT_R5G6B5_UNORM_PACK16:
 				c.x = Float4(As<UShort4>(cs.x)) * Float4(1.0f / 0xF800);
 				c.y = Float4(As<UShort4>(cs.y)) * Float4(1.0f / 0xFC00);
 				c.z = Float4(As<UShort4>(cs.z)) * Float4(1.0f / 0xF800);
-			}
-			else if (state.textureFormat == VK_FORMAT_B4G4R4A4_UNORM_PACK16)
-			{
+				break;
+			case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
 				c.x = Float4(As<UShort4>(cs.x)) * Float4(1.0f / 0xF000);
 				c.y = Float4(As<UShort4>(cs.y)) * Float4(1.0f / 0xF000);
 				c.z = Float4(As<UShort4>(cs.z)) * Float4(1.0f / 0xF000);
 				c.w = Float4(As<UShort4>(cs.w)) * Float4(1.0f / 0xF000);
-			}
-			else if (state.textureFormat == VK_FORMAT_A1R5G5B5_UNORM_PACK16)
-			{
+				break;
+			case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
 				c.x = Float4(As<UShort4>(cs.x)) * Float4(1.0f / 0xF800);
 				c.y = Float4(As<UShort4>(cs.y)) * Float4(1.0f / 0xF800);
 				c.z = Float4(As<UShort4>(cs.z)) * Float4(1.0f / 0xF800);
 				c.w = Float4(As<UShort4>(cs.w)) * Float4(1.0f / 0x8000);
-			}
-			else
-			{
+				break;
+			case VK_FORMAT_R8_SNORM:
+			case VK_FORMAT_R8G8_SNORM:
+			case VK_FORMAT_R8G8B8A8_SNORM:
+			case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
+				c.x = Float4(cs.x) * Float4(1.0f / 0x7F00);
+				c.y = Float4(cs.y) * Float4(1.0f / 0x7F00);
+				c.z = Float4(cs.z) * Float4(1.0f / 0x7F00);
+				c.w = Float4(cs.w) * Float4(1.0f / 0x7F00);
+				break;
+			default:
 				for(int component = 0; component < textureComponentCount(); component++)
 				{
 					if(hasUnsignedTextureComponent(component))
@@ -1349,6 +1358,16 @@
 							c.z >>= 8;
 							c.w >>= 8;
 						}
+
+						if (state.textureFormat == VK_FORMAT_R8G8B8A8_SNORM)
+						{
+							// TODO: avoid populating the low bits at all.
+							c.x &= Short4(0xFF00);
+							c.y &= Short4(0xFF00);
+							c.z &= Short4(0xFF00);
+							c.w &= Short4(0xFF00);
+						}
+
 						break;
 					case VK_FORMAT_R8G8B8A8_UINT:
 						c.z = As<Short4>(UnpackHigh(c.x, c.y));
@@ -1374,10 +1393,13 @@
 				switch(state.textureFormat)
 				{
 				case VK_FORMAT_R8G8_UNORM:
-				case VK_FORMAT_R8G8_SNORM:
 					c.y = (c.x & Short4(0xFF00u)) | As<Short4>(As<UShort4>(c.x) >> 8);
 					c.x = (c.x & Short4(0x00FFu)) | (c.x << 8);
 					break;
+				case VK_FORMAT_R8G8_SNORM:
+					c.y = (c.x & Short4(0xFF00u));
+					c.x = (c.x << 8);
+					break;
 				case VK_FORMAT_R8G8_SINT:
 					c.y = c.x >> 8;
 					c.x = (c.x << 8) >> 8; // Propagate sign bit
@@ -1412,6 +1434,11 @@
 							}
 						}
 						break;
+					case VK_FORMAT_R8_SNORM:
+						// TODO: avoid populating the low bits at all.
+						c.x = Unpack(As<Byte4>(c0));
+						c.x &= Short4(0xff00);
+						break;
 					default:
 						c.x = Unpack(As<Byte4>(c0));
 						break;