Pass down the texture compare state.

Depth format textures can have a comparison operation performed after
their texels have been sampled.

Change-Id: I49f6bb7fab9765265761144ee8b6b62439beb5a3
Reviewed-on: https://swiftshader-review.googlesource.com/5870
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 29c488c..9eefb3f 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -1686,16 +1686,16 @@
 
 	switch(pname)
 	{
-	case GL_TEXTURE_MIN_FILTER:    samplerObject->setMinFilter(static_cast<GLenum>(param));       break;
-	case GL_TEXTURE_MAG_FILTER:    samplerObject->setMagFilter(static_cast<GLenum>(param));       break;
-	case GL_TEXTURE_WRAP_S:        samplerObject->setWrapS(static_cast<GLenum>(param));           break;
-	case GL_TEXTURE_WRAP_T:        samplerObject->setWrapT(static_cast<GLenum>(param));           break;
-	case GL_TEXTURE_WRAP_R:        samplerObject->setWrapR(static_cast<GLenum>(param));           break;
-	case GL_TEXTURE_MIN_LOD:       samplerObject->setMinLod(static_cast<GLfloat>(param));         break;
-	case GL_TEXTURE_MAX_LOD:       samplerObject->setMaxLod(static_cast<GLfloat>(param));         break;
-	case GL_TEXTURE_COMPARE_MODE:  samplerObject->setComparisonMode(static_cast<GLenum>(param));  break;
-	case GL_TEXTURE_COMPARE_FUNC:  samplerObject->setComparisonFunc(static_cast<GLenum>(param));  break;
-	default:                       UNREACHABLE(pname); break;
+	case GL_TEXTURE_MIN_FILTER:   samplerObject->setMinFilter(static_cast<GLenum>(param));   break;
+	case GL_TEXTURE_MAG_FILTER:   samplerObject->setMagFilter(static_cast<GLenum>(param));   break;
+	case GL_TEXTURE_WRAP_S:       samplerObject->setWrapS(static_cast<GLenum>(param));       break;
+	case GL_TEXTURE_WRAP_T:       samplerObject->setWrapT(static_cast<GLenum>(param));       break;
+	case GL_TEXTURE_WRAP_R:       samplerObject->setWrapR(static_cast<GLenum>(param));       break;
+	case GL_TEXTURE_MIN_LOD:      samplerObject->setMinLod(static_cast<GLfloat>(param));     break;
+	case GL_TEXTURE_MAX_LOD:      samplerObject->setMaxLod(static_cast<GLfloat>(param));     break;
+	case GL_TEXTURE_COMPARE_MODE: samplerObject->setCompareMode(static_cast<GLenum>(param)); break;
+	case GL_TEXTURE_COMPARE_FUNC: samplerObject->setCompareFunc(static_cast<GLenum>(param)); break;
+	default:                      UNREACHABLE(pname); break;
 	}
 }
 
@@ -1708,16 +1708,16 @@
 
 	switch(pname)
 	{
-	case GL_TEXTURE_MIN_FILTER:    samplerObject->setMinFilter(static_cast<GLenum>(roundf(param)));       break;
-	case GL_TEXTURE_MAG_FILTER:    samplerObject->setMagFilter(static_cast<GLenum>(roundf(param)));       break;
-	case GL_TEXTURE_WRAP_S:        samplerObject->setWrapS(static_cast<GLenum>(roundf(param)));           break;
-	case GL_TEXTURE_WRAP_T:        samplerObject->setWrapT(static_cast<GLenum>(roundf(param)));           break;
-	case GL_TEXTURE_WRAP_R:        samplerObject->setWrapR(static_cast<GLenum>(roundf(param)));           break;
-	case GL_TEXTURE_MIN_LOD:       samplerObject->setMinLod(param);                                       break;
-	case GL_TEXTURE_MAX_LOD:       samplerObject->setMaxLod(param);                                       break;
-	case GL_TEXTURE_COMPARE_MODE:  samplerObject->setComparisonMode(static_cast<GLenum>(roundf(param)));  break;
-	case GL_TEXTURE_COMPARE_FUNC:  samplerObject->setComparisonFunc(static_cast<GLenum>(roundf(param)));  break;
-	default:                       UNREACHABLE(pname); break;
+	case GL_TEXTURE_MIN_FILTER:   samplerObject->setMinFilter(static_cast<GLenum>(roundf(param)));   break;
+	case GL_TEXTURE_MAG_FILTER:   samplerObject->setMagFilter(static_cast<GLenum>(roundf(param)));   break;
+	case GL_TEXTURE_WRAP_S:       samplerObject->setWrapS(static_cast<GLenum>(roundf(param)));       break;
+	case GL_TEXTURE_WRAP_T:       samplerObject->setWrapT(static_cast<GLenum>(roundf(param)));       break;
+	case GL_TEXTURE_WRAP_R:       samplerObject->setWrapR(static_cast<GLenum>(roundf(param)));       break;
+	case GL_TEXTURE_MIN_LOD:      samplerObject->setMinLod(param);                                   break;
+	case GL_TEXTURE_MAX_LOD:      samplerObject->setMaxLod(param);                                   break;
+	case GL_TEXTURE_COMPARE_MODE: samplerObject->setCompareMode(static_cast<GLenum>(roundf(param))); break;
+	case GL_TEXTURE_COMPARE_FUNC: samplerObject->setCompareFunc(static_cast<GLenum>(roundf(param))); break;
+	default:                      UNREACHABLE(pname); break;
 	}
 }
 
@@ -1730,16 +1730,16 @@
 
 	switch(pname)
 	{
-	case GL_TEXTURE_MIN_FILTER:    return static_cast<GLint>(samplerObject->getMinFilter());
-	case GL_TEXTURE_MAG_FILTER:    return static_cast<GLint>(samplerObject->getMagFilter());
-	case GL_TEXTURE_WRAP_S:        return static_cast<GLint>(samplerObject->getWrapS());
-	case GL_TEXTURE_WRAP_T:        return static_cast<GLint>(samplerObject->getWrapT());
-	case GL_TEXTURE_WRAP_R:        return static_cast<GLint>(samplerObject->getWrapR());
-	case GL_TEXTURE_MIN_LOD:       return static_cast<GLint>(roundf(samplerObject->getMinLod()));
-	case GL_TEXTURE_MAX_LOD:       return static_cast<GLint>(roundf(samplerObject->getMaxLod()));
-	case GL_TEXTURE_COMPARE_MODE:  return static_cast<GLint>(samplerObject->getComparisonMode());
-	case GL_TEXTURE_COMPARE_FUNC:  return static_cast<GLint>(samplerObject->getComparisonFunc());
-	default:                       UNREACHABLE(pname); return 0;
+	case GL_TEXTURE_MIN_FILTER:   return static_cast<GLint>(samplerObject->getMinFilter());
+	case GL_TEXTURE_MAG_FILTER:   return static_cast<GLint>(samplerObject->getMagFilter());
+	case GL_TEXTURE_WRAP_S:       return static_cast<GLint>(samplerObject->getWrapS());
+	case GL_TEXTURE_WRAP_T:       return static_cast<GLint>(samplerObject->getWrapT());
+	case GL_TEXTURE_WRAP_R:       return static_cast<GLint>(samplerObject->getWrapR());
+	case GL_TEXTURE_MIN_LOD:      return static_cast<GLint>(roundf(samplerObject->getMinLod()));
+	case GL_TEXTURE_MAX_LOD:      return static_cast<GLint>(roundf(samplerObject->getMaxLod()));
+	case GL_TEXTURE_COMPARE_MODE: return static_cast<GLint>(samplerObject->getCompareMode());
+	case GL_TEXTURE_COMPARE_FUNC: return static_cast<GLint>(samplerObject->getCompareFunc());
+	default:                      UNREACHABLE(pname); return 0;
 	}
 }
 
@@ -1752,16 +1752,16 @@
 
 	switch(pname)
 	{
-	case GL_TEXTURE_MIN_FILTER:    return static_cast<GLfloat>(samplerObject->getMinFilter());
-	case GL_TEXTURE_MAG_FILTER:    return static_cast<GLfloat>(samplerObject->getMagFilter());
-	case GL_TEXTURE_WRAP_S:        return static_cast<GLfloat>(samplerObject->getWrapS());
-	case GL_TEXTURE_WRAP_T:        return static_cast<GLfloat>(samplerObject->getWrapT());
-	case GL_TEXTURE_WRAP_R:        return static_cast<GLfloat>(samplerObject->getWrapR());
-	case GL_TEXTURE_MIN_LOD:       return samplerObject->getMinLod();
-	case GL_TEXTURE_MAX_LOD:       return samplerObject->getMaxLod();
-	case GL_TEXTURE_COMPARE_MODE:  return static_cast<GLfloat>(samplerObject->getComparisonMode());
-	case GL_TEXTURE_COMPARE_FUNC:  return static_cast<GLfloat>(samplerObject->getComparisonFunc());
-	default:                       UNREACHABLE(pname); return 0;
+	case GL_TEXTURE_MIN_FILTER:   return static_cast<GLfloat>(samplerObject->getMinFilter());
+	case GL_TEXTURE_MAG_FILTER:   return static_cast<GLfloat>(samplerObject->getMagFilter());
+	case GL_TEXTURE_WRAP_S:       return static_cast<GLfloat>(samplerObject->getWrapS());
+	case GL_TEXTURE_WRAP_T:       return static_cast<GLfloat>(samplerObject->getWrapT());
+	case GL_TEXTURE_WRAP_R:       return static_cast<GLfloat>(samplerObject->getWrapR());
+	case GL_TEXTURE_MIN_LOD:      return samplerObject->getMinLod();
+	case GL_TEXTURE_MAX_LOD:      return samplerObject->getMaxLod();
+	case GL_TEXTURE_COMPARE_MODE: return static_cast<GLfloat>(samplerObject->getCompareMode());
+	case GL_TEXTURE_COMPARE_FUNC: return static_cast<GLfloat>(samplerObject->getCompareFunc());
+	default:                      UNREACHABLE(pname); return 0;
 	}
 }
 
@@ -3027,7 +3027,7 @@
 
 			if(texture->isSamplerComplete())
 			{
-				GLenum wrapS, wrapT, wrapR, minFilter, magFilter;
+				GLenum wrapS, wrapT, wrapR, minFilter, magFilter, compFunc, compMode;
 				GLfloat minLOD, maxLOD;
 
 				Sampler *samplerObject = mState.sampler[textureUnit];
@@ -3040,6 +3040,8 @@
 					magFilter = samplerObject->getMagFilter();
 					minLOD = samplerObject->getMinLod();
 					maxLOD = samplerObject->getMaxLod();
+					compFunc = samplerObject->getCompareFunc();
+					compMode = samplerObject->getCompareMode();
 				}
 				else
 				{
@@ -3050,9 +3052,11 @@
 					magFilter = texture->getMagFilter();
 					minLOD = texture->getMinLOD();
 					maxLOD = texture->getMaxLOD();
+					compFunc = texture->getCompareFunc();
+					compMode = texture->getCompareMode();
 				}
-				GLfloat maxAnisotropy = texture->getMaxAnisotropy();
 
+				GLfloat maxAnisotropy = texture->getMaxAnisotropy();
 				GLint baseLevel = texture->getBaseLevel();
 				GLint maxLevel = texture->getMaxLevel();
 				GLenum swizzleR = texture->getSwizzleR();
@@ -3063,6 +3067,7 @@
 				device->setAddressingModeU(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapS));
 				device->setAddressingModeV(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapT));
 				device->setAddressingModeW(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapR));
+				device->setCompareFunc(samplerType, samplerIndex, es2sw::ConvertCompareFunc(compFunc, compMode));
 				device->setSwizzleR(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleR));
 				device->setSwizzleG(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleG));
 				device->setSwizzleB(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleB));
@@ -3071,7 +3076,6 @@
 				device->setMaxLod(samplerType, samplerIndex, maxLOD);
 				device->setBaseLevel(samplerType, samplerIndex, baseLevel);
 				device->setMaxLevel(samplerType, samplerIndex, maxLevel);
-
 				device->setTextureFilter(samplerType, samplerIndex, es2sw::ConvertTextureFilter(minFilter, magFilter, maxAnisotropy));
 				device->setMipmapFilter(samplerType, samplerIndex, es2sw::ConvertMipMapFilter(minFilter));
 				device->setMaxAnisotropy(samplerType, samplerIndex, maxAnisotropy);
diff --git a/src/OpenGL/libGLESv2/Sampler.h b/src/OpenGL/libGLESv2/Sampler.h
index 12ed6da..0dbf8c9 100644
--- a/src/OpenGL/libGLESv2/Sampler.h
+++ b/src/OpenGL/libGLESv2/Sampler.h
@@ -50,8 +50,8 @@
 	void setWrapR(GLenum wrapR) { mWrapModeR = wrapR; }
 	void setMinLod(GLfloat minLod) { mMinLod = minLod; }
 	void setMaxLod(GLfloat maxLod) { mMaxLod = maxLod; }
-	void setComparisonMode(GLenum comparisonMode) { mCompareMode = comparisonMode; }
-	void setComparisonFunc(GLenum comparisonFunc) { mCompareFunc = comparisonFunc; }
+	void setCompareMode(GLenum compareMode) { mCompareMode = compareMode; }
+	void setCompareFunc(GLenum compareFunc) { mCompareFunc = compareFunc; }
 
 	GLenum getMinFilter() const { return mMinFilter; }
 	GLenum getMagFilter() const { return mMagFilter; }
@@ -60,8 +60,8 @@
 	GLenum getWrapR() const { return mWrapModeR; }
 	GLfloat getMinLod() const { return mMinLod; }
 	GLfloat getMaxLod() const { return mMaxLod; }
-	GLenum getComparisonMode() const { return mCompareMode; }
-	GLenum getComparisonFunc() const { return mCompareFunc; }
+	GLenum getCompareMode() const { return mCompareMode; }
+	GLenum getCompareFunc() const { return mCompareFunc; }
 
 private:
 	GLenum mMinFilter;
diff --git a/src/OpenGL/libGLESv2/utilities.cpp b/src/OpenGL/libGLESv2/utilities.cpp
index 8282975..1415b5e 100644
--- a/src/OpenGL/libGLESv2/utilities.cpp
+++ b/src/OpenGL/libGLESv2/utilities.cpp
@@ -1374,6 +1374,32 @@
 		return sw::ADDRESSING_WRAP;
 	}
 
+	sw::CompareFunc ConvertCompareFunc(GLenum compareFunc, GLenum compareMode)
+	{
+		if(compareMode == GL_COMPARE_REF_TO_TEXTURE)
+		{
+			switch(compareFunc)
+			{
+			case GL_LEQUAL:   return sw::COMPARE_LESSEQUAL;
+			case GL_GEQUAL:   return sw::COMPARE_GREATEREQUAL;
+			case GL_LESS:     return sw::COMPARE_LESS;
+			case GL_GREATER:  return sw::COMPARE_GREATER;
+			case GL_EQUAL:    return sw::COMPARE_EQUAL;
+			case GL_NOTEQUAL: return sw::COMPARE_NOTEQUAL;
+			case GL_ALWAYS:   return sw::COMPARE_ALWAYS;
+			case GL_NEVER:    return sw::COMPARE_NEVER;
+			default: UNREACHABLE(compareFunc);
+			}
+		}
+		else if(compareMode == GL_NONE)
+		{
+			return sw::COMPARE_BYPASS;
+		}
+		else UNREACHABLE(compareMode);
+
+		return sw::COMPARE_BYPASS;
+	};
+
 	sw::SwizzleType ConvertSwizzleType(GLenum swizzleType)
 	{
 		switch(swizzleType)
diff --git a/src/OpenGL/libGLESv2/utilities.h b/src/OpenGL/libGLESv2/utilities.h
index 53deb98..93690c7 100644
--- a/src/OpenGL/libGLESv2/utilities.h
+++ b/src/OpenGL/libGLESv2/utilities.h
@@ -74,6 +74,7 @@
 	sw::LogicalOperation ConvertLogicalOperation(GLenum logicalOperation);
 	sw::StencilOperation ConvertStencilOp(GLenum stencilOp);
 	sw::AddressingMode ConvertTextureWrap(GLenum wrap);
+	sw::CompareFunc ConvertCompareFunc(GLenum compareFunc, GLenum compareMode);
 	sw::SwizzleType ConvertSwizzleType(GLenum swizzleType);
 	sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace);
 	unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha);
diff --git a/src/Renderer/PixelProcessor.cpp b/src/Renderer/PixelProcessor.cpp
index 356aa47..003cfb3 100644
--- a/src/Renderer/PixelProcessor.cpp
+++ b/src/Renderer/PixelProcessor.cpp
@@ -489,6 +489,15 @@
 		else ASSERT(false);
 	}
 
+	void PixelProcessor::setCompareFunc(unsigned int sampler, CompareFunc compFunc)
+	{
+		if(sampler < TEXTURE_IMAGE_UNITS)
+		{
+			context->sampler[sampler].setCompareFunc(compFunc);
+		}
+		else ASSERT(false);
+	}
+
 	void PixelProcessor::setBaseLevel(unsigned int sampler, int baseLevel)
 	{
 		if(sampler < TEXTURE_IMAGE_UNITS)
diff --git a/src/Renderer/PixelProcessor.hpp b/src/Renderer/PixelProcessor.hpp
index d3b0602..57bbb19 100644
--- a/src/Renderer/PixelProcessor.hpp
+++ b/src/Renderer/PixelProcessor.hpp
@@ -237,6 +237,7 @@
 		void setSwizzleG(unsigned int sampler, SwizzleType swizzleG);
 		void setSwizzleB(unsigned int sampler, SwizzleType swizzleB);
 		void setSwizzleA(unsigned int sampler, SwizzleType swizzleA);
+		void setCompareFunc(unsigned int sampler, CompareFunc compare);
 		void setBaseLevel(unsigned int sampler, int baseLevel);
 		void setMaxLevel(unsigned int sampler, int maxLevel);
 		void setMinLod(unsigned int sampler, float minLod);
diff --git a/src/Renderer/Renderer.cpp b/src/Renderer/Renderer.cpp
index b7c423f..43e01bc 100644
--- a/src/Renderer/Renderer.cpp
+++ b/src/Renderer/Renderer.cpp
@@ -420,7 +420,7 @@
 				{
 					for(int sampler = 0; sampler < VERTEX_TEXTURE_IMAGE_UNITS; sampler++)
 					{
-						if(vertexState.samplerState[sampler].textureType != TEXTURE_NULL)
+						if(vertexState.sampler[sampler].textureType != TEXTURE_NULL)
 						{
 							draw->texture[TEXTURE_IMAGE_UNITS + sampler] = context->texture[TEXTURE_IMAGE_UNITS + sampler];
 							draw->texture[TEXTURE_IMAGE_UNITS + sampler]->lock(PUBLIC, PRIVATE);
@@ -2388,6 +2388,18 @@
 		}
 	}
 
+	void Renderer::setCompareFunc(SamplerType type, int sampler, CompareFunc compFunc)
+	{
+		if(type == SAMPLER_PIXEL)
+		{
+			PixelProcessor::setCompareFunc(sampler, compFunc);
+		}
+		else
+		{
+			VertexProcessor::setCompareFunc(sampler, compFunc);
+		}
+	}
+
 	void Renderer::setBaseLevel(SamplerType type, int sampler, int baseLevel)
 	{
 		if(type == SAMPLER_PIXEL)
diff --git a/src/Renderer/Renderer.hpp b/src/Renderer/Renderer.hpp
index ca2140a..108f84b 100644
--- a/src/Renderer/Renderer.hpp
+++ b/src/Renderer/Renderer.hpp
@@ -348,6 +348,7 @@
 		void setSwizzleG(SamplerType type, int sampler, SwizzleType swizzleG);
 		void setSwizzleB(SamplerType type, int sampler, SwizzleType swizzleB);
 		void setSwizzleA(SamplerType type, int sampler, SwizzleType swizzleA);
+		void setCompareFunc(SamplerType type, int sampler, CompareFunc compare);
 		void setBaseLevel(SamplerType type, int sampler, int baseLevel);
 		void setMaxLevel(SamplerType type, int sampler, int maxLevel);
 		void setMinLod(SamplerType type, int sampler, float minLod);
diff --git a/src/Renderer/Sampler.cpp b/src/Renderer/Sampler.cpp
index 123a1c9..5bf11c8 100644
--- a/src/Renderer/Sampler.cpp
+++ b/src/Renderer/Sampler.cpp
@@ -67,6 +67,8 @@
 		swizzleB = SWIZZLE_BLUE;
 		swizzleA = SWIZZLE_ALPHA;
 
+		compare = COMPARE_BYPASS;
+
 		texture.LOD = 0.0f;
 		exp2LOD = 1.0f;
 
@@ -99,6 +101,7 @@
 			state.swizzleB = swizzleB;
 			state.swizzleA = swizzleA;
 			state.highPrecisionFiltering = highPrecisionFiltering;
+			state.compare = getCompareFunc();
 
 			#if PERF_PROFILE
 				state.compressedFormat = Surface::isCompressed(externalTextureFormat);
@@ -332,6 +335,11 @@
 		this->swizzleA = swizzleA;
 	}
 
+	void Sampler::setCompareFunc(CompareFunc compare)
+	{
+		this->compare = compare;
+	}
+
 	void Sampler::setBaseLevel(int baseLevel)
 	{
 		texture.baseLevel = baseLevel;
@@ -478,4 +486,19 @@
 
 		return addressingModeW;
 	}
+
+	CompareFunc Sampler::getCompareFunc() const
+	{
+		if(getTextureFilter() == FILTER_GATHER)
+		{
+			return COMPARE_BYPASS;
+		}
+
+		if(internalTextureFormat == FORMAT_D32FS8_SHADOW)
+		{
+			return COMPARE_LESSEQUAL;
+		}
+
+		return compare;
+	}
 }
diff --git a/src/Renderer/Sampler.hpp b/src/Renderer/Sampler.hpp
index 6fae602..ad2145c 100644
--- a/src/Renderer/Sampler.hpp
+++ b/src/Renderer/Sampler.hpp
@@ -110,6 +110,21 @@
 		ADDRESSING_LAST = ADDRESSING_TEXELFETCH
 	};
 
+	enum CompareFunc ENUM_UNDERLYING_TYPE_UNSIGNED_INT
+	{
+		COMPARE_BYPASS,
+		COMPARE_LESSEQUAL,
+		COMPARE_GREATEREQUAL,
+		COMPARE_LESS,
+		COMPARE_GREATER,
+		COMPARE_EQUAL,
+		COMPARE_NOTEQUAL,
+		COMPARE_ALWAYS,
+		COMPARE_NEVER,
+
+		COMPARE_LAST = COMPARE_NEVER
+	};
+
 	enum SwizzleType ENUM_UNDERLYING_TYPE_UNSIGNED_INT
 	{
 		SWIZZLE_RED,
@@ -142,6 +157,7 @@
 			SwizzleType swizzleB           : BITS(SWIZZLE_LAST);
 			SwizzleType swizzleA           : BITS(SWIZZLE_LAST);
 			bool highPrecisionFiltering    : 1;
+			CompareFunc compare            : BITS(COMPARE_LAST);
 
 			#if PERF_PROFILE
 			bool compressedFormat          : 1;
@@ -170,6 +186,7 @@
 		void setSwizzleG(SwizzleType swizzleG);
 		void setSwizzleB(SwizzleType swizzleB);
 		void setSwizzleA(SwizzleType swizzleA);
+		void setCompareFunc(CompareFunc compare);
 		void setBaseLevel(int baseLevel);
 		void setMaxLevel(int maxLevel);
 		void setMinLod(float minLod);
@@ -193,6 +210,7 @@
 		AddressingMode getAddressingModeU() const;
 		AddressingMode getAddressingModeV() const;
 		AddressingMode getAddressingModeW() const;
+		CompareFunc getCompareFunc() const;
 
 		Format externalTextureFormat;
 		Format internalTextureFormat;
@@ -211,6 +229,8 @@
 		SwizzleType swizzleG;
 		SwizzleType swizzleB;
 		SwizzleType swizzleA;
+		CompareFunc compare;
+
 		Texture texture;
 		float exp2LOD;
 
diff --git a/src/Renderer/VertexProcessor.cpp b/src/Renderer/VertexProcessor.cpp
index 2fa6caa..3d364ac 100644
--- a/src/Renderer/VertexProcessor.cpp
+++ b/src/Renderer/VertexProcessor.cpp
@@ -647,6 +647,15 @@
 		else ASSERT(false);
 	}
 
+	void VertexProcessor::setCompareFunc(unsigned int sampler, CompareFunc compFunc)
+	{
+		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
+		{
+			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setCompareFunc(compFunc);
+		}
+		else ASSERT(false);
+	}
+
 	void VertexProcessor::setBaseLevel(unsigned int sampler, int baseLevel)
 	{
 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
@@ -986,7 +995,7 @@
 			{
 				if(context->vertexShader->usesSampler(i))
 				{
-					state.samplerState[i] = context->sampler[TEXTURE_IMAGE_UNITS + i].samplerState();
+					state.sampler[i] = context->sampler[TEXTURE_IMAGE_UNITS + i].samplerState();
 				}
 			}
 		}
diff --git a/src/Renderer/VertexProcessor.hpp b/src/Renderer/VertexProcessor.hpp
index 3552f84..deac83d 100644
--- a/src/Renderer/VertexProcessor.hpp
+++ b/src/Renderer/VertexProcessor.hpp
@@ -91,7 +91,7 @@
 
 			TextureState textureState[8];
 
-			Sampler::State samplerState[VERTEX_TEXTURE_IMAGE_UNITS];
+			Sampler::State sampler[VERTEX_TEXTURE_IMAGE_UNITS];
 
 			struct Input
 			{
@@ -263,6 +263,7 @@
 		void setSwizzleG(unsigned int sampler, SwizzleType swizzleG);
 		void setSwizzleB(unsigned int sampler, SwizzleType swizzleB);
 		void setSwizzleA(unsigned int sampler, SwizzleType swizzleA);
+		void setCompareFunc(unsigned int sampler, CompareFunc compare);
 		void setBaseLevel(unsigned int sampler, int baseLevel);
 		void setMaxLevel(unsigned int sampler, int maxLevel);
 		void setMinLod(unsigned int sampler, float minLod);
diff --git a/src/Shader/VertexProgram.cpp b/src/Shader/VertexProgram.cpp
index 9a8495f..5197363 100644
--- a/src/Shader/VertexProgram.cpp
+++ b/src/Shader/VertexProgram.cpp
@@ -68,7 +68,7 @@
 	{
 		for(int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
 		{
-			sampler[i] = new SamplerCore(constants, state.samplerState[i]);
+			sampler[i] = new SamplerCore(constants, state.sampler[i]);
 		}
 
 		if(!state.preTransformed)