Implement mipmap base/max level.

Change-Id: I611815fb0dcbba97e67f3c146dffb463f133447e
Reviewed-on: https://swiftshader-review.googlesource.com/15248
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Shader/SamplerCore.cpp b/src/Shader/SamplerCore.cpp
index 8aebbd8..53383cd 100644
--- a/src/Shader/SamplerCore.cpp
+++ b/src/Shader/SamplerCore.cpp
@@ -525,17 +525,17 @@
 		mask = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
 	}
 
-	Short4 SamplerCore::offsetSample(Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod)
+	Short4 SamplerCore::offsetSample(Pointer<Byte> &texture, Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod)
 	{
 		Short4 offset = *Pointer<Short4>(mipmap + halfOffset);
 
 		if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
 		{
-			offset &= Short4(CmpNLE(Float4(lod), Float4(0.0f)));
+			offset &= Short4(CmpNLE(Float4(lod), Float4(Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel))))));
 		}
 		else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR)
 		{
-			offset &= Short4(CmpLE(Float4(lod), Float4(0.0f)));
+			offset &= Short4(CmpLE(Float4(lod), Float4(Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel))))));
 		}
 
 		if(wrap)
@@ -759,10 +759,10 @@
 		}
 		else
 		{
-			Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1, lod);
-			Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1, lod);
-			Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1, lod);
-			Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1, lod);
+			Short4 uuuu0 = offsetSample(texture, uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1, lod);
+			Short4 vvvv0 = offsetSample(texture, vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1, lod);
+			Short4 uuuu1 = offsetSample(texture, uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1, lod);
+			Short4 vvvv1 = offsetSample(texture, vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1, lod);
 
 			Vector4s c0 = sampleTexel(uuuu0, vvvv0, wwww, offset, mipmap, buffer, function);
 			Vector4s c1 = sampleTexel(uuuu1, vvvv0, wwww, offset, mipmap, buffer, function);
@@ -966,9 +966,9 @@
 				{
 					for(int k = 0; k < 2; k++)
 					{
-						u[i][j][k] = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, i * 2 - 1, lod);
-						v[i][j][k] = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, j * 2 - 1, lod);
-						s[i][j][k] = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, k * 2 - 1, lod);
+						u[i][j][k] = offsetSample(texture, uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, i * 2 - 1, lod);
+						v[i][j][k] = offsetSample(texture, vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, j * 2 - 1, lod);
+						s[i][j][k] = offsetSample(texture, wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, k * 2 - 1, lod);
 					}
 				}
 			}
@@ -1219,7 +1219,7 @@
 
 		Int4 x0, x1, y0, y1, z0;
 		Float4 fu, fv;
-		Int4 filter = computeFilterOffset(lod);
+		Int4 filter = computeFilterOffset(texture, lod);
 		address(u, x0, x1, fu, mipmap, offset.x, filter, OFFSET(Mipmap, width), state.addressingModeU, function);
 		address(v, y0, y1, fv, mipmap, offset.y, filter, OFFSET(Mipmap, height), state.addressingModeV, function);
 		address(w, z0, z0, fv, mipmap, offset.z, filter, OFFSET(Mipmap, depth), state.addressingModeW, function);
@@ -1288,7 +1288,7 @@
 
 		Int4 x0, x1, y0, y1, z0, z1;
 		Float4 fu, fv, fw;
-		Int4 filter = computeFilterOffset(lod);
+		Int4 filter = computeFilterOffset(texture, lod);
 		address(u, x0, x1, fu, mipmap, offset.x, filter, OFFSET(Mipmap, width), state.addressingModeU, function);
 		address(v, y0, y1, fv, mipmap, offset.y, filter, OFFSET(Mipmap, height), state.addressingModeV, function);
 		address(w, z0, z1, fw, mipmap, offset.z, filter, OFFSET(Mipmap, depth), state.addressingModeW, function);
@@ -1431,19 +1431,22 @@
 		}
 		else if(function == Lod)
 		{
-			lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+			lod = lodBias;
 		}
 		else if(function == Fetch)
 		{
 			// TODO: Eliminate int-float-int conversion.
-			lod = Float(As<Int>(lodBias)) + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+			lod = Float(As<Int>(lodBias));
 		}
 		else if(function == Base)
 		{
-			lod = Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+			lod = Float(0);
 		}
 		else assert(false);
 
+		// TODO: Avoid float conversion.
+		lod += Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+
 		lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
 		lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
 	}
@@ -1497,19 +1500,22 @@
 		}
 		else if(function == Lod)
 		{
-			lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+			lod = lodBias;
 		}
 		else if(function == Fetch)
 		{
 			// TODO: Eliminate int-float-int conversion.
-			lod = Float(As<Int>(lodBias)) + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+			lod = Float(As<Int>(lodBias));
 		}
 		else if(function == Base)
 		{
-			lod = Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+			lod = Float(0);
 		}
 		else assert(false);
 
+		// TODO: Avoid float conversion.
+		lod += Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+
 		lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
 		lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
 	}
@@ -1561,19 +1567,22 @@
 			}
 			else if(function == Lod)
 			{
-				lod = lodBias + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+				lod = lodBias;
 			}
 			else if(function == Fetch)
 			{
 				// TODO: Eliminate int-float-int conversion.
-				lod = Float(As<Int>(lodBias)) + Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+				lod = Float(As<Int>(lodBias));
 			}
 			else if(function == Base)
 			{
-				lod = Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+				lod = Float(0);
 			}
 			else assert(false);
 
+			// TODO: Avoid float conversion.
+			lod += Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)));
+
 			lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
 			lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
 		}
@@ -2277,7 +2286,7 @@
 		}
 	}
 
-	Int4 SamplerCore::computeFilterOffset(Float &lod)
+	Int4 SamplerCore::computeFilterOffset(Pointer<Byte> &texture, Float &lod)
 	{
 		Int4 filter = -1;
 
@@ -2287,11 +2296,11 @@
 		}
 		else if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT)
 		{
-			filter = CmpNLE(Float4(lod), Float4(0.0f));
+			filter = CmpNLE(Float4(lod), Float4(Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)))));
 		}
 		else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR)
 		{
-			filter = CmpLE(Float4(lod), Float4(0.0f));
+			filter = CmpLE(Float4(lod), Float4(Float(*Pointer<Int>(texture + OFFSET(Texture,baseLevel)))));
 		}
 
 		return filter;