Eliminate fixed-point texture sampling

The fixed-function OpenGL ES 1.1 and Direct3D 8 texture sampling
operations used 4.12 fixed-point values. SPIR-V only returns float4
or int4 results.

Also eliminate handling of 'null' textures. Vulkan 1.1 demands valid
descriptors

Bug b/129523279

Change-Id: I692bcaced55082b41a9c8a18551c23b03cb18430
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/29272
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp
index fd83369..af19a2a 100644
--- a/src/Pipeline/SamplerCore.cpp
+++ b/src/Pipeline/SamplerCore.cpp
@@ -19,20 +19,6 @@
 
 namespace
 {
-	void applySwizzle(sw::SwizzleType swizzle, sw::Short4& s, const sw::Vector4s& c)
-	{
-		switch(swizzle)
-		{
-		case sw::SWIZZLE_RED:	s = c.x; break;
-		case sw::SWIZZLE_GREEN: s = c.y; break;
-		case sw::SWIZZLE_BLUE:  s = c.z; break;
-		case sw::SWIZZLE_ALPHA: s = c.w; break;
-		case sw::SWIZZLE_ZERO:  s = sw::Short4(0x0000); break;
-		case sw::SWIZZLE_ONE:   s = sw::Short4(0x1000); break;
-		default: ASSERT(false);
-		}
-	}
-
 	void applySwizzle(sw::SwizzleType swizzle, sw::Float4& f, const sw::Vector4f& c)
 	{
 		switch(swizzle)
@@ -56,12 +42,7 @@
 	{
 	}
 
-	Vector4s SamplerCore::sampleTexture(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy)
-	{
-		return sampleTexture(texture, u, v, w, q, q, dsx, dsy, (dsx), Implicit, true);
-	}
-
-	Vector4s SamplerCore::sampleTexture(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function, bool fixed12)
+	Vector4s SamplerCore::sampleTexture(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
 	{
 		Vector4s c;
 
@@ -74,23 +55,57 @@
 			}
 		#endif
 
-		if(state.textureType == TEXTURE_NULL)
-		{
-			c.x = Short4(0x0000);
-			c.y = Short4(0x0000);
-			c.z = Short4(0x0000);
+		Float4 uuuu = u;
+		Float4 vvvv = v;
+		Float4 wwww = w;
+		Float4 qqqq = q;
 
-			if(fixed12)   // FIXME: Convert to fixed12 at higher level, when required
+		Int face[4];
+		Float lod;
+		Float anisotropy;
+		Float4 uDelta;
+		Float4 vDelta;
+
+		if(state.textureType != TEXTURE_3D)
+		{
+			if(state.textureType != TEXTURE_CUBE)
 			{
-				c.w = Short4(0x1000);
+				computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, bias.x, dsx, dsy, function);
 			}
 			else
 			{
-				c.w = Short4(0xFFFFu);   // FIXME
+				Float4 M;
+				cubeFace(face, uuuu, vvvv, u, v, w, M);
+				computeLodCube(texture, lod, u, v, w, bias.x, dsx, dsy, M, function);
 			}
 		}
 		else
 		{
+			computeLod3D(texture, lod, uuuu, vvvv, wwww, bias.x, dsx, dsy, function);
+		}
+
+		return sampleFilter(texture, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
+	}
+
+	Vector4f SamplerCore::sampleTextureF(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
+	{
+		Vector4f c;
+
+		#if PERF_PROFILE
+			AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
+
+			if(state.compressedFormat)
+			{
+				AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
+			}
+		#endif
+
+		// FIXME: YUV is not supported by the floating point path
+		bool forceFloatFiltering = state.highPrecisionFiltering && !hasYuvFormat() && (state.textureFilter != FILTER_POINT);
+		bool seamlessCube = (state.addressingModeU == ADDRESSING_SEAMLESS);
+		bool rectangleTexture = (state.textureType == TEXTURE_RECTANGLE);
+		if(hasFloatTexture() || hasUnnormalizedIntegerTexture() || forceFloatFiltering || seamlessCube || rectangleTexture)   // FIXME: Mostly identical to integer sampling
+		{
 			Float4 uuuu = u;
 			Float4 vvvv = v;
 			Float4 wwww = w;
@@ -120,291 +135,126 @@
 				computeLod3D(texture, lod, uuuu, vvvv, wwww, bias.x, dsx, dsy, function);
 			}
 
-			if(!hasFloatTexture())
-			{
-				c = sampleFilter(texture, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
-			}
-			else
-			{
-				Vector4f cf = sampleFloatFilter(texture, uuuu, vvvv, wwww, qqqq, offset, lod, anisotropy, uDelta, vDelta, face, function);
+			c = sampleFloatFilter(texture, uuuu, vvvv, wwww, qqqq, offset, lod, anisotropy, uDelta, vDelta, face, function);
 
-				convertFixed12(c, cf);
-			}
-
-			if(fixed12)
+			if(!hasFloatTexture() && !hasUnnormalizedIntegerTexture())
 			{
-				if(!hasFloatTexture())
+				if(has16bitTextureFormat())
 				{
-					if(state.textureFormat == VK_FORMAT_R5G6B5_UNORM_PACK16)
-					{
-						c.x = MulHigh(As<UShort4>(c.x), UShort4(0x10000000 / 0xF800));
-						c.y = MulHigh(As<UShort4>(c.y), UShort4(0x10000000 / 0xFC00));
-						c.z = MulHigh(As<UShort4>(c.z), UShort4(0x10000000 / 0xF800));
-					}
-					else
-					{
-						for(int component = 0; component < textureComponentCount(); component++)
-						{
-							if(hasUnsignedTextureComponent(component))
-							{
-								c[component] = As<UShort4>(c[component]) >> 4;
-							}
-							else
-							{
-								c[component] = c[component] >> 3;
-							}
-						}
-					}
-				}
-
-				if(state.textureFilter != FILTER_GATHER)
-				{
-					int componentCount = textureComponentCount();
-					short defaultColorValue = colorsDefaultToZero ? 0x0000 : 0x1000;
-
 					switch(state.textureFormat)
 					{
-					case VK_FORMAT_R8_SNORM:
-					case VK_FORMAT_R8G8_SNORM:
-					case VK_FORMAT_R8G8B8A8_SNORM:
-					case VK_FORMAT_R8_UNORM:
 					case VK_FORMAT_R5G6B5_UNORM_PACK16:
-					case VK_FORMAT_R8G8_UNORM:
-					case VK_FORMAT_R8_SINT:
-					case VK_FORMAT_R8_UINT:
-					case VK_FORMAT_R8G8_SINT:
-					case VK_FORMAT_R8G8_UINT:
-					case VK_FORMAT_R8G8B8A8_SINT:
-					case VK_FORMAT_R8G8B8A8_UINT:
-					case VK_FORMAT_R16_SINT:
-					case VK_FORMAT_R16_UINT:
-					case VK_FORMAT_R16G16_UNORM:
-					case VK_FORMAT_R16G16_SINT:
-					case VK_FORMAT_R16G16_UINT:
-					case VK_FORMAT_R16G16B16A16_UNORM:
-					case VK_FORMAT_R16G16B16A16_SINT:
-					case VK_FORMAT_R16G16B16A16_UINT:
-					case VK_FORMAT_R32_SINT:
-					case VK_FORMAT_R32_UINT:
-					case VK_FORMAT_R32G32_SINT:
-					case VK_FORMAT_R32G32_UINT:
-					case VK_FORMAT_R32G32B32A32_SINT:
-					case VK_FORMAT_R32G32B32A32_UINT:
-					case VK_FORMAT_B8G8R8A8_UNORM:
-					case VK_FORMAT_R8G8B8A8_UNORM:
-					case VK_FORMAT_R8G8B8A8_SRGB:
-					case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
-						if(componentCount < 2) c.y = Short4(defaultColorValue);
-						if(componentCount < 3) c.z = Short4(defaultColorValue);
-						if(componentCount < 4) c.w = Short4(0x1000);
-						break;
-					case VK_FORMAT_R32_SFLOAT:
-						c.y = Short4(defaultColorValue);
-					case VK_FORMAT_R32G32_SFLOAT:
-						c.z = Short4(defaultColorValue);
-						c.w = Short4(0x1000);
-					case VK_FORMAT_R32G32B32A32_SFLOAT:
+						c.x *= Float4(1.0f / 0xF800);
+						c.y *= Float4(1.0f / 0xFC00);
+						c.z *= Float4(1.0f / 0xF800);
 						break;
 					default:
 						ASSERT(false);
 					}
 				}
-
-				if((state.swizzleR != SWIZZLE_RED) ||
-				   (state.swizzleG != SWIZZLE_GREEN) ||
-				   (state.swizzleB != SWIZZLE_BLUE) ||
-				   (state.swizzleA != SWIZZLE_ALPHA))
-				{
-					const Vector4s col(c);
-					applySwizzle(state.swizzleR, c.x, col);
-					applySwizzle(state.swizzleG, c.y, col);
-					applySwizzle(state.swizzleB, c.z, col);
-					applySwizzle(state.swizzleA, c.w, col);
-				}
-			}
-		}
-
-		return c;
-	}
-
-	Vector4f SamplerCore::sampleTextureF(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
-	{
-		Vector4f c;
-
-		#if PERF_PROFILE
-			AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
-
-			if(state.compressedFormat)
-			{
-				AddAtomic(Pointer<Long>(&profiler.compressedTex), 4);
-			}
-		#endif
-
-		if(state.textureType == TEXTURE_NULL)
-		{
-			c.x = Float4(0.0f);
-			c.y = Float4(0.0f);
-			c.z = Float4(0.0f);
-			c.w = Float4(1.0f);
-		}
-		else
-		{
-			// FIXME: YUV is not supported by the floating point path
-			bool forceFloatFiltering = state.highPrecisionFiltering && !hasYuvFormat() && (state.textureFilter != FILTER_POINT);
-			bool seamlessCube = (state.addressingModeU == ADDRESSING_SEAMLESS);
-			bool rectangleTexture = (state.textureType == TEXTURE_RECTANGLE);
-			if(hasFloatTexture() || hasUnnormalizedIntegerTexture() || forceFloatFiltering || seamlessCube || rectangleTexture)   // FIXME: Mostly identical to integer sampling
-			{
-				Float4 uuuu = u;
-				Float4 vvvv = v;
-				Float4 wwww = w;
-				Float4 qqqq = q;
-
-				Int face[4];
-				Float lod;
-				Float anisotropy;
-				Float4 uDelta;
-				Float4 vDelta;
-
-				if(state.textureType != TEXTURE_3D)
-				{
-					if(state.textureType != TEXTURE_CUBE)
-					{
-						computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, bias.x, dsx, dsy, function);
-					}
-					else
-					{
-						Float4 M;
-						cubeFace(face, uuuu, vvvv, u, v, w, M);
-						computeLodCube(texture, lod, u, v, w, bias.x, dsx, dsy, M, function);
-					}
-				}
-				else
-				{
-					computeLod3D(texture, lod, uuuu, vvvv, wwww, bias.x, dsx, dsy, function);
-				}
-
-				c = sampleFloatFilter(texture, uuuu, vvvv, wwww, qqqq, offset, lod, anisotropy, uDelta, vDelta, face, function);
-
-				if(!hasFloatTexture() && !hasUnnormalizedIntegerTexture())
-				{
-					if(has16bitTextureFormat())
-					{
-						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;
-						default:
-							ASSERT(false);
-						}
-					}
-					else
-					{
-						for(int component = 0; component < textureComponentCount(); component++)
-						{
-							c[component] *= Float4(hasUnsignedTextureComponent(component) ? 1.0f / 0xFFFF : 1.0f / 0x7FFF);
-						}
-					}
-				}
-			}
-			else
-			{
-				Vector4s cs = sampleTexture(texture, u, v, w, q, bias, dsx, dsy, offset, function, false);
-
-				if(state.textureFormat ==  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
 				{
 					for(int component = 0; component < textureComponentCount(); component++)
 					{
-						if(hasUnsignedTextureComponent(component))
-						{
-							convertUnsigned16(c[component], cs[component]);
-						}
-						else
-						{
-							convertSigned15(c[component], cs[component]);
-						}
+						c[component] *= Float4(hasUnsignedTextureComponent(component) ? 1.0f / 0xFFFF : 1.0f / 0x7FFF);
 					}
 				}
 			}
+		}
+		else
+		{
+			Vector4s cs = sampleTexture(texture, u, v, w, q, bias, dsx, dsy, offset, function);
 
-			int componentCount = textureComponentCount();
-			float defaultColorValue = colorsDefaultToZero ? 0.0f : 1.0f;
-
-			if(state.textureFilter != FILTER_GATHER)
+			if(state.textureFormat ==  VK_FORMAT_R5G6B5_UNORM_PACK16)
 			{
-				switch(state.textureFormat)
+				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
+			{
+				for(int component = 0; component < textureComponentCount(); component++)
 				{
-				case VK_FORMAT_R8_SINT:
-				case VK_FORMAT_R8_UINT:
-				case VK_FORMAT_R16_SINT:
-				case VK_FORMAT_R16_UINT:
-				case VK_FORMAT_R32_SINT:
-				case VK_FORMAT_R32_UINT:
-					c.y = As<Float4>(UInt4(0));
-				case VK_FORMAT_R8G8_SINT:
-				case VK_FORMAT_R8G8_UINT:
-				case VK_FORMAT_R16G16_SINT:
-				case VK_FORMAT_R16G16_UINT:
-				case VK_FORMAT_R32G32_SINT:
-				case VK_FORMAT_R32G32_UINT:
-					c.z = As<Float4>(UInt4(0));
-				case VK_FORMAT_R8G8B8A8_SINT:
-				case VK_FORMAT_R8G8B8A8_UINT:
-				case VK_FORMAT_R16G16B16A16_SINT:
-				case VK_FORMAT_R16G16B16A16_UINT:
-				case VK_FORMAT_R32G32B32A32_SINT:
-				case VK_FORMAT_R32G32B32A32_UINT:
-					break;
-				case VK_FORMAT_R8_SNORM:
-				case VK_FORMAT_R8G8_SNORM:
-				case VK_FORMAT_R8G8B8A8_SNORM:
-				case VK_FORMAT_R8_UNORM:
-				case VK_FORMAT_R5G6B5_UNORM_PACK16:
-				case VK_FORMAT_R8G8_UNORM:
-				case VK_FORMAT_R16G16_UNORM:
-				case VK_FORMAT_R16G16B16A16_UNORM:
-				case VK_FORMAT_B8G8R8A8_UNORM:
-				case VK_FORMAT_R8G8B8A8_UNORM:
-				case VK_FORMAT_R8G8B8A8_SRGB:
-				case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
-					if(componentCount < 2) c.y = Float4(defaultColorValue);
-					if(componentCount < 3) c.z = Float4(defaultColorValue);
-					if(componentCount < 4) c.w = Float4(1.0f);
-					break;
-				case VK_FORMAT_R32_SFLOAT:
-					c.y = Float4(defaultColorValue);
-				case VK_FORMAT_R32G32_SFLOAT:
-					c.z = Float4(defaultColorValue);
-					c.w = Float4(1.0f);
-				case VK_FORMAT_R32G32B32A32_SFLOAT:
-					break;
-				default:
-					ASSERT(false);
+					if(hasUnsignedTextureComponent(component))
+					{
+						convertUnsigned16(c[component], cs[component]);
+					}
+					else
+					{
+						convertSigned15(c[component], cs[component]);
+					}
 				}
 			}
+		}
 
-			if((state.swizzleR != SWIZZLE_RED) ||
-			   (state.swizzleG != SWIZZLE_GREEN) ||
-			   (state.swizzleB != SWIZZLE_BLUE) ||
-			   (state.swizzleA != SWIZZLE_ALPHA))
+		int componentCount = textureComponentCount();
+		float defaultColorValue = colorsDefaultToZero ? 0.0f : 1.0f;
+
+		if(state.textureFilter != FILTER_GATHER)
+		{
+			switch(state.textureFormat)
 			{
-				const Vector4f col(c);
-				applySwizzle(state.swizzleR, c.x, col);
-				applySwizzle(state.swizzleG, c.y, col);
-				applySwizzle(state.swizzleB, c.z, col);
-				applySwizzle(state.swizzleA, c.w, col);
+			case VK_FORMAT_R8_SINT:
+			case VK_FORMAT_R8_UINT:
+			case VK_FORMAT_R16_SINT:
+			case VK_FORMAT_R16_UINT:
+			case VK_FORMAT_R32_SINT:
+			case VK_FORMAT_R32_UINT:
+				c.y = As<Float4>(UInt4(0));
+			case VK_FORMAT_R8G8_SINT:
+			case VK_FORMAT_R8G8_UINT:
+			case VK_FORMAT_R16G16_SINT:
+			case VK_FORMAT_R16G16_UINT:
+			case VK_FORMAT_R32G32_SINT:
+			case VK_FORMAT_R32G32_UINT:
+				c.z = As<Float4>(UInt4(0));
+			case VK_FORMAT_R8G8B8A8_SINT:
+			case VK_FORMAT_R8G8B8A8_UINT:
+			case VK_FORMAT_R16G16B16A16_SINT:
+			case VK_FORMAT_R16G16B16A16_UINT:
+			case VK_FORMAT_R32G32B32A32_SINT:
+			case VK_FORMAT_R32G32B32A32_UINT:
+				break;
+			case VK_FORMAT_R8_SNORM:
+			case VK_FORMAT_R8G8_SNORM:
+			case VK_FORMAT_R8G8B8A8_SNORM:
+			case VK_FORMAT_R8_UNORM:
+			case VK_FORMAT_R5G6B5_UNORM_PACK16:
+			case VK_FORMAT_R8G8_UNORM:
+			case VK_FORMAT_R16G16_UNORM:
+			case VK_FORMAT_R16G16B16A16_UNORM:
+			case VK_FORMAT_B8G8R8A8_UNORM:
+			case VK_FORMAT_R8G8B8A8_UNORM:
+			case VK_FORMAT_R8G8B8A8_SRGB:
+			case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+				if(componentCount < 2) c.y = Float4(defaultColorValue);
+				if(componentCount < 3) c.z = Float4(defaultColorValue);
+				if(componentCount < 4) c.w = Float4(1.0f);
+				break;
+			case VK_FORMAT_R32_SFLOAT:
+				c.y = Float4(defaultColorValue);
+			case VK_FORMAT_R32G32_SFLOAT:
+				c.z = Float4(defaultColorValue);
+				c.w = Float4(1.0f);
+			case VK_FORMAT_R32G32B32A32_SFLOAT:
+				break;
+			default:
+				ASSERT(false);
 			}
 		}
 
+		if((state.swizzleR != SWIZZLE_RED) ||
+			(state.swizzleG != SWIZZLE_GREEN) ||
+			(state.swizzleB != SWIZZLE_BLUE) ||
+			(state.swizzleA != SWIZZLE_ALPHA))
+		{
+			const Vector4f col(c);
+			applySwizzle(state.swizzleR, c.x, col);
+			applySwizzle(state.swizzleG, c.y, col);
+			applySwizzle(state.swizzleB, c.z, col);
+			applySwizzle(state.swizzleA, c.w, col);
+		}
+
 		return c;
 	}
 
@@ -2352,32 +2202,6 @@
 		}
 	}
 
-	void SamplerCore::convertFixed12(Short4 &cs, Float4 &cf)
-	{
-		cs = RoundShort4(cf * Float4(0x1000));
-	}
-
-	void SamplerCore::convertFixed12(Vector4s &cs, Vector4f &cf)
-	{
-		convertFixed12(cs.x, cf.x);
-		convertFixed12(cs.y, cf.y);
-		convertFixed12(cs.z, cf.z);
-		convertFixed12(cs.w, cf.w);
-	}
-
-	void SamplerCore::convertSigned12(Float4 &cf, Short4 &cs)
-	{
-		cf = Float4(cs) * Float4(1.0f / 0x0FFE);
-	}
-
-//	void SamplerCore::convertSigned12(Vector4f &cf, Vector4s &cs)
-//	{
-//		convertSigned12(cf.x, cs.x);
-//		convertSigned12(cf.y, cs.y);
-//		convertSigned12(cf.z, cs.z);
-//		convertSigned12(cf.w, cs.w);
-//	}
-
 	void SamplerCore::convertSigned15(Float4 &cf, Short4 &cs)
 	{
 		cf = Float4(cs) * Float4(1.0f / 0x7FFF);