Refactor sampler LOD calculation method into an enum.

Change-Id: I0beed96cd68608ce07aec0b11f14d6f61e67e53d
Reviewed-on: https://swiftshader-review.googlesource.com/5034
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/Shader/PixelPipeline.cpp b/src/Shader/PixelPipeline.cpp
index 7669163..99f91e7 100644
--- a/src/Shader/PixelPipeline.cpp
+++ b/src/Shader/PixelPipeline.cpp
@@ -94,9 +94,9 @@
 			Vector4s s1;
 			Vector4s s2;
 
-			if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegisterS(src0);
-			if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegisterS(src1);
-			if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegisterS(src2);
+			if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegister(src0);
+			if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegister(src1);
+			if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegister(src2);
 
 			Float4 x = version < 0x0104 ? v[2 + dst.index].x : v[2 + src0.index].x;
 			Float4 y = version < 0x0104 ? v[2 + dst.index].y : v[2 + src0.index].y;
@@ -1221,25 +1221,20 @@
 		sampleTexture(c, stage, x, y, z, w, project);
 	}
 
-	void PixelPipeline::sampleTexture(Vector4s &c, int stage, Float4 &u, Float4 &v, Float4 &w, Float4 &q, bool project, bool bias)
+	void PixelPipeline::sampleTexture(Vector4s &c, int stage, Float4 &u, Float4 &v, Float4 &w, Float4 &q, bool project)
 	{
+		#if PERF_PROFILE
+			Long texTime = Ticks();
+		#endif
+
 		Vector4f dsx;
 		Vector4f dsy;
 
-		sampleTexture(c, stage, u, v, w, q, dsx, dsy, project, bias, false);
-	}
-
-	void PixelPipeline::sampleTexture(Vector4s &c, int stage, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool project, bool bias, bool gradients, bool lodProvided)
-	{
-#if PERF_PROFILE
-		Long texTime = Ticks();
-#endif
-
 		Pointer<Byte> texture = data + OFFSET(DrawData, mipmap) + stage * sizeof(Texture);
 
 		if(!project)
 		{
-			sampler[stage]->sampleTexture(texture, c, u, v, w, q, dsx, dsy, bias, gradients, lodProvided);
+			sampler[stage]->sampleTexture(texture, c, u, v, w, q, dsx, dsy);
 		}
 		else
 		{
@@ -1249,12 +1244,12 @@
 			Float4 v_q = v * rq;
 			Float4 w_q = w * rq;
 
-			sampler[stage]->sampleTexture(texture, c, u_q, v_q, w_q, q, dsx, dsy, bias, gradients, lodProvided);
+			sampler[stage]->sampleTexture(texture, c, u_q, v_q, w_q, q, dsx, dsy);
 		}
 
-#if PERF_PROFILE
-		cycles[PERF_TEX] += Ticks() - texTime;
-#endif
+		#if PERF_PROFILE
+			cycles[PERF_TEX] += Ticks() - texTime;
+		#endif
 	}
 
 	Short4 PixelPipeline::convertFixed12(RValue<Float4> cf)
@@ -1317,7 +1312,7 @@
 		}
 	}
 
-	Vector4s PixelPipeline::fetchRegisterS(const Src &src)
+	Vector4s PixelPipeline::fetchRegister(const Src &src)
 	{
 		Vector4s *reg;
 		int i = src.index;
diff --git a/src/Shader/PixelPipeline.hpp b/src/Shader/PixelPipeline.hpp
index fd76b3e..4d0362d 100644
--- a/src/Shader/PixelPipeline.hpp
+++ b/src/Shader/PixelPipeline.hpp
@@ -57,8 +57,7 @@
 		void specularPixel(Vector4s &current, Vector4s &specular);

 

 		void sampleTexture(Vector4s &c, int coordinates, int sampler, bool project = false);

-		void sampleTexture(Vector4s &c, int sampler, Float4 &u, Float4 &v, Float4 &w, Float4 &q, bool project = false, bool bias = false);

-		void sampleTexture(Vector4s &c, int sampler, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool project = false, bool bias = false, bool gradients = false, bool lodProvided = false);

+		void sampleTexture(Vector4s &c, int sampler, Float4 &u, Float4 &v, Float4 &w, Float4 &q, bool project = false);

 

 		Short4 convertFixed12(RValue<Float4> cf);

 		void convertFixed12(Vector4s &cs, Vector4f &cf);

@@ -66,7 +65,7 @@
 		void convertSigned12(Vector4f &cf, Vector4s &cs);

 

 		void writeDestination(Vector4s &d, const Dst &dst);

-		Vector4s fetchRegisterS(const Src &src);

+		Vector4s fetchRegister(const Src &src);

 

 		// Instructions

 		void MOV(Vector4s &dst, Vector4s &src0);

diff --git a/src/Shader/PixelProgram.cpp b/src/Shader/PixelProgram.cpp
index 0286bc30..6eca4eb 100644
--- a/src/Shader/PixelProgram.cpp
+++ b/src/Shader/PixelProgram.cpp
@@ -136,11 +136,11 @@
 				}
 			}
 
-			if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegisterF(src0);
-			if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegisterF(src1);
-			if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegisterF(src2);
-			if(src3.type != Shader::PARAMETER_VOID) s3 = fetchRegisterF(src3);
-			if(src4.type != Shader::PARAMETER_VOID) s4 = fetchRegisterF(src4);
+			if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegister(src0);
+			if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegister(src1);
+			if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegister(src2);
+			if(src3.type != Shader::PARAMETER_VOID) s3 = fetchRegister(src3);
+			if(src4.type != Shader::PARAMETER_VOID) s4 = fetchRegister(src4);
 
 			switch(opcode)
 			{
@@ -270,8 +270,8 @@
 			case Shader::OPCODE_M3X3:       M3X3(d, s0, src1);                             break;
 			case Shader::OPCODE_M3X2:       M3X2(d, s0, src1);                             break;
 			case Shader::OPCODE_TEX:        TEXLD(d, s0, src1, project, bias);             break;
-			case Shader::OPCODE_TEXLDD:     TEXLDD(d, s0, src1, s2, s3, project, bias);    break;
-			case Shader::OPCODE_TEXLDL:     TEXLDL(d, s0, src1, project, bias);            break;
+			case Shader::OPCODE_TEXLDD:     TEXLDD(d, s0, src1, s2, s3, project);          break;
+			case Shader::OPCODE_TEXLDL:     TEXLDL(d, s0, src1, project);                  break;
 			case Shader::OPCODE_TEXSIZE:    TEXSIZE(d, s0.x, src1);                        break;
 			case Shader::OPCODE_TEXKILL:    TEXKILL(cMask, d, dst.mask);                   break;
 			case Shader::OPCODE_TEXOFFSET:  TEXOFFSET(d, s0, src1, s2, s3, project, bias); break;
@@ -624,15 +624,17 @@
 		}
 	}
 
-	void PixelProgram::sampleTexture(Vector4f &c, const Src &sampler, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool project, bool bias, bool gradients, bool lodProvided)
+	void PixelProgram::sampleTexture(Vector4f &c, const Src &sampler, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool project, SamplerMethod method)
 	{
+		Vector4f tmp;
+
 		if(sampler.type == Shader::PARAMETER_SAMPLER && sampler.rel.type == Shader::PARAMETER_VOID)
 		{
-			sampleTexture(c, sampler.index, u, v, w, q, dsx, dsy, project, bias, gradients, lodProvided);
+			sampleTexture(tmp, sampler.index, u, v, w, q, dsx, dsy, project, method);
 		}
 		else
 		{
-			Int index = As<Int>(Float(fetchRegisterF(sampler).x.x));
+			Int index = As<Int>(Float(fetchRegister(sampler).x.x));
 
 			for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++)
 			{
@@ -640,25 +642,30 @@
 				{
 					If(index == i)
 					{
-						sampleTexture(c, i, u, v, w, q, dsx, dsy, project, bias, gradients, lodProvided);
+						sampleTexture(tmp, i, u, v, w, q, dsx, dsy, project, method);
 						// FIXME: When the sampler states are the same, we could use one sampler and just index the texture
 					}
 				}
 			}
 		}
+
+		c.x = tmp[(sampler.swizzle >> 0) & 0x3];
+		c.y = tmp[(sampler.swizzle >> 2) & 0x3];
+		c.z = tmp[(sampler.swizzle >> 4) & 0x3];
+		c.w = tmp[(sampler.swizzle >> 6) & 0x3];
 	}
 
-	void PixelProgram::sampleTexture(Vector4f &c, int stage, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool project, bool bias, bool gradients, bool lodProvided)
+	void PixelProgram::sampleTexture(Vector4f &c, int stage, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool project, SamplerMethod method)
 	{
-#if PERF_PROFILE
-		Long texTime = Ticks();
-#endif
+		#if PERF_PROFILE
+			Long texTime = Ticks();
+		#endif
 
 		Pointer<Byte> texture = data + OFFSET(DrawData, mipmap) + stage * sizeof(Texture);
 
 		if(!project)
 		{
-			sampler[stage]->sampleTexture(texture, c, u, v, w, q, dsx, dsy, bias, gradients, lodProvided);
+			sampler[stage]->sampleTexture(texture, c, u, v, w, q, dsx, dsy, method);
 		}
 		else
 		{
@@ -668,12 +675,12 @@
 			Float4 v_q = v * rq;
 			Float4 w_q = w * rq;
 
-			sampler[stage]->sampleTexture(texture, c, u_q, v_q, w_q, q, dsx, dsy, bias, gradients, lodProvided);
+			sampler[stage]->sampleTexture(texture, c, u_q, v_q, w_q, q, dsx, dsy, method);
 		}
 
-#if PERF_PROFILE
-		cycles[PERF_TEX] += Ticks() - texTime;
-#endif
+		#if PERF_PROFILE
+			cycles[PERF_TEX] += Ticks() - texTime;
+		#endif
 	}
 
 	void PixelProgram::clampColor(Vector4f oC[RENDERTARGETS])
@@ -743,7 +750,7 @@
 		return enable;
 	}
 
-	Vector4f PixelProgram::fetchRegisterF(const Src &src, unsigned int offset)
+	Vector4f PixelProgram::fetchRegister(const Src &src, unsigned int offset)
 	{
 		Vector4f reg;
 		unsigned int i = src.index + offset;
@@ -989,8 +996,8 @@
 
 	void PixelProgram::M3X2(Vector4f &dst, Vector4f &src0, const Src &src1)
 	{
-		Vector4f row0 = fetchRegisterF(src1, 0);
-		Vector4f row1 = fetchRegisterF(src1, 1);
+		Vector4f row0 = fetchRegister(src1, 0);
+		Vector4f row1 = fetchRegister(src1, 1);
 
 		dst.x = dot3(src0, row0);
 		dst.y = dot3(src0, row1);
@@ -998,9 +1005,9 @@
 
 	void PixelProgram::M3X3(Vector4f &dst, Vector4f &src0, const Src &src1)
 	{
-		Vector4f row0 = fetchRegisterF(src1, 0);
-		Vector4f row1 = fetchRegisterF(src1, 1);
-		Vector4f row2 = fetchRegisterF(src1, 2);
+		Vector4f row0 = fetchRegister(src1, 0);
+		Vector4f row1 = fetchRegister(src1, 1);
+		Vector4f row2 = fetchRegister(src1, 2);
 
 		dst.x = dot3(src0, row0);
 		dst.y = dot3(src0, row1);
@@ -1009,10 +1016,10 @@
 
 	void PixelProgram::M3X4(Vector4f &dst, Vector4f &src0, const Src &src1)
 	{
-		Vector4f row0 = fetchRegisterF(src1, 0);
-		Vector4f row1 = fetchRegisterF(src1, 1);
-		Vector4f row2 = fetchRegisterF(src1, 2);
-		Vector4f row3 = fetchRegisterF(src1, 3);
+		Vector4f row0 = fetchRegister(src1, 0);
+		Vector4f row1 = fetchRegister(src1, 1);
+		Vector4f row2 = fetchRegister(src1, 2);
+		Vector4f row3 = fetchRegister(src1, 3);
 
 		dst.x = dot3(src0, row0);
 		dst.y = dot3(src0, row1);
@@ -1022,9 +1029,9 @@
 
 	void PixelProgram::M4X3(Vector4f &dst, Vector4f &src0, const Src &src1)
 	{
-		Vector4f row0 = fetchRegisterF(src1, 0);
-		Vector4f row1 = fetchRegisterF(src1, 1);
-		Vector4f row2 = fetchRegisterF(src1, 2);
+		Vector4f row0 = fetchRegister(src1, 0);
+		Vector4f row1 = fetchRegister(src1, 1);
+		Vector4f row2 = fetchRegister(src1, 2);
 
 		dst.x = dot4(src0, row0);
 		dst.y = dot4(src0, row1);
@@ -1033,10 +1040,10 @@
 
 	void PixelProgram::M4X4(Vector4f &dst, Vector4f &src0, const Src &src1)
 	{
-		Vector4f row0 = fetchRegisterF(src1, 0);
-		Vector4f row1 = fetchRegisterF(src1, 1);
-		Vector4f row2 = fetchRegisterF(src1, 2);
-		Vector4f row3 = fetchRegisterF(src1, 3);
+		Vector4f row0 = fetchRegister(src1, 0);
+		Vector4f row1 = fetchRegister(src1, 1);
+		Vector4f row2 = fetchRegister(src1, 2);
+		Vector4f row3 = fetchRegister(src1, 3);
 
 		dst.x = dot4(src0, row0);
 		dst.y = dot4(src0, row1);
@@ -1046,13 +1053,7 @@
 
 	void PixelProgram::TEXLD(Vector4f &dst, Vector4f &src0, const Src &src1, bool project, bool bias)
 	{
-		Vector4f tmp;
-		sampleTexture(tmp, src1, src0.x, src0.y, src0.z, src0.w, src0, src0, project, bias);
-
-		dst.x = tmp[(src1.swizzle >> 0) & 0x3];
-		dst.y = tmp[(src1.swizzle >> 2) & 0x3];
-		dst.z = tmp[(src1.swizzle >> 4) & 0x3];
-		dst.w = tmp[(src1.swizzle >> 6) & 0x3];
+		sampleTexture(dst, src1, src0.x, src0.y, src0.z, src0.w, src0, src0, project, bias ? Bias : Implicit);
 	}
 
 	void PixelProgram::TEXOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3, bool project, bool bias)
@@ -1085,26 +1086,14 @@
 		UNIMPLEMENTED();
 	}
 
-	void PixelProgram::TEXLDD(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &src2, Vector4f &src3, bool project, bool bias)
+	void PixelProgram::TEXLDD(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &src2, Vector4f &src3, bool project)
 	{
-		Vector4f tmp;
-		sampleTexture(tmp, src1, src0.x, src0.y, src0.z, src0.w, src2, src3, project, bias, true);
-
-		dst.x = tmp[(src1.swizzle >> 0) & 0x3];
-		dst.y = tmp[(src1.swizzle >> 2) & 0x3];
-		dst.z = tmp[(src1.swizzle >> 4) & 0x3];
-		dst.w = tmp[(src1.swizzle >> 6) & 0x3];
+		sampleTexture(dst, src1, src0.x, src0.y, src0.z, src0.w, src2, src3, project, Grad);
 	}
 
-	void PixelProgram::TEXLDL(Vector4f &dst, Vector4f &src0, const Src &src1, bool project, bool bias)
+	void PixelProgram::TEXLDL(Vector4f &dst, Vector4f &src0, const Src &src1, bool project)
 	{
-		Vector4f tmp;
-		sampleTexture(tmp, src1, src0.x, src0.y, src0.z, src0.w, src0, src0, project, bias, false, true);
-
-		dst.x = tmp[(src1.swizzle >> 0) & 0x3];
-		dst.y = tmp[(src1.swizzle >> 2) & 0x3];
-		dst.z = tmp[(src1.swizzle >> 4) & 0x3];
-		dst.w = tmp[(src1.swizzle >> 6) & 0x3];
+		sampleTexture(dst, src1, src0.x, src0.y, src0.z, src0.w, src0, src0, project, Lod);
 	}
 
 	void PixelProgram::TEXSIZE(Vector4f &dst, Float4 &lod, const Src &src1)
@@ -1458,7 +1447,7 @@
 		}
 		else
 		{
-			Int4 condition = As<Int4>(fetchRegisterF(src).x);
+			Int4 condition = As<Int4>(fetchRegister(src).x);
 			IF(condition);
 		}
 	}
@@ -1627,7 +1616,7 @@
 		Nucleus::setInsertBlock(testBlock);
 		enableContinue = restoreContinue;
 
-		const Vector4f &src = fetchRegisterF(temporaryRegister);
+		const Vector4f &src = fetchRegister(temporaryRegister);
 		Int4 condition = As<Int4>(src.x);
 		condition &= enableStack[enableIndex - 1];
 		enableStack[enableIndex] = condition;
diff --git a/src/Shader/PixelProgram.hpp b/src/Shader/PixelProgram.hpp
index ab69b62..085255d 100644
--- a/src/Shader/PixelProgram.hpp
+++ b/src/Shader/PixelProgram.hpp
@@ -13,6 +13,7 @@
 #define sw_PixelProgram_hpp

 

 #include "PixelRoutine.hpp"

+#include "SamplerCore.hpp"

 

 namespace sw

 {

@@ -78,15 +79,15 @@
 		Int4 enableContinue;

 		Int4 enableLeave;

 

-		void sampleTexture(Vector4f &c, const Src &sampler, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool project = false, bool bias = false, bool gradients = false, bool lodProvided = false);

-		void sampleTexture(Vector4f &c, int sampler, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool project = false, bool bias = false, bool gradients = false, bool lodProvided = false);

+		void sampleTexture(Vector4f &c, const Src &sampler, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool project, SamplerMethod method);

+		void sampleTexture(Vector4f &c, int sampler, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool project, SamplerMethod method);

 

 		// Raster operations

 		void clampColor(Vector4f oC[RENDERTARGETS]);

 

 		Int4 enableMask(const Shader::Instruction *instruction);

 

-		Vector4f fetchRegisterF(const Src &src, unsigned int offset = 0);

+		Vector4f fetchRegister(const Src &src, unsigned int offset = 0);

 		Vector4f readConstant(const Src &src, unsigned int offset = 0);

 		RValue<Pointer<Byte>> uniformAddress(int bufferIndex, unsigned int index);

 		RValue<Pointer<Byte>> uniformAddress(int bufferIndex, unsigned int index, Int& offset);

@@ -103,8 +104,8 @@
 		void M4X3(Vector4f &dst, Vector4f &src0, const Src &src1);

 		void M4X4(Vector4f &dst, Vector4f &src0, const Src &src1);

 		void TEXLD(Vector4f &dst, Vector4f &src0, const Src &src1, bool project, bool bias);

-		void TEXLDD(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &src2, Vector4f &src3, bool project, bool bias);

-		void TEXLDL(Vector4f &dst, Vector4f &src0, const Src &src1, bool project, bool bias);

+		void TEXLDD(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &src2, Vector4f &src3, bool project);

+		void TEXLDL(Vector4f &dst, Vector4f &src0, const Src &src1, bool project);

 		void TEXSIZE(Vector4f &dst, Float4 &lod, const Src &src1);

 		void TEXKILL(Int cMask[4], Vector4f &src, unsigned char mask);

 		void TEXOFFSET(Vector4f &dst, Vector4f &src, const Src&, Vector4f &src2, Vector4f &src3, bool project, bool bias);

diff --git a/src/Shader/SamplerCore.cpp b/src/Shader/SamplerCore.cpp
index 82a6644..8128617 100644
--- a/src/Shader/SamplerCore.cpp
+++ b/src/Shader/SamplerCore.cpp
@@ -51,7 +51,12 @@
 	{
 	}
 
-	void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool bias, bool gradients, bool lodProvided, bool fixed12)
+	void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, SamplerMethod method)
+	{
+		sampleTexture(texture, c, u, v, w, q, dsx, dsy, method, true);
+	}
+
+	void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, SamplerMethod method, bool fixed12)
 	{
 		#if PERF_PROFILE
 			AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
@@ -101,16 +106,16 @@
 			{
 				if(state.textureType != TEXTURE_CUBE)
 				{
-					computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, q.x, dsx, dsy, bias, gradients, lodProvided);
+					computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, q.x, dsx, dsy, method);
 				}
 				else
 				{
-					computeLod(texture, lod, anisotropy, uDelta, vDelta, lodU, lodV, q.x, dsx, dsy, bias, gradients, lodProvided);
+					computeLod(texture, lod, anisotropy, uDelta, vDelta, lodU, lodV, q.x, dsx, dsy, method);
 				}
 			}
 			else
 			{
-				computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, bias, gradients, lodProvided);
+				computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, method);
 			}
 
 			if(state.textureType == TEXTURE_CUBE)
@@ -121,13 +126,13 @@
 
 			if(!hasFloatTexture())
 			{
-				sampleFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, lodProvided);
+				sampleFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, method);
 			}
 			else
 			{
 				Vector4f cf;
 
-				sampleFloatFilter(texture, cf, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, lodProvided);
+				sampleFloatFilter(texture, cf, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, method);
 
 				convertFixed12(c, cf);
 			}
@@ -287,7 +292,7 @@
 		}
 	}
 
-	void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool bias, bool gradients, bool lodProvided)
+	void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, SamplerMethod method)
 	{
 		#if PERF_PROFILE
 			AddAtomic(Pointer<Long>(&profiler.texOperations), 4);
@@ -331,16 +336,16 @@
 				{
 					if(state.textureType != TEXTURE_CUBE)
 					{
-						computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, q.x, dsx, dsy, bias, gradients, lodProvided);
+						computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, q.x, dsx, dsy, method);
 					}
 					else
 					{
-						computeLod(texture, lod, anisotropy, uDelta, vDelta, lodU, lodV, q.x, dsx, dsy, bias, gradients, lodProvided);
+						computeLod(texture, lod, anisotropy, uDelta, vDelta, lodU, lodV, q.x, dsx, dsy, method);
 					}
 				}
 				else
 				{
-					computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, bias, gradients, lodProvided);
+					computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, method);
 				}
 
 				if(state.textureType == TEXTURE_CUBE)
@@ -349,13 +354,13 @@
 					vvvv += Float4(0.5f);
 				}
 
-				sampleFloatFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, lodProvided);
+				sampleFloatFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, method);
 			}
 			else
 			{
 				Vector4s cs;
 
-				sampleTexture(texture, cs, u, v, w, q, dsx, dsy, bias, gradients, lodProvided, false);
+				sampleTexture(texture, cs, u, v, w, q, dsx, dsy, method, false);
 
 				for(int component = 0; component < textureComponentCount(); component++)
 				{
@@ -593,15 +598,15 @@
 		return uvw;
 	}
 
-	void SamplerCore::sampleFilter(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool lodProvided)
+	void SamplerCore::sampleFilter(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], SamplerMethod method)
 	{
-		sampleAniso(texture, c, u, v, w, lod, anisotropy, uDelta, vDelta, face, false, lodProvided);
+		sampleAniso(texture, c, u, v, w, lod, anisotropy, uDelta, vDelta, face, false, method);
 
 		if(state.mipmapFilter > MIPMAP_POINT)
 		{
 			Vector4s cc;
 
-			sampleAniso(texture, cc, u, v, w, lod, anisotropy, uDelta, vDelta, face, true, lodProvided);
+			sampleAniso(texture, cc, u, v, w, lod, anisotropy, uDelta, vDelta, face, true, method);
 
 			lod *= Float(1 << 16);
 
@@ -689,9 +694,9 @@
 		}
 	}
 
-	void SamplerCore::sampleAniso(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, bool lodProvided)
+	void SamplerCore::sampleAniso(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, SamplerMethod method)
 	{
-		if(state.textureFilter != FILTER_ANISOTROPIC || lodProvided)
+		if(state.textureFilter != FILTER_ANISOTROPIC || method == Lod)
 		{
 			sampleQuad(texture, c, u, v, w, lod, face, secondLOD);
 		}
@@ -1093,15 +1098,15 @@
 		}
 	}
 
-	void SamplerCore::sampleFloatFilter(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool lodProvided)
+	void SamplerCore::sampleFloatFilter(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], SamplerMethod method)
 	{
-		sampleFloatAniso(texture, c, u, v, w, lod, anisotropy, uDelta, vDelta, face, false, lodProvided);
+		sampleFloatAniso(texture, c, u, v, w, lod, anisotropy, uDelta, vDelta, face, false, method);
 
 		if(state.mipmapFilter > MIPMAP_POINT)
 		{
 			Vector4f cc;
 
-			sampleFloatAniso(texture, cc, u, v, w, lod, anisotropy, uDelta, vDelta, face, true, lodProvided);
+			sampleFloatAniso(texture, cc, u, v, w, lod, anisotropy, uDelta, vDelta, face, true, method);
 
 			Float4 lod4 = Float4(Frac(lod));
 
@@ -1168,9 +1173,9 @@
 		}
 	}
 
-	void SamplerCore::sampleFloatAniso(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, bool lodProvided)
+	void SamplerCore::sampleFloatAniso(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, SamplerMethod method)
 	{
-		if(state.textureFilter != FILTER_ANISOTROPIC || lodProvided)
+		if(state.textureFilter != FILTER_ANISOTROPIC || method == Lod)
 		{
 			sampleFloat(texture, c, u, v, w, lod, face, secondLOD);
 		}
@@ -1390,13 +1395,13 @@
 		}
 	}
 
-	void SamplerCore::computeLod(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &uuuu, Float4 &vvvv, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, bool bias, bool gradients, bool lodProvided)
+	void SamplerCore::computeLod(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &uuuu, Float4 &vvvv, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method)
 	{
-		if(!lodProvided)
+		if(method != Lod)
 		{
 			Float4 duvdxy;
 
-			if(!gradients)
+			if(method != Grad)
 			{
 				duvdxy = Float4(uuuu.yz, vvvv.yz) - Float4(uuuu.xx, vvvv.xx);
 			}
@@ -1440,7 +1445,7 @@
 			lod -= Float(0x3F800000);
 			lod *= As<Float>(Int(0x33800000));
 
-			if(bias)
+			if(method == Bias)
 			{
 				lod += lodBias;
 			}
@@ -1460,20 +1465,20 @@
 		lod = Min(lod, Float(MIPMAP_LEVELS - 2));   // Trilinear accesses lod+1
 	}
 
-	void SamplerCore::computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, bool bias, bool gradients, bool lodProvided)
+	void SamplerCore::computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method)
 	{
 		if(state.mipmapFilter == MIPMAP_NONE)
 		{
 		}
 		else   // Point and linear filter
 		{
-			if(!lodProvided)
+			if(method != Lod)
 			{
 				Float4 dudxy;
 				Float4 dvdxy;
 				Float4 dsdxy;
 
-				if(!gradients)
+				if(method != Grad)
 				{
 					dudxy = uuuu.ywyw - uuuu;
 					dvdxy = vvvv.ywyw - vvvv;
@@ -1513,7 +1518,7 @@
 				lod -= Float(0x3F800000);
 				lod *= As<Float>(Int(0x33800000));
 
-				if(bias)
+				if(method == Bias)
 				{
 					lod += lodBias;
 				}
diff --git a/src/Shader/SamplerCore.hpp b/src/Shader/SamplerCore.hpp
index 75d8f31..bb8324f 100644
--- a/src/Shader/SamplerCore.hpp
+++ b/src/Shader/SamplerCore.hpp
@@ -17,30 +17,40 @@
 

 namespace sw

 {

+	enum SamplerMethod

+	{

+		Implicit,

+		Bias,

+		Lod,

+		Grad,

+	};

+

 	class SamplerCore

 	{

 	public:

 		SamplerCore(Pointer<Byte> &r, const Sampler::State &state);

 

-		void sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool bias = false, bool gradients = false, bool lodProvided = false, bool fixed12 = true);

-		void sampleTexture(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool bias = false, bool gradients = false, bool lodProvided = false);

+		void sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, SamplerMethod method = Implicit);

+		void sampleTexture(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, SamplerMethod method = Implicit);

 

 	private:

+		void sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, SamplerMethod method, bool fixed12);

+

 		void border(Short4 &mask, Float4 &coordinates);

 		void border(Int4 &mask, Float4 &coordinates);

 		Short4 offsetSample(Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod);

-		void sampleFilter(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool lodProvided);

-		void sampleAniso(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, bool lodProvided);

+		void sampleFilter(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], SamplerMethod method);

+		void sampleAniso(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, SamplerMethod method);

 		void sampleQuad(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD);

 		void sampleQuad2D(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD);

 		void sample3D(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, bool secondLOD);

-		void sampleFloatFilter(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool lodProvided);

-		void sampleFloatAniso(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, bool lodProvided);

+		void sampleFloatFilter(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], SamplerMethod method);

+		void sampleFloatAniso(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, SamplerMethod method);

 		void sampleFloat(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD);

 		void sampleFloat2D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD);

 		void sampleFloat3D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, bool secondLOD);

-		void computeLod(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &u, Float4 &v, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, bool bias, bool gradients, bool lodProvided);

-		void computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, bool bias, bool gradients, bool lodProvided);

+		void computeLod(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &u, Float4 &v, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method);

+		void computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method);

 		void cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &lodU, Float4 &lodV, Float4 &x, Float4 &y, Float4 &z);

 		void computeIndices(Int index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, const Pointer<Byte> &mipmap);

 		void sampleTexel(Vector4s &c, Short4 &u, Short4 &v, Short4 &s, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4]);

diff --git a/src/Shader/VertexProgram.cpp b/src/Shader/VertexProgram.cpp
index dc829ef..e0ecd73 100644
--- a/src/Shader/VertexProgram.cpp
+++ b/src/Shader/VertexProgram.cpp
@@ -136,11 +136,11 @@
 			Vector4f s3;
 			Vector4f s4;
 
-			if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegisterF(src0);
-			if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegisterF(src1);
-			if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegisterF(src2);
-			if(src3.type != Shader::PARAMETER_VOID) s3 = fetchRegisterF(src3);
-			if(src4.type != Shader::PARAMETER_VOID) s4 = fetchRegisterF(src4);
+			if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegister(src0);
+			if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegister(src1);
+			if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegister(src2);
+			if(src3.type != Shader::PARAMETER_VOID) s3 = fetchRegister(src3);
+			if(src4.type != Shader::PARAMETER_VOID) s4 = fetchRegister(src4);
 
 			switch(opcode)
 			{
@@ -647,7 +647,7 @@
 		}
 	}
 
-	Vector4f VertexProgram::fetchRegisterF(const Src &src, unsigned int offset)
+	Vector4f VertexProgram::fetchRegister(const Src &src, unsigned int offset)
 	{
 		Vector4f reg;
 		unsigned int i = src.index + offset;
@@ -830,7 +830,7 @@
 			if(src.rel.deterministic)
 			{
 				Int a = relativeAddress(src, src.bufferIndex);
-			
+
 				c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i, a));
 
 				c.x = c.x.xxxx;
@@ -930,8 +930,8 @@
 
 	void VertexProgram::M3X2(Vector4f &dst, Vector4f &src0, Src &src1)
 	{
-		Vector4f row0 = fetchRegisterF(src1, 0);
-		Vector4f row1 = fetchRegisterF(src1, 1);
+		Vector4f row0 = fetchRegister(src1, 0);
+		Vector4f row1 = fetchRegister(src1, 1);
 
 		dst.x = dot3(src0, row0);
 		dst.y = dot3(src0, row1);
@@ -939,9 +939,9 @@
 
 	void VertexProgram::M3X3(Vector4f &dst, Vector4f &src0, Src &src1)
 	{
-		Vector4f row0 = fetchRegisterF(src1, 0);
-		Vector4f row1 = fetchRegisterF(src1, 1);
-		Vector4f row2 = fetchRegisterF(src1, 2);
+		Vector4f row0 = fetchRegister(src1, 0);
+		Vector4f row1 = fetchRegister(src1, 1);
+		Vector4f row2 = fetchRegister(src1, 2);
 
 		dst.x = dot3(src0, row0);
 		dst.y = dot3(src0, row1);
@@ -950,10 +950,10 @@
 
 	void VertexProgram::M3X4(Vector4f &dst, Vector4f &src0, Src &src1)
 	{
-		Vector4f row0 = fetchRegisterF(src1, 0);
-		Vector4f row1 = fetchRegisterF(src1, 1);
-		Vector4f row2 = fetchRegisterF(src1, 2);
-		Vector4f row3 = fetchRegisterF(src1, 3);
+		Vector4f row0 = fetchRegister(src1, 0);
+		Vector4f row1 = fetchRegister(src1, 1);
+		Vector4f row2 = fetchRegister(src1, 2);
+		Vector4f row3 = fetchRegister(src1, 3);
 
 		dst.x = dot3(src0, row0);
 		dst.y = dot3(src0, row1);
@@ -963,9 +963,9 @@
 
 	void VertexProgram::M4X3(Vector4f &dst, Vector4f &src0, Src &src1)
 	{
-		Vector4f row0 = fetchRegisterF(src1, 0);
-		Vector4f row1 = fetchRegisterF(src1, 1);
-		Vector4f row2 = fetchRegisterF(src1, 2);
+		Vector4f row0 = fetchRegister(src1, 0);
+		Vector4f row1 = fetchRegister(src1, 1);
+		Vector4f row2 = fetchRegister(src1, 2);
 
 		dst.x = dot4(src0, row0);
 		dst.y = dot4(src0, row1);
@@ -974,10 +974,10 @@
 
 	void VertexProgram::M4X4(Vector4f &dst, Vector4f &src0, Src &src1)
 	{
-		Vector4f row0 = fetchRegisterF(src1, 0);
-		Vector4f row1 = fetchRegisterF(src1, 1);
-		Vector4f row2 = fetchRegisterF(src1, 2);
-		Vector4f row3 = fetchRegisterF(src1, 3);
+		Vector4f row0 = fetchRegister(src1, 0);
+		Vector4f row1 = fetchRegister(src1, 1);
+		Vector4f row2 = fetchRegister(src1, 2);
+		Vector4f row3 = fetchRegister(src1, 3);
 
 		dst.x = dot4(src0, row0);
 		dst.y = dot4(src0, row1);
@@ -1259,7 +1259,7 @@
 		}
 		else
 		{
-			Int4 condition = As<Int4>(fetchRegisterF(src).x);
+			Int4 condition = As<Int4>(fetchRegister(src).x);
 			IF(condition);
 		}
 	}
@@ -1429,7 +1429,7 @@
 		Nucleus::setInsertBlock(testBlock);
 		enableContinue = restoreContinue;
 
-		const Vector4f &src = fetchRegisterF(temporaryRegister);
+		const Vector4f &src = fetchRegister(temporaryRegister);
 		Int4 condition = As<Int4>(src.x);
 		condition &= enableStack[enableIndex - 1];
 		enableStack[enableIndex] = condition;
@@ -1494,25 +1494,13 @@
 
 	void VertexProgram::TEXLDL(Vector4f &dst, Vector4f &src0, const Src &src1)
 	{
-		Vector4f tmp;
-		sampleTexture(tmp, src1, src0.x, src0.y, src0.z, src0.w);
-
-		dst.x = tmp[(src1.swizzle >> 0) & 0x3];
-		dst.y = tmp[(src1.swizzle >> 2) & 0x3];
-		dst.z = tmp[(src1.swizzle >> 4) & 0x3];
-		dst.w = tmp[(src1.swizzle >> 6) & 0x3];
+		sampleTexture(dst, src1, src0.x, src0.y, src0.z, src0.w, Lod);
 	}
 
 	void VertexProgram::TEX(Vector4f &dst, Vector4f &src0, const Src &src1)
 	{
-		Float4 lod = Float4(0.0f);
-		Vector4f tmp;
-		sampleTexture(tmp, src1, src0.x, src0.y, src0.z, lod);
-
-		dst.x = tmp[(src1.swizzle >> 0) & 0x3];
-		dst.y = tmp[(src1.swizzle >> 2) & 0x3];
-		dst.z = tmp[(src1.swizzle >> 4) & 0x3];
-		dst.w = tmp[(src1.swizzle >> 6) & 0x3];
+		Float4 lod0 = Float4(0.0f);
+		sampleTexture(dst, src1, src0.x, src0.y, src0.z, lod0, Lod);
 	}
 
 	void VertexProgram::TEXOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3)
@@ -1557,29 +1545,36 @@
 		}
 	}
 
-	void VertexProgram::sampleTexture(Vector4f &c, const Src &s, Float4 &u, Float4 &v, Float4 &w, Float4 &q)
+	void VertexProgram::sampleTexture(Vector4f &c, const Src &s, Float4 &u, Float4 &v, Float4 &w, Float4 &q, SamplerMethod method)
 	{
+		Vector4f tmp;
+
 		if(s.type == Shader::PARAMETER_SAMPLER && s.rel.type == Shader::PARAMETER_VOID)
 		{
-			Pointer<Byte> texture = data + OFFSET(DrawData,mipmap[16]) + s.index * sizeof(Texture);
-			sampler[s.index]->sampleTexture(texture, c, u, v, w, q, a0, a0, false, false, true);
+			Pointer<Byte> texture = data + OFFSET(DrawData,mipmap[TEXTURE_IMAGE_UNITS]) + s.index * sizeof(Texture);
+			sampler[s.index]->sampleTexture(texture, tmp, u, v, w, q, a0, a0, method);
 		}
 		else
 		{
-			Int index = As<Int>(Float(fetchRegisterF(s).x.x));
+			Int index = As<Int>(Float(fetchRegister(s).x.x));
 
-			for(int i = 0; i < 16; i++)
+			for(int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
 			{
 				if(shader->usesSampler(i))
 				{
 					If(index == i)
 					{
-						Pointer<Byte> texture = data + OFFSET(DrawData,mipmap[16]) + i * sizeof(Texture);
-						sampler[i]->sampleTexture(texture, c, u, v, w, q, a0, a0, false, false, true);
+						Pointer<Byte> texture = data + OFFSET(DrawData,mipmap[TEXTURE_IMAGE_UNITS]) + i * sizeof(Texture);
+						sampler[i]->sampleTexture(texture, tmp, u, v, w, q, a0, a0, method);
 						// FIXME: When the sampler states are the same, we could use one sampler and just index the texture
 					}
 				}
 			}
 		}
+
+		c.x = tmp[(s.swizzle >> 0) & 0x3];
+		c.y = tmp[(s.swizzle >> 2) & 0x3];
+		c.z = tmp[(s.swizzle >> 4) & 0x3];
+		c.w = tmp[(s.swizzle >> 6) & 0x3];
 	}
 }
diff --git a/src/Shader/VertexProgram.hpp b/src/Shader/VertexProgram.hpp
index 1819d91..98e09cd 100644
--- a/src/Shader/VertexProgram.hpp
+++ b/src/Shader/VertexProgram.hpp
@@ -14,6 +14,7 @@
 
 #include "VertexRoutine.hpp"
 #include "ShaderCore.hpp"
+#include "SamplerCore.hpp"
 
 #include "Stream.hpp"
 #include "Types.hpp"
@@ -22,7 +23,6 @@
 {
 	struct Stream;
 	class VertexShader;
-	class SamplerCore;
 
 	class VertexProgram : public VertexRoutine, public ShaderCore
 	{
@@ -63,7 +63,7 @@
 		void program();
 		void passThrough();
 
-		Vector4f fetchRegisterF(const Src &src, unsigned int offset = 0);
+		Vector4f fetchRegister(const Src &src, unsigned int offset = 0);
 		Vector4f readConstant(const Src &src, unsigned int offset = 0);
 		RValue<Pointer<Byte>> uniformAddress(int bufferIndex, unsigned int index);
 		RValue<Pointer<Byte>> uniformAddress(int bufferIndex, unsigned int index, Int& offset);
@@ -111,7 +111,7 @@
 		void TEXGRAD(Vector4f &dst, Vector4f &src, const Src&, Vector4f &src2, Vector4f &src3, Vector4f &src4);
 		void TEXSIZE(Vector4f &dst, Float4 &lod, const Src&);
 
-		void sampleTexture(Vector4f &c, const Src &s, Float4 &u, Float4 &v, Float4 &w, Float4 &q);
+		void sampleTexture(Vector4f &c, const Src &s, Float4 &u, Float4 &v, Float4 &w, Float4 &q, SamplerMethod method);
 
 		SamplerCore *sampler[VERTEX_TEXTURE_IMAGE_UNITS];