Refactor duplicate mipmap LOD calculation

Bug: b/129523279
Change-Id: If4dfa5900ac73643cc8a8052867434d62fa1aa1e
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30430
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp
index 1bb238c..d7039fa 100644
--- a/src/Pipeline/SamplerCore.cpp
+++ b/src/Pipeline/SamplerCore.cpp
@@ -74,23 +74,55 @@
 		Float anisotropy;
 		Float4 uDelta;
 		Float4 vDelta;
+		Float4 M;  // Major axis
 
-		if(state.textureType != TEXTURE_3D)
+		if(state.textureType == TEXTURE_CUBE)
 		{
-			if(state.textureType != TEXTURE_CUBE)
+			cubeFace(face, uuuu, vvvv, u, v, w, M);
+		}
+
+		if(function == Implicit || function == Bias || function == Grad)
+		{
+			if(state.textureType != TEXTURE_3D)
 			{
-				computeLod(texture, sampler, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, lodOrBias.x, dsx, dsy, function);
+				if(state.textureType != TEXTURE_CUBE)
+				{
+					computeLod(texture, sampler, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, lodOrBias.x, dsx, dsy, function);
+				}
+				else
+				{
+					computeLodCube(texture, sampler, lod, u, v, w, lodOrBias.x, dsx, dsy, M, function);
+				}
 			}
 			else
 			{
-				Float4 M;
-				cubeFace(face, uuuu, vvvv, u, v, w, M);
-				computeLodCube(texture, sampler, lod, u, v, w, lodOrBias.x, dsx, dsy, M, function);
+				computeLod3D(texture, sampler, lod, uuuu, vvvv, wwww, lodOrBias.x, dsx, dsy, function);
+			}
+
+			if(function == Bias)
+			{
+				lod += lodOrBias.x;
 			}
 		}
-		else
+		else if(function == Lod)
 		{
-			computeLod3D(texture, sampler, lod, uuuu, vvvv, wwww, lodOrBias.x, dsx, dsy, function);
+			lod = lodOrBias.x;
+		}
+		else if(function == Fetch)
+		{
+			// TODO: Eliminate int-float-int conversion.
+			lod = Float(As<Int>(Float(lodOrBias.x)));
+		}
+		else if(function == Base)
+		{
+			lod = Float(0);
+		}
+		else UNREACHABLE("Sampler function %d", int(function));
+
+		if(function != Base)
+		{
+			lod = Max(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, minLod)));
+			lod = Min(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, maxLod)));
 		}
 
 		// FIXME: YUV is not supported by the floating point path
@@ -1156,198 +1188,123 @@
 
 	void SamplerCore::computeLod(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &uuuu, Float4 &vvvv, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
 	{
-		if(function != Lod && function != Fetch)
+		Float4 duvdxy;
+
+		if(function != Grad)   // Implicit
 		{
-			Float4 duvdxy;
-
-			if(function != Grad)   // Implicit
-			{
-				duvdxy = Float4(uuuu.yz, vvvv.yz) - Float4(uuuu.xx, vvvv.xx);
-			}
-			else
-			{
-				Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
-				Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
-
-				duvdxy = Float4(dudxy.xz, dvdxy.xz);
-			}
-
-			// Scale by texture dimensions.
-			Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture, widthWidthHeightHeight));
-
-			Float4 dUV2dxy = dUVdxy * dUVdxy;
-			Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
-
-			lod = Max(Float(dUV2.x), Float(dUV2.y));   // Square length of major axis
-
-			if(state.textureFilter == FILTER_ANISOTROPIC)
-			{
-				Float det = Abs(Float(dUVdxy.x) * Float(dUVdxy.w) - Float(dUVdxy.y) * Float(dUVdxy.z));
-
-				Float4 dudx = duvdxy.xxxx;
-				Float4 dudy = duvdxy.yyyy;
-				Float4 dvdx = duvdxy.zzzz;
-				Float4 dvdy = duvdxy.wwww;
-
-				Int4 mask = As<Int4>(CmpNLT(dUV2.x, dUV2.y));
-				uDelta = As<Float4>((As<Int4>(dudx) & mask) | ((As<Int4>(dudy) & ~mask)));
-				vDelta = As<Float4>((As<Int4>(dvdx) & mask) | ((As<Int4>(dvdy) & ~mask)));
-
-				anisotropy = lod * Rcp_pp(det);
-				anisotropy = Min(anisotropy, *Pointer<Float>(sampler + OFFSET(vk::Sampler,maxAnisotropy)));
-
-				lod *= Rcp_pp(anisotropy * anisotropy);
-			}
-
-			lod = log2sqrt(lod);   // log2(sqrt(lod))
-
-			if(function == Bias)
-			{
-				lod += lodOrBias;
-			}
+			duvdxy = Float4(uuuu.yz, vvvv.yz) - Float4(uuuu.xx, vvvv.xx);
 		}
-		else if(function == Lod)
+		else
 		{
-			lod = lodOrBias;
-		}
-		else if(function == Fetch)
-		{
-			// TODO: Eliminate int-float-int conversion.
-			lod = Float(As<Int>(lodOrBias));
-		}
-		else if(function == Base)
-		{
-			lod = Float(0);
-		}
-		else assert(false);
+			Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx);
+			Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx);
 
-		lod = Max(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, minLod)));
-		lod = Min(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, maxLod)));
+			duvdxy = Float4(dudxy.xz, dvdxy.xz);
+		}
+
+		// Scale by texture dimensions.
+		Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture, widthWidthHeightHeight));
+
+		Float4 dUV2dxy = dUVdxy * dUVdxy;
+		Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
+
+		lod = Max(Float(dUV2.x), Float(dUV2.y));   // Square length of major axis
+
+		if(state.textureFilter == FILTER_ANISOTROPIC)
+		{
+			Float det = Abs(Float(dUVdxy.x) * Float(dUVdxy.w) - Float(dUVdxy.y) * Float(dUVdxy.z));
+
+			Float4 dudx = duvdxy.xxxx;
+			Float4 dudy = duvdxy.yyyy;
+			Float4 dvdx = duvdxy.zzzz;
+			Float4 dvdy = duvdxy.wwww;
+
+			Int4 mask = As<Int4>(CmpNLT(dUV2.x, dUV2.y));
+			uDelta = As<Float4>((As<Int4>(dudx) & mask) | ((As<Int4>(dudy) & ~mask)));
+			vDelta = As<Float4>((As<Int4>(dvdx) & mask) | ((As<Int4>(dvdy) & ~mask)));
+
+			anisotropy = lod * Rcp_pp(det);
+			anisotropy = Min(anisotropy, *Pointer<Float>(sampler + OFFSET(vk::Sampler,maxAnisotropy)));
+
+			lod *= Rcp_pp(anisotropy * anisotropy);
+		}
+
+		lod = log2sqrt(lod);   // log2(sqrt(lod))
 	}
 
 	void SamplerCore::computeLodCube(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, Float4 &M, SamplerFunction function)
 	{
-		if(function != Lod && function != Fetch)
+		Float4 dudxy, dvdxy, dsdxy;
+
+		if(function != Grad)  // Implicit
 		{
-			Float4 dudxy, dvdxy, dsdxy;
+			Float4 U = u * M;
+			Float4 V = v * M;
+			Float4 W = w * M;
 
-			if(function != Grad)  // Implicit
-			{
-				Float4 U = u * M;
-				Float4 V = v * M;
-				Float4 W = w * M;
-
-				dudxy = Abs(U - U.xxxx);
-				dvdxy = Abs(V - V.xxxx);
-				dsdxy = Abs(W - W.xxxx);
-			}
-			else
-			{
-				dudxy = Float4(dsx.x.xx, dsy.x.xx);
-				dvdxy = Float4(dsx.y.xx, dsy.y.xx);
-				dsdxy = Float4(dsx.z.xx, dsy.z.xx);
-
-				dudxy = Abs(dudxy * Float4(M.x));
-				dvdxy = Abs(dvdxy * Float4(M.x));
-				dsdxy = Abs(dsdxy * Float4(M.x));
-			}
-
-			// Compute the largest Manhattan distance in two dimensions.
-			// This takes the footprint across adjacent faces into account.
-			Float4 duvdxy = dudxy + dvdxy;
-			Float4 dusdxy = dudxy + dsdxy;
-			Float4 dvsdxy = dvdxy + dsdxy;
-
-			dudxy = Max(Max(duvdxy, dusdxy), dvsdxy);
-
-			lod = Max(Float(dudxy.y), Float(dudxy.z));   // FIXME: Max(dudxy.y, dudxy.z);
-
-			// Scale by texture dimension and global LOD.
-			lod *= *Pointer<Float>(texture + OFFSET(Texture,width));
-
-			lod = log2(lod);
-
-			if(function == Bias)
-			{
-				lod += lodOrBias;
-			}
+			dudxy = Abs(U - U.xxxx);
+			dvdxy = Abs(V - V.xxxx);
+			dsdxy = Abs(W - W.xxxx);
 		}
-		else if(function == Lod)
+		else
 		{
-			lod = lodOrBias;
-		}
-		else if(function == Fetch)
-		{
-			// TODO: Eliminate int-float-int conversion.
-			lod = Float(As<Int>(lodOrBias));
-		}
-		else if(function == Base)
-		{
-			lod = Float(0);
-		}
-		else assert(false);
+			dudxy = Float4(dsx.x.xx, dsy.x.xx);
+			dvdxy = Float4(dsx.y.xx, dsy.y.xx);
+			dsdxy = Float4(dsx.z.xx, dsy.z.xx);
 
-		lod = Max(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, minLod)));
-		lod = Min(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, maxLod)));
+			dudxy = Abs(dudxy * Float4(M.x));
+			dvdxy = Abs(dvdxy * Float4(M.x));
+			dsdxy = Abs(dsdxy * Float4(M.x));
+		}
+
+		// Compute the largest Manhattan distance in two dimensions.
+		// This takes the footprint across adjacent faces into account.
+		Float4 duvdxy = dudxy + dvdxy;
+		Float4 dusdxy = dudxy + dsdxy;
+		Float4 dvsdxy = dvdxy + dsdxy;
+
+		dudxy = Max(Max(duvdxy, dusdxy), dvsdxy);
+
+		lod = Max(Float(dudxy.y), Float(dudxy.z));   // FIXME: Max(dudxy.y, dudxy.z);
+
+		// Scale by texture dimension.
+		lod *= *Pointer<Float>(texture + OFFSET(Texture,width));
+
+		lod = log2(lod);
 	}
 
 	void SamplerCore::computeLod3D(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
 	{
-		if(function != Lod && function != Fetch)
+		Float4 dudxy, dvdxy, dsdxy;
+
+		if(function != Grad)   // Implicit
 		{
-			Float4 dudxy, dvdxy, dsdxy;
-
-			if(function != Grad)   // Implicit
-			{
-				dudxy = uuuu - uuuu.xxxx;
-				dvdxy = vvvv - vvvv.xxxx;
-				dsdxy = wwww - wwww.xxxx;
-			}
-			else
-			{
-				dudxy = Float4(dsx.x.xx, dsy.x.xx);
-				dvdxy = Float4(dsx.y.xx, dsy.y.xx);
-				dsdxy = Float4(dsx.z.xx, dsy.z.xx);
-			}
-
-			// Scale by texture dimensions and global LOD.
-			dudxy *= *Pointer<Float4>(texture + OFFSET(Texture, width));
-			dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture, height));
-			dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture, depth));
-
-			dudxy *= dudxy;
-			dvdxy *= dvdxy;
-			dsdxy *= dsdxy;
-
-			dudxy += dvdxy;
-			dudxy += dsdxy;
-
-			lod = Max(Float(dudxy.y), Float(dudxy.z));   // FIXME: Max(dudxy.y, dudxy.z);
-
-			lod = log2sqrt(lod);   // log2(sqrt(lod))
-
-			if(function == Bias)
-			{
-				lod += lodOrBias;
-			}
+			dudxy = uuuu - uuuu.xxxx;
+			dvdxy = vvvv - vvvv.xxxx;
+			dsdxy = wwww - wwww.xxxx;
 		}
-		else if(function == Lod)
+		else
 		{
-			lod = lodOrBias;
+			dudxy = Float4(dsx.x.xx, dsy.x.xx);
+			dvdxy = Float4(dsx.y.xx, dsy.y.xx);
+			dsdxy = Float4(dsx.z.xx, dsy.z.xx);
 		}
-		else if(function == Fetch)
-		{
-			// TODO: Eliminate int-float-int conversion.
-			lod = Float(As<Int>(lodOrBias));
-		}
-		else if(function == Base)
-		{
-			lod = Float(0);
-		}
-		else assert(false);
 
-		lod = Max(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, minLod)));
-		lod = Min(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, maxLod)));
+		// Scale by texture dimensions.
+		dudxy *= *Pointer<Float4>(texture + OFFSET(Texture, width));
+		dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture, height));
+		dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture, depth));
+
+		dudxy *= dudxy;
+		dvdxy *= dvdxy;
+		dsdxy *= dsdxy;
+
+		dudxy += dvdxy;
+		dudxy += dsdxy;
+
+		lod = Max(Float(dudxy.y), Float(dudxy.z));   // FIXME: Max(dudxy.y, dudxy.z);
+
+		lod = log2sqrt(lod);   // log2(sqrt(lod))
 	}
 
 	void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &x, Float4 &y, Float4 &z, Float4 &M)