/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Texture lookup simulator that is capable of verifying generic
 *		  lookup results based on accuracy parameters.
 *//*--------------------------------------------------------------------*/

#include "tcuTexLookupVerifier.hpp"
#include "tcuTexVerifierUtil.hpp"
#include "tcuVectorUtil.hpp"
#include "tcuTextureUtil.hpp"
#include "deMath.h"

namespace tcu
{

using namespace TexVerifierUtil;

// Generic utilities

#if defined(DE_DEBUG)
static bool isSamplerSupported (const Sampler& sampler)
{
	return sampler.compare == Sampler::COMPAREMODE_NONE &&
		   isWrapModeSupported(sampler.wrapS)			&&
		   isWrapModeSupported(sampler.wrapT)			&&
		   isWrapModeSupported(sampler.wrapR);
}
#endif // DE_DEBUG

// Color read & compare utilities

static inline bool coordsInBounds (const ConstPixelBufferAccess& access, int x, int y, int z)
{
	return de::inBounds(x, 0, access.getWidth()) && de::inBounds(y, 0, access.getHeight()) && de::inBounds(z, 0, access.getDepth());
}

template<typename ScalarType>
inline Vector<ScalarType, 4> lookup (const ConstPixelBufferAccess& access, const Sampler& sampler, int i, int j, int k)
{
	if (coordsInBounds(access, i, j, k))
		return access.getPixelT<ScalarType>(i, j, k);
	else
		return sampler.borderColor.cast<ScalarType>();
}

template<>
inline Vector<float, 4> lookup (const ConstPixelBufferAccess& access, const Sampler& sampler, int i, int j, int k)
{
	// Specialization for float lookups: sRGB conversion is performed as specified in format.
	if (coordsInBounds(access, i, j, k))
	{
		const Vec4 p = access.getPixel(i, j, k);
		return isSRGB(access.getFormat()) ? sRGBToLinear(p) : p;
	}
	else
		return sampler.borderColor;
}

static inline bool isColorValid (const LookupPrecision& prec, const Vec4& ref, const Vec4& result)
{
	const Vec4 diff = abs(ref - result);
	return boolAll(logicalOr(lessThanEqual(diff, prec.colorThreshold), logicalNot(prec.colorMask)));
}

static inline bool isColorValid (const IntLookupPrecision& prec, const IVec4& ref, const IVec4& result)
{
	return boolAll(logicalOr(lessThanEqual(absDiff(ref, result).asUint(), prec.colorThreshold), logicalNot(prec.colorMask)));
}

static inline bool isColorValid (const IntLookupPrecision& prec, const UVec4& ref, const UVec4& result)
{
	return boolAll(logicalOr(lessThanEqual(absDiff(ref, result), prec.colorThreshold), logicalNot(prec.colorMask)));
}

struct ColorQuad
{
	Vec4	p00;		//!< (0, 0)
	Vec4	p01;		//!< (1, 0)
	Vec4	p10;		//!< (0, 1)
	Vec4	p11;		//!< (1, 1)
};

static void lookupQuad (ColorQuad& dst, const ConstPixelBufferAccess& level, const Sampler& sampler, int x0, int x1, int y0, int y1, int z)
{
	dst.p00	= lookup<float>(level, sampler, x0, y0, z);
	dst.p10	= lookup<float>(level, sampler, x1, y0, z);
	dst.p01	= lookup<float>(level, sampler, x0, y1, z);
	dst.p11	= lookup<float>(level, sampler, x1, y1, z);
}

struct ColorLine
{
	Vec4	p0;		//!< 0
	Vec4	p1;		//!< 1
};

static void lookupLine (ColorLine& dst, const ConstPixelBufferAccess& level, const Sampler& sampler, int x0, int x1, int y)
{
	dst.p0 = lookup<float>(level, sampler, x0, y, 0);
	dst.p1 = lookup<float>(level, sampler, x1, y, 0);
}

template<typename T, int Size>
static T minComp (const Vector<T, Size>& vec)
{
	T minVal = vec[0];
	for (int ndx = 1; ndx < Size; ndx++)
		minVal = de::min(minVal, vec[ndx]);
	return minVal;
}

template<typename T, int Size>
static T maxComp (const Vector<T, Size>& vec)
{
	T maxVal = vec[0];
	for (int ndx = 1; ndx < Size; ndx++)
		maxVal = de::max(maxVal, vec[ndx]);
	return maxVal;
}

static float computeBilinearSearchStepFromFloatLine (const LookupPrecision&	prec,
													 const ColorLine&		line)
{
	DE_ASSERT(boolAll(greaterThan(prec.colorThreshold, Vec4(0.0f))));

	const int		maxSteps	= 1<<16;
	const Vec4		d			= abs(line.p1 - line.p0);
	const Vec4		stepCount	= d / prec.colorThreshold;
	const Vec4		minStep		= 1.0f / (stepCount + 1.0f);
	const float		step		= de::max(minComp(minStep), 1.0f / float(maxSteps));

	return step;
}

static float computeBilinearSearchStepFromFloatQuad (const LookupPrecision&	prec,
													 const ColorQuad&		quad)
{
	DE_ASSERT(boolAll(greaterThan(prec.colorThreshold, Vec4(0.0f))));

	const int		maxSteps	= 1<<16;
	const Vec4		d0			= abs(quad.p10 - quad.p00);
	const Vec4		d1			= abs(quad.p01 - quad.p00);
	const Vec4		d2			= abs(quad.p11 - quad.p10);
	const Vec4		d3			= abs(quad.p11 - quad.p01);
	const Vec4		maxD		= max(d0, max(d1, max(d2, d3)));
	const Vec4		stepCount	= maxD / prec.colorThreshold;
	const Vec4		minStep		= 1.0f / (stepCount + 1.0f);
	const float		step		= de::max(minComp(minStep), 1.0f / float(maxSteps));

	return step;
}

static float computeBilinearSearchStepForUnorm (const LookupPrecision& prec)
{
	DE_ASSERT(boolAll(greaterThan(prec.colorThreshold, Vec4(0.0f))));

	const Vec4		stepCount	= 1.0f / prec.colorThreshold;
	const Vec4		minStep		= 1.0f / (stepCount + 1.0f);
	const float		step		= minComp(minStep);

	return step;
}

static float computeBilinearSearchStepForSnorm (const LookupPrecision& prec)
{
	DE_ASSERT(boolAll(greaterThan(prec.colorThreshold, Vec4(0.0f))));

	const Vec4		stepCount	= 2.0f / prec.colorThreshold;
	const Vec4		minStep		= 1.0f / (stepCount + 1.0f);
	const float		step		= minComp(minStep);

	return step;
}

static inline Vec4 min (const ColorLine& line)
{
	return min(line.p0, line.p1);
}

static inline Vec4 max (const ColorLine& line)
{
	return max(line.p0, line.p1);
}

static inline Vec4 min (const ColorQuad& quad)
{
	return min(quad.p00, min(quad.p10, min(quad.p01, quad.p11)));
}

static inline Vec4 max (const ColorQuad& quad)
{
	return max(quad.p00, max(quad.p10, max(quad.p01, quad.p11)));
}

static bool isInColorBounds (const LookupPrecision& prec, const ColorQuad& quad, const Vec4& result)
{
	const tcu::Vec4 minVal = min(quad) - prec.colorThreshold;
	const tcu::Vec4 maxVal = max(quad) + prec.colorThreshold;
	return boolAll(logicalOr(logicalAnd(greaterThanEqual(result, minVal), lessThanEqual(result, maxVal)), logicalNot(prec.colorMask)));
}

static bool isInColorBounds (const LookupPrecision& prec, const ColorQuad& quad0, const ColorQuad& quad1, const Vec4& result)
{
	const tcu::Vec4 minVal = min(min(quad0), min(quad1)) - prec.colorThreshold;
	const tcu::Vec4 maxVal = max(max(quad0), max(quad1)) + prec.colorThreshold;
	return boolAll(logicalOr(logicalAnd(greaterThanEqual(result, minVal), lessThanEqual(result, maxVal)), logicalNot(prec.colorMask)));
}

static bool isInColorBounds (const LookupPrecision& prec, const ColorLine& line0, const ColorLine& line1, const Vec4& result)
{
	const tcu::Vec4 minVal = min(min(line0), min(line1)) - prec.colorThreshold;
	const tcu::Vec4 maxVal = max(max(line0), max(line1)) + prec.colorThreshold;
	return boolAll(logicalOr(logicalAnd(greaterThanEqual(result, minVal), lessThanEqual(result, maxVal)), logicalNot(prec.colorMask)));
}

static bool isInColorBounds (const LookupPrecision&		prec,
							 const ColorQuad&			quad00,
							 const ColorQuad&			quad01,
							 const ColorQuad&			quad10,
							 const ColorQuad&			quad11,
							 const Vec4&				result)
{
	const tcu::Vec4 minVal = min(min(quad00), min(min(quad01), min(min(quad10), min(quad11)))) - prec.colorThreshold;
	const tcu::Vec4 maxVal = max(max(quad00), max(max(quad01), max(max(quad10), max(quad11)))) + prec.colorThreshold;
	return boolAll(logicalOr(logicalAnd(greaterThanEqual(result, minVal), lessThanEqual(result, maxVal)), logicalNot(prec.colorMask)));
}

// Range search utilities

static bool isLinearRangeValid (const LookupPrecision&	prec,
								const Vec4&				c0,
								const Vec4&				c1,
								const Vec2&				fBounds,
								const Vec4&				result)
{
	// This is basically line segment - AABB test. Valid interpolation line is checked
	// against result AABB constructed by applying threshold.

	const Vec4		i0				= c0*(1.0f - fBounds[0]) + c1*fBounds[0];
	const Vec4		i1				= c0*(1.0f - fBounds[1]) + c1*fBounds[1];
	const Vec4		rMin			= result - prec.colorThreshold;
	const Vec4		rMax			= result + prec.colorThreshold;
	bool			allIntersect	= true;

	// Algorithm: For each component check whether segment endpoints are inside, or intersect with slab.
	// If all intersect or are inside, line segment intersects the whole 4D AABB.
	for (int compNdx = 0; compNdx < 4; compNdx++)
	{
		if (!prec.colorMask[compNdx])
			continue;

		// Signs for both bounds: false = left, true = right.
		const bool	sMin0	= i0[compNdx] >= rMin[compNdx];
		const bool	sMin1	= i1[compNdx] >= rMin[compNdx];
		const bool	sMax0	= i0[compNdx] > rMax[compNdx];
		const bool	sMax1	= i1[compNdx] > rMax[compNdx];

		// If all signs are equal, line segment is outside bounds.
		if (sMin0 == sMin1 && sMin1 == sMax0 && sMax0 == sMax1)
		{
			allIntersect = false;
			break;
		}
	}

	return allIntersect;
}

static bool isBilinearRangeValid (const LookupPrecision&	prec,
								  const ColorQuad&			quad,
								  const Vec2&				xBounds,
								  const Vec2&				yBounds,
								  const float				searchStep,
								  const Vec4&				result)
{
	DE_ASSERT(xBounds.x() <= xBounds.y());
	DE_ASSERT(yBounds.x() <= yBounds.y());

	if (!isInColorBounds(prec, quad, result))
		return false;

	for (float x = xBounds.x(); x < xBounds.y()+searchStep; x += searchStep)
	{
		const float		a	= de::min(x, xBounds.y());
		const Vec4		c0	= quad.p00*(1.0f - a) + quad.p10*a;
		const Vec4		c1	= quad.p01*(1.0f - a) + quad.p11*a;

		if (isLinearRangeValid(prec, c0, c1, yBounds, result))
			return true;
	}

	return false;
}

static bool isTrilinearRangeValid (const LookupPrecision&	prec,
								   const ColorQuad&			quad0,
								   const ColorQuad&			quad1,
								   const Vec2&				xBounds,
								   const Vec2&				yBounds,
								   const Vec2&				zBounds,
								   const float				searchStep,
								   const Vec4&				result)
{
	DE_ASSERT(xBounds.x() <= xBounds.y());
	DE_ASSERT(yBounds.x() <= yBounds.y());
	DE_ASSERT(zBounds.x() <= zBounds.y());

	if (!isInColorBounds(prec, quad0, quad1, result))
		return false;

	for (float x = xBounds.x(); x < xBounds.y()+searchStep; x += searchStep)
	{
		for (float y = yBounds.x(); y < yBounds.y()+searchStep; y += searchStep)
		{
			const float		a	= de::min(x, xBounds.y());
			const float		b	= de::min(y, yBounds.y());
			const Vec4		c0	= quad0.p00*(1.0f-a)*(1.0f-b) + quad0.p10*a*(1.0f-b) + quad0.p01*(1.0f-a)*b + quad0.p11*a*b;
			const Vec4		c1	= quad1.p00*(1.0f-a)*(1.0f-b) + quad1.p10*a*(1.0f-b) + quad1.p01*(1.0f-a)*b + quad1.p11*a*b;

			if (isLinearRangeValid(prec, c0, c1, zBounds, result))
				return true;
		}
	}

	return false;
}

static bool is1DTrilinearFilterResultValid (const LookupPrecision&	prec,
											const ColorLine&		line0,
											const ColorLine&		line1,
											const Vec2&				xBounds0,
											const Vec2&				xBounds1,
											const Vec2&				zBounds,
											const float				searchStep,
											const Vec4&				result)
{
	DE_ASSERT(xBounds0.x() <= xBounds0.y());
	DE_ASSERT(xBounds1.x() <= xBounds1.y());

	if (!isInColorBounds(prec, line0, line1, result))
		return false;

	for (float x0 = xBounds0.x(); x0 < xBounds0.y()+searchStep; x0 += searchStep)
	{
		const float		a0	= de::min(x0, xBounds0.y());
		const Vec4		c0	= line0.p0*(1.0f-a0) + line0.p1*a0;

		for (float x1 = xBounds1.x(); x1 <= xBounds1.y(); x1 += searchStep)
		{
			const float		a1	= de::min(x1, xBounds1.y());
			const Vec4		c1	= line1.p0*(1.0f-a1) + line1.p1*a1;

			if (isLinearRangeValid(prec, c0, c1, zBounds, result))
				return true;
		}
	}

	return false;
}

static bool is2DTrilinearFilterResultValid (const LookupPrecision&	prec,
											const ColorQuad&		quad0,
											const ColorQuad&		quad1,
											const Vec2&				xBounds0,
											const Vec2&				yBounds0,
											const Vec2&				xBounds1,
											const Vec2&				yBounds1,
											const Vec2&				zBounds,
											const float				searchStep,
											const Vec4&				result)
{
	DE_ASSERT(xBounds0.x() <= xBounds0.y());
	DE_ASSERT(yBounds0.x() <= yBounds0.y());
	DE_ASSERT(xBounds1.x() <= xBounds1.y());
	DE_ASSERT(yBounds1.x() <= yBounds1.y());

	if (!isInColorBounds(prec, quad0, quad1, result))
		return false;

	for (float x0 = xBounds0.x(); x0 < xBounds0.y()+searchStep; x0 += searchStep)
	{
		for (float y0 = yBounds0.x(); y0 < yBounds0.y()+searchStep; y0 += searchStep)
		{
			const float		a0	= de::min(x0, xBounds0.y());
			const float		b0	= de::min(y0, yBounds0.y());
			const Vec4		c0	= quad0.p00*(1.0f-a0)*(1.0f-b0) + quad0.p10*a0*(1.0f-b0) + quad0.p01*(1.0f-a0)*b0 + quad0.p11*a0*b0;

			for (float x1 = xBounds1.x(); x1 <= xBounds1.y(); x1 += searchStep)
			{
				for (float y1 = yBounds1.x(); y1 <= yBounds1.y(); y1 += searchStep)
				{
					const float		a1	= de::min(x1, xBounds1.y());
					const float		b1	= de::min(y1, yBounds1.y());
					const Vec4		c1	= quad1.p00*(1.0f-a1)*(1.0f-b1) + quad1.p10*a1*(1.0f-b1) + quad1.p01*(1.0f-a1)*b1 + quad1.p11*a1*b1;

					if (isLinearRangeValid(prec, c0, c1, zBounds, result))
						return true;
				}
			}
		}
	}

	return false;
}

static bool is3DTrilinearFilterResultValid (const LookupPrecision&	prec,
											const ColorQuad&		quad00,
											const ColorQuad&		quad01,
											const ColorQuad&		quad10,
											const ColorQuad&		quad11,
											const Vec2&				xBounds0,
											const Vec2&				yBounds0,
											const Vec2&				zBounds0,
											const Vec2&				xBounds1,
											const Vec2&				yBounds1,
											const Vec2&				zBounds1,
											const Vec2&				wBounds,
											const float				searchStep,
											const Vec4&				result)
{
	DE_ASSERT(xBounds0.x() <= xBounds0.y());
	DE_ASSERT(yBounds0.x() <= yBounds0.y());
	DE_ASSERT(zBounds0.x() <= zBounds0.y());
	DE_ASSERT(xBounds1.x() <= xBounds1.y());
	DE_ASSERT(yBounds1.x() <= yBounds1.y());
	DE_ASSERT(zBounds1.x() <= zBounds1.y());

	if (!isInColorBounds(prec, quad00, quad01, quad10, quad11, result))
		return false;

	for (float x0 = xBounds0.x(); x0 < xBounds0.y()+searchStep; x0 += searchStep)
	{
		for (float y0 = yBounds0.x(); y0 < yBounds0.y()+searchStep; y0 += searchStep)
		{
			const float		a0	= de::min(x0, xBounds0.y());
			const float		b0	= de::min(y0, yBounds0.y());
			const Vec4		c00	= quad00.p00*(1.0f-a0)*(1.0f-b0) + quad00.p10*a0*(1.0f-b0) + quad00.p01*(1.0f-a0)*b0 + quad00.p11*a0*b0;
			const Vec4		c01	= quad01.p00*(1.0f-a0)*(1.0f-b0) + quad01.p10*a0*(1.0f-b0) + quad01.p01*(1.0f-a0)*b0 + quad01.p11*a0*b0;

			for (float z0 = zBounds0.x(); z0 < zBounds0.y()+searchStep; z0 += searchStep)
			{
				const float		c0	= de::min(z0, zBounds0.y());
				const Vec4		cz0	= c00*(1.0f-c0) + c01*c0;

				for (float x1 = xBounds1.x(); x1 < xBounds1.y()+searchStep; x1 += searchStep)
				{
					for (float y1 = yBounds1.x(); y1 < yBounds1.y()+searchStep; y1 += searchStep)
					{
						const float		a1	= de::min(x1, xBounds1.y());
						const float		b1	= de::min(y1, yBounds1.y());
						const Vec4		c10	= quad10.p00*(1.0f-a1)*(1.0f-b1) + quad10.p10*a1*(1.0f-b1) + quad10.p01*(1.0f-a1)*b1 + quad10.p11*a1*b1;
						const Vec4		c11	= quad11.p00*(1.0f-a1)*(1.0f-b1) + quad11.p10*a1*(1.0f-b1) + quad11.p01*(1.0f-a1)*b1 + quad11.p11*a1*b1;

						for (float z1 = zBounds1.x(); z1 < zBounds1.y()+searchStep; z1 += searchStep)
						{
							const float		c1	= de::min(z1, zBounds1.y());
							const Vec4		cz1	= c10*(1.0f - c1) + c11*c1;

							if (isLinearRangeValid(prec, cz0, cz1, wBounds, result))
								return true;
						}
					}
				}
			}
		}
	}

	return false;
}

template<typename PrecType, typename ScalarType>
static bool isNearestSampleResultValid (const ConstPixelBufferAccess&		level,
										const Sampler&						sampler,
										const PrecType&						prec,
										const float							coordX,
										const int							coordY,
										const Vector<ScalarType, 4>&		result)
{
	DE_ASSERT(level.getDepth() == 1);

	const Vec2		uBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(),	coordX, prec.coordBits.x(), prec.uvwBits.x());

	const int		minI			= deFloorFloatToInt32(uBounds.x());
	const int		maxI			= deFloorFloatToInt32(uBounds.y());

	for (int i = minI; i <= maxI; i++)
	{
		const int					x		= wrap(sampler.wrapS, i, level.getWidth());
		const Vector<ScalarType, 4>	color	= lookup<ScalarType>(level, sampler, x, coordY, 0);

		if (isColorValid(prec, color, result))
			return true;
	}

	return false;
}

template<typename PrecType, typename ScalarType>
static bool isNearestSampleResultValid (const ConstPixelBufferAccess&		level,
										const Sampler&						sampler,
										const PrecType&						prec,
										const Vec2&							coord,
										const int							coordZ,
										const Vector<ScalarType, 4>&		result)
{
	const Vec2		uBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(),	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2		vBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(),	coord.y(), prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinates - without wrap mode
	const int		minI			= deFloorFloatToInt32(uBounds.x());
	const int		maxI			= deFloorFloatToInt32(uBounds.y());
	const int		minJ			= deFloorFloatToInt32(vBounds.x());
	const int		maxJ			= deFloorFloatToInt32(vBounds.y());

	// \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.

	for (int j = minJ; j <= maxJ; j++)
	{
		for (int i = minI; i <= maxI; i++)
		{
			const int					x		= wrap(sampler.wrapS, i, level.getWidth());
			const int					y		= wrap(sampler.wrapT, j, level.getHeight());
			const Vector<ScalarType, 4>	color	= lookup<ScalarType>(level, sampler, x, y, coordZ);

			if (isColorValid(prec, color, result))
				return true;
		}
	}

	return false;
}

template<typename PrecType, typename ScalarType>
static bool isNearestSampleResultValid (const ConstPixelBufferAccess&		level,
										const Sampler&						sampler,
										const PrecType&						prec,
										const Vec3&							coord,
										const Vector<ScalarType, 4>&		result)
{
	const Vec2		uBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(),	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2		vBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(),	coord.y(), prec.coordBits.y(), prec.uvwBits.y());
	const Vec2		wBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getDepth(),	coord.z(), prec.coordBits.z(), prec.uvwBits.z());

	// Integer coordinates - without wrap mode
	const int		minI			= deFloorFloatToInt32(uBounds.x());
	const int		maxI			= deFloorFloatToInt32(uBounds.y());
	const int		minJ			= deFloorFloatToInt32(vBounds.x());
	const int		maxJ			= deFloorFloatToInt32(vBounds.y());
	const int		minK			= deFloorFloatToInt32(wBounds.x());
	const int		maxK			= deFloorFloatToInt32(wBounds.y());

	// \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.

	for (int k = minK; k <= maxK; k++)
	{
		for (int j = minJ; j <= maxJ; j++)
		{
			for (int i = minI; i <= maxI; i++)
			{
				const int					x		= wrap(sampler.wrapS, i, level.getWidth());
				const int					y		= wrap(sampler.wrapT, j, level.getHeight());
				const int					z		= wrap(sampler.wrapR, k, level.getDepth());
				const Vector<ScalarType, 4>	color	= lookup<ScalarType>(level, sampler, x, y, z);

				if (isColorValid(prec, color, result))
					return true;
			}
		}
	}

	return false;
}

bool isLinearSampleResultValid (const ConstPixelBufferAccess&		level,
								const Sampler&						sampler,
								const LookupPrecision&				prec,
								const float							coordX,
								const int							coordY,
								const Vec4&							result)
{
	const Vec2					uBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coordX, prec.coordBits.x(), prec.uvwBits.x());

	const int					minI			= deFloorFloatToInt32(uBounds.x()-0.5f);
	const int					maxI			= deFloorFloatToInt32(uBounds.y()-0.5f);

	const int					w				= level.getWidth();

	for (int i = minI; i <= maxI; i++)
	{
		// Wrapped coordinates
		const int	x0		= wrap(sampler.wrapS, i  , w);
		const int	x1		= wrap(sampler.wrapS, i+1, w);

		// Bounds for filtering factors
		const float	minA	= de::clamp((uBounds.x()-0.5f)-float(i), 0.0f, 1.0f);
		const float	maxA	= de::clamp((uBounds.y()-0.5f)-float(i), 0.0f, 1.0f);

		const Vec4	colorA	= lookup<float>(level, sampler, x0, coordY, 0);
		const Vec4	colorB	= lookup<float>(level, sampler, x1, coordY, 0);

		if (isLinearRangeValid(prec, colorA, colorB, Vec2(minA, maxA), result))
			return true;
	}

	return false;
}

bool isLinearSampleResultValid (const ConstPixelBufferAccess&		level,
								const Sampler&						sampler,
								const LookupPrecision&				prec,
								const Vec2&							coord,
								const int							coordZ,
								const Vec4&							result)
{
	const Vec2					uBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(),	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2					vBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(),	coord.y(), prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinate bounds for (x0,y0) - without wrap mode
	const int					minI			= deFloorFloatToInt32(uBounds.x()-0.5f);
	const int					maxI			= deFloorFloatToInt32(uBounds.y()-0.5f);
	const int					minJ			= deFloorFloatToInt32(vBounds.x()-0.5f);
	const int					maxJ			= deFloorFloatToInt32(vBounds.y()-0.5f);

	const int					w				= level.getWidth();
	const int					h				= level.getHeight();

	const TextureChannelClass	texClass		= getTextureChannelClass(level.getFormat().type);
	float						searchStep		= texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT	? computeBilinearSearchStepForUnorm(prec) :
												  texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT	? computeBilinearSearchStepForSnorm(prec) :
												  0.0f; // Step is computed for floating-point quads based on texel values.

	// \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.

	for (int j = minJ; j <= maxJ; j++)
	{
		for (int i = minI; i <= maxI; i++)
		{
			// Wrapped coordinates
			const int	x0		= wrap(sampler.wrapS, i  , w);
			const int	x1		= wrap(sampler.wrapS, i+1, w);
			const int	y0		= wrap(sampler.wrapT, j  , h);
			const int	y1		= wrap(sampler.wrapT, j+1, h);

			// Bounds for filtering factors
			const float	minA	= de::clamp((uBounds.x()-0.5f)-float(i), 0.0f, 1.0f);
			const float	maxA	= de::clamp((uBounds.y()-0.5f)-float(i), 0.0f, 1.0f);
			const float	minB	= de::clamp((vBounds.x()-0.5f)-float(j), 0.0f, 1.0f);
			const float	maxB	= de::clamp((vBounds.y()-0.5f)-float(j), 0.0f, 1.0f);

			ColorQuad quad;
			lookupQuad(quad, level, sampler, x0, x1, y0, y1, coordZ);

			if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
				searchStep = computeBilinearSearchStepFromFloatQuad(prec, quad);

			if (isBilinearRangeValid(prec, quad, Vec2(minA, maxA), Vec2(minB, maxB), searchStep, result))
				return true;
		}
	}

	return false;
}

static bool isLinearSampleResultValid (const ConstPixelBufferAccess&		level,
									   const Sampler&						sampler,
									   const LookupPrecision&				prec,
									   const Vec3&							coord,
									   const Vec4&							result)
{
	const Vec2					uBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(),	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2					vBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(),	coord.y(), prec.coordBits.y(), prec.uvwBits.y());
	const Vec2					wBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getDepth(),	coord.z(), prec.coordBits.z(), prec.uvwBits.z());

	// Integer coordinate bounds for (x0,y0) - without wrap mode
	const int					minI			= deFloorFloatToInt32(uBounds.x()-0.5f);
	const int					maxI			= deFloorFloatToInt32(uBounds.y()-0.5f);
	const int					minJ			= deFloorFloatToInt32(vBounds.x()-0.5f);
	const int					maxJ			= deFloorFloatToInt32(vBounds.y()-0.5f);
	const int					minK			= deFloorFloatToInt32(wBounds.x()-0.5f);
	const int					maxK			= deFloorFloatToInt32(wBounds.y()-0.5f);

	const int					w				= level.getWidth();
	const int					h				= level.getHeight();
	const int					d				= level.getDepth();

	const TextureChannelClass	texClass		= getTextureChannelClass(level.getFormat().type);
	float						searchStep		= texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT	? computeBilinearSearchStepForUnorm(prec) :
												  texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT	? computeBilinearSearchStepForSnorm(prec) :
												  0.0f; // Step is computed for floating-point quads based on texel values.

	// \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.

	for (int k = minK; k <= maxK; k++)
	{
		for (int j = minJ; j <= maxJ; j++)
		{
			for (int i = minI; i <= maxI; i++)
			{
				// Wrapped coordinates
				const int	x0		= wrap(sampler.wrapS, i  , w);
				const int	x1		= wrap(sampler.wrapS, i+1, w);
				const int	y0		= wrap(sampler.wrapT, j  , h);
				const int	y1		= wrap(sampler.wrapT, j+1, h);
				const int	z0		= wrap(sampler.wrapR, k  , d);
				const int	z1		= wrap(sampler.wrapR, k+1, d);

				// Bounds for filtering factors
				const float	minA	= de::clamp((uBounds.x()-0.5f)-float(i), 0.0f, 1.0f);
				const float	maxA	= de::clamp((uBounds.y()-0.5f)-float(i), 0.0f, 1.0f);
				const float	minB	= de::clamp((vBounds.x()-0.5f)-float(j), 0.0f, 1.0f);
				const float	maxB	= de::clamp((vBounds.y()-0.5f)-float(j), 0.0f, 1.0f);
				const float	minC	= de::clamp((wBounds.x()-0.5f)-float(k), 0.0f, 1.0f);
				const float	maxC	= de::clamp((wBounds.y()-0.5f)-float(k), 0.0f, 1.0f);

				ColorQuad quad0, quad1;
				lookupQuad(quad0, level, sampler, x0, x1, y0, y1, z0);
				lookupQuad(quad1, level, sampler, x0, x1, y0, y1, z1);

				if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
					searchStep = de::min(computeBilinearSearchStepFromFloatQuad(prec, quad0), computeBilinearSearchStepFromFloatQuad(prec, quad1));

				if (isTrilinearRangeValid(prec, quad0, quad1, Vec2(minA, maxA), Vec2(minB, maxB), Vec2(minC, maxC), searchStep, result))
					return true;
			}
		}
	}

	return false;
}

static bool isNearestMipmapLinearSampleResultValid (const ConstPixelBufferAccess&	level0,
													const ConstPixelBufferAccess&	level1,
													const Sampler&					sampler,
													const LookupPrecision&			prec,
													const float						coord,
													const int						coordY,
													const Vec2&						fBounds,
													const Vec4&						result)
{
	const int		w0				= level0.getWidth();
	const int		w1				= level1.getWidth();

	const Vec2		uBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0,	coord, prec.coordBits.x(), prec.uvwBits.x());
	const Vec2		uBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1,	coord, prec.coordBits.x(), prec.uvwBits.x());

	// Integer coordinates - without wrap mode
	const int		minI0			= deFloorFloatToInt32(uBounds0.x());
	const int		maxI0			= deFloorFloatToInt32(uBounds0.y());
	const int		minI1			= deFloorFloatToInt32(uBounds1.x());
	const int		maxI1			= deFloorFloatToInt32(uBounds1.y());

	for (int i0 = minI0; i0 <= maxI0; i0++)
	{
		for (int i1 = minI1; i1 <= maxI1; i1++)
		{
			const Vec4	c0	= lookup<float>(level0, sampler, wrap(sampler.wrapS, i0, w0), coordY, 0);
			const Vec4	c1	= lookup<float>(level1, sampler, wrap(sampler.wrapS, i1, w1), coordY, 0);

			if (isLinearRangeValid(prec, c0, c1, fBounds, result))
				return true;
		}
	}

	return false;
}

static bool isNearestMipmapLinearSampleResultValid (const ConstPixelBufferAccess&	level0,
													const ConstPixelBufferAccess&	level1,
													const Sampler&					sampler,
													const LookupPrecision&			prec,
													const Vec2&						coord,
													const int						coordZ,
													const Vec2&						fBounds,
													const Vec4&						result)
{
	const int		w0				= level0.getWidth();
	const int		w1				= level1.getWidth();
	const int		h0				= level0.getHeight();
	const int		h1				= level1.getHeight();

	const Vec2		uBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0,	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2		uBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1,	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2		vBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0,	coord.y(), prec.coordBits.y(), prec.uvwBits.y());
	const Vec2		vBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1,	coord.y(), prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinates - without wrap mode
	const int		minI0			= deFloorFloatToInt32(uBounds0.x());
	const int		maxI0			= deFloorFloatToInt32(uBounds0.y());
	const int		minI1			= deFloorFloatToInt32(uBounds1.x());
	const int		maxI1			= deFloorFloatToInt32(uBounds1.y());
	const int		minJ0			= deFloorFloatToInt32(vBounds0.x());
	const int		maxJ0			= deFloorFloatToInt32(vBounds0.y());
	const int		minJ1			= deFloorFloatToInt32(vBounds1.x());
	const int		maxJ1			= deFloorFloatToInt32(vBounds1.y());

	for (int j0 = minJ0; j0 <= maxJ0; j0++)
	{
		for (int i0 = minI0; i0 <= maxI0; i0++)
		{
			for (int j1 = minJ1; j1 <= maxJ1; j1++)
			{
				for (int i1 = minI1; i1 <= maxI1; i1++)
				{
					const Vec4	c0	= lookup<float>(level0, sampler, wrap(sampler.wrapS, i0, w0), wrap(sampler.wrapT, j0, h0), coordZ);
					const Vec4	c1	= lookup<float>(level1, sampler, wrap(sampler.wrapS, i1, w1), wrap(sampler.wrapT, j1, h1), coordZ);

					if (isLinearRangeValid(prec, c0, c1, fBounds, result))
						return true;
				}
			}
		}
	}

	return false;
}

static bool isNearestMipmapLinearSampleResultValid (const ConstPixelBufferAccess&	level0,
													const ConstPixelBufferAccess&	level1,
													const Sampler&					sampler,
													const LookupPrecision&			prec,
													const Vec3&						coord,
													const Vec2&						fBounds,
													const Vec4&						result)
{
	const int		w0				= level0.getWidth();
	const int		w1				= level1.getWidth();
	const int		h0				= level0.getHeight();
	const int		h1				= level1.getHeight();
	const int		d0				= level0.getDepth();
	const int		d1				= level1.getDepth();

	const Vec2		uBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0,	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2		uBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1,	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2		vBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0,	coord.y(), prec.coordBits.y(), prec.uvwBits.y());
	const Vec2		vBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1,	coord.y(), prec.coordBits.y(), prec.uvwBits.y());
	const Vec2		wBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, d0,	coord.z(), prec.coordBits.z(), prec.uvwBits.z());
	const Vec2		wBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, d1,	coord.z(), prec.coordBits.z(), prec.uvwBits.z());

	// Integer coordinates - without wrap mode
	const int		minI0			= deFloorFloatToInt32(uBounds0.x());
	const int		maxI0			= deFloorFloatToInt32(uBounds0.y());
	const int		minI1			= deFloorFloatToInt32(uBounds1.x());
	const int		maxI1			= deFloorFloatToInt32(uBounds1.y());
	const int		minJ0			= deFloorFloatToInt32(vBounds0.x());
	const int		maxJ0			= deFloorFloatToInt32(vBounds0.y());
	const int		minJ1			= deFloorFloatToInt32(vBounds1.x());
	const int		maxJ1			= deFloorFloatToInt32(vBounds1.y());
	const int		minK0			= deFloorFloatToInt32(wBounds0.x());
	const int		maxK0			= deFloorFloatToInt32(wBounds0.y());
	const int		minK1			= deFloorFloatToInt32(wBounds1.x());
	const int		maxK1			= deFloorFloatToInt32(wBounds1.y());

	for (int k0 = minK0; k0 <= maxK0; k0++)
	{
		for (int j0 = minJ0; j0 <= maxJ0; j0++)
		{
			for (int i0 = minI0; i0 <= maxI0; i0++)
			{
				for (int k1 = minK1; k1 <= maxK1; k1++)
				{
					for (int j1 = minJ1; j1 <= maxJ1; j1++)
					{
						for (int i1 = minI1; i1 <= maxI1; i1++)
						{
							const Vec4	c0	= lookup<float>(level0, sampler, wrap(sampler.wrapS, i0, w0), wrap(sampler.wrapT, j0, h0), wrap(sampler.wrapR, k0, d0));
							const Vec4	c1	= lookup<float>(level1, sampler, wrap(sampler.wrapS, i1, w1), wrap(sampler.wrapT, j1, h1), wrap(sampler.wrapR, k1, d1));

							if (isLinearRangeValid(prec, c0, c1, fBounds, result))
								return true;
						}
					}
				}
			}
		}
	}

	return false;
}

static bool isLinearMipmapLinearSampleResultValid (const ConstPixelBufferAccess&	level0,
												   const ConstPixelBufferAccess&	level1,
												   const Sampler&					sampler,
												   const LookupPrecision&			prec,
												   const float						coordX,
												   const int						coordY,
												   const Vec2&						fBounds,
												   const Vec4&						result)
{
	// \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
	//						   Right now this allows pairing any two valid bilinear quads.

	const int					w0				= level0.getWidth();
	const int					w1				= level1.getWidth();

	const Vec2					uBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0,	coordX, prec.coordBits.x(), prec.uvwBits.x());
	const Vec2					uBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1,	coordX, prec.coordBits.x(), prec.uvwBits.x());

	// Integer coordinates - without wrap mode
	const int					minI0			= deFloorFloatToInt32(uBounds0.x()-0.5f);
	const int					maxI0			= deFloorFloatToInt32(uBounds0.y()-0.5f);
	const int					minI1			= deFloorFloatToInt32(uBounds1.x()-0.5f);
	const int					maxI1			= deFloorFloatToInt32(uBounds1.y()-0.5f);

	const TextureChannelClass	texClass		= getTextureChannelClass(level0.getFormat().type);
	const float					cSearchStep		= texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT	? computeBilinearSearchStepForUnorm(prec) :
												  texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT	? computeBilinearSearchStepForSnorm(prec) :
												  0.0f; // Step is computed for floating-point quads based on texel values.

	for (int i0 = minI0; i0 <= maxI0; i0++)
	{
		ColorLine	line0;
		float		searchStep0;

		{
			const int	x0		= wrap(sampler.wrapS, i0  , w0);
			const int	x1		= wrap(sampler.wrapS, i0+1, w0);
			lookupLine(line0, level0, sampler, x0, x1, coordY);

			if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
				searchStep0 = computeBilinearSearchStepFromFloatLine(prec, line0);
			else
				searchStep0 = cSearchStep;
		}

		const float	minA0	= de::clamp((uBounds0.x()-0.5f)-float(i0), 0.0f, 1.0f);
		const float	maxA0	= de::clamp((uBounds0.y()-0.5f)-float(i0), 0.0f, 1.0f);

		for (int i1 = minI1; i1 <= maxI1; i1++)
		{
			ColorLine	line1;
			float		searchStep1;

			{
				const int	x0		= wrap(sampler.wrapS, i1  , w1);
				const int	x1		= wrap(sampler.wrapS, i1+1, w1);
				lookupLine(line1, level1, sampler, x0, x1, coordY);

				if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
					searchStep1 = computeBilinearSearchStepFromFloatLine(prec, line1);
				else
					searchStep1 = cSearchStep;
			}

			const float	minA1	= de::clamp((uBounds1.x()-0.5f)-float(i1), 0.0f, 1.0f);
			const float	maxA1	= de::clamp((uBounds1.y()-0.5f)-float(i1), 0.0f, 1.0f);

			if (is1DTrilinearFilterResultValid(prec, line0, line1, Vec2(minA0, maxA0), Vec2(minA1, maxA1), fBounds, de::min(searchStep0, searchStep1), result))
				return true;
		}
	}

	return false;
}

static bool isLinearMipmapLinearSampleResultValid (const ConstPixelBufferAccess&	level0,
												   const ConstPixelBufferAccess&	level1,
												   const Sampler&					sampler,
												   const LookupPrecision&			prec,
												   const Vec2&						coord,
												   const int						coordZ,
												   const Vec2&						fBounds,
												   const Vec4&						result)
{
	// \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
	//						   Right now this allows pairing any two valid bilinear quads.

	const int					w0				= level0.getWidth();
	const int					w1				= level1.getWidth();
	const int					h0				= level0.getHeight();
	const int					h1				= level1.getHeight();

	const Vec2					uBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0,	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2					uBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1,	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2					vBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0,	coord.y(), prec.coordBits.y(), prec.uvwBits.y());
	const Vec2					vBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1,	coord.y(), prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinates - without wrap mode
	const int					minI0			= deFloorFloatToInt32(uBounds0.x()-0.5f);
	const int					maxI0			= deFloorFloatToInt32(uBounds0.y()-0.5f);
	const int					minI1			= deFloorFloatToInt32(uBounds1.x()-0.5f);
	const int					maxI1			= deFloorFloatToInt32(uBounds1.y()-0.5f);
	const int					minJ0			= deFloorFloatToInt32(vBounds0.x()-0.5f);
	const int					maxJ0			= deFloorFloatToInt32(vBounds0.y()-0.5f);
	const int					minJ1			= deFloorFloatToInt32(vBounds1.x()-0.5f);
	const int					maxJ1			= deFloorFloatToInt32(vBounds1.y()-0.5f);

	const TextureChannelClass	texClass		= getTextureChannelClass(level0.getFormat().type);
	const float					cSearchStep		= texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT	? computeBilinearSearchStepForUnorm(prec) :
												  texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT	? computeBilinearSearchStepForSnorm(prec) :
												  0.0f; // Step is computed for floating-point quads based on texel values.

	for (int j0 = minJ0; j0 <= maxJ0; j0++)
	{
		for (int i0 = minI0; i0 <= maxI0; i0++)
		{
			ColorQuad	quad0;
			float		searchStep0;

			{
				const int	x0		= wrap(sampler.wrapS, i0  , w0);
				const int	x1		= wrap(sampler.wrapS, i0+1, w0);
				const int	y0		= wrap(sampler.wrapT, j0  , h0);
				const int	y1		= wrap(sampler.wrapT, j0+1, h0);
				lookupQuad(quad0, level0, sampler, x0, x1, y0, y1, coordZ);

				if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
					searchStep0 = computeBilinearSearchStepFromFloatQuad(prec, quad0);
				else
					searchStep0 = cSearchStep;
			}

			const float	minA0	= de::clamp((uBounds0.x()-0.5f)-float(i0), 0.0f, 1.0f);
			const float	maxA0	= de::clamp((uBounds0.y()-0.5f)-float(i0), 0.0f, 1.0f);
			const float	minB0	= de::clamp((vBounds0.x()-0.5f)-float(j0), 0.0f, 1.0f);
			const float	maxB0	= de::clamp((vBounds0.y()-0.5f)-float(j0), 0.0f, 1.0f);

			for (int j1 = minJ1; j1 <= maxJ1; j1++)
			{
				for (int i1 = minI1; i1 <= maxI1; i1++)
				{
					ColorQuad	quad1;
					float		searchStep1;

					{
						const int	x0		= wrap(sampler.wrapS, i1  , w1);
						const int	x1		= wrap(sampler.wrapS, i1+1, w1);
						const int	y0		= wrap(sampler.wrapT, j1  , h1);
						const int	y1		= wrap(sampler.wrapT, j1+1, h1);
						lookupQuad(quad1, level1, sampler, x0, x1, y0, y1, coordZ);

						if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
							searchStep1 = computeBilinearSearchStepFromFloatQuad(prec, quad1);
						else
							searchStep1 = cSearchStep;
					}

					const float	minA1	= de::clamp((uBounds1.x()-0.5f)-float(i1), 0.0f, 1.0f);
					const float	maxA1	= de::clamp((uBounds1.y()-0.5f)-float(i1), 0.0f, 1.0f);
					const float	minB1	= de::clamp((vBounds1.x()-0.5f)-float(j1), 0.0f, 1.0f);
					const float	maxB1	= de::clamp((vBounds1.y()-0.5f)-float(j1), 0.0f, 1.0f);

					if (is2DTrilinearFilterResultValid(prec, quad0, quad1, Vec2(minA0, maxA0), Vec2(minB0, maxB0), Vec2(minA1, maxA1), Vec2(minB1, maxB1),
													   fBounds, de::min(searchStep0, searchStep1), result))
						return true;
				}
			}
		}
	}

	return false;
}

static bool isLinearMipmapLinearSampleResultValid (const ConstPixelBufferAccess&	level0,
												   const ConstPixelBufferAccess&	level1,
												   const Sampler&					sampler,
												   const LookupPrecision&			prec,
												   const Vec3&						coord,
												   const Vec2&						fBounds,
												   const Vec4&						result)
{
	// \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
	//						   Right now this allows pairing any two valid bilinear quads.

	const int					w0				= level0.getWidth();
	const int					w1				= level1.getWidth();
	const int					h0				= level0.getHeight();
	const int					h1				= level1.getHeight();
	const int					d0				= level0.getDepth();
	const int					d1				= level1.getDepth();

	const Vec2					uBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0,	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2					uBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1,	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2					vBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0,	coord.y(), prec.coordBits.y(), prec.uvwBits.y());
	const Vec2					vBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1,	coord.y(), prec.coordBits.y(), prec.uvwBits.y());
	const Vec2					wBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, d0,	coord.z(), prec.coordBits.z(), prec.uvwBits.z());
	const Vec2					wBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, d1,	coord.z(), prec.coordBits.z(), prec.uvwBits.z());

	// Integer coordinates - without wrap mode
	const int					minI0			= deFloorFloatToInt32(uBounds0.x()-0.5f);
	const int					maxI0			= deFloorFloatToInt32(uBounds0.y()-0.5f);
	const int					minI1			= deFloorFloatToInt32(uBounds1.x()-0.5f);
	const int					maxI1			= deFloorFloatToInt32(uBounds1.y()-0.5f);
	const int					minJ0			= deFloorFloatToInt32(vBounds0.x()-0.5f);
	const int					maxJ0			= deFloorFloatToInt32(vBounds0.y()-0.5f);
	const int					minJ1			= deFloorFloatToInt32(vBounds1.x()-0.5f);
	const int					maxJ1			= deFloorFloatToInt32(vBounds1.y()-0.5f);
	const int					minK0			= deFloorFloatToInt32(wBounds0.x()-0.5f);
	const int					maxK0			= deFloorFloatToInt32(wBounds0.y()-0.5f);
	const int					minK1			= deFloorFloatToInt32(wBounds1.x()-0.5f);
	const int					maxK1			= deFloorFloatToInt32(wBounds1.y()-0.5f);

	const TextureChannelClass	texClass		= getTextureChannelClass(level0.getFormat().type);
	const float					cSearchStep		= texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT	? computeBilinearSearchStepForUnorm(prec) :
												  texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT	? computeBilinearSearchStepForSnorm(prec) :
												  0.0f; // Step is computed for floating-point quads based on texel values.

	for (int k0 = minK0; k0 <= maxK0; k0++)
	{
		for (int j0 = minJ0; j0 <= maxJ0; j0++)
		{
			for (int i0 = minI0; i0 <= maxI0; i0++)
			{
				ColorQuad	quad00, quad01;
				float		searchStep0;

				{
					const int	x0		= wrap(sampler.wrapS, i0  , w0);
					const int	x1		= wrap(sampler.wrapS, i0+1, w0);
					const int	y0		= wrap(sampler.wrapT, j0  , h0);
					const int	y1		= wrap(sampler.wrapT, j0+1, h0);
					const int	z0		= wrap(sampler.wrapR, k0  , d0);
					const int	z1		= wrap(sampler.wrapR, k0+1, d0);
					lookupQuad(quad00, level0, sampler, x0, x1, y0, y1, z0);
					lookupQuad(quad01, level0, sampler, x0, x1, y0, y1, z1);

					if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
						searchStep0 = de::min(computeBilinearSearchStepFromFloatQuad(prec, quad00), computeBilinearSearchStepFromFloatQuad(prec, quad01));
					else
						searchStep0 = cSearchStep;
				}

				const float	minA0	= de::clamp((uBounds0.x()-0.5f)-float(i0), 0.0f, 1.0f);
				const float	maxA0	= de::clamp((uBounds0.y()-0.5f)-float(i0), 0.0f, 1.0f);
				const float	minB0	= de::clamp((vBounds0.x()-0.5f)-float(j0), 0.0f, 1.0f);
				const float	maxB0	= de::clamp((vBounds0.y()-0.5f)-float(j0), 0.0f, 1.0f);
				const float	minC0	= de::clamp((wBounds0.x()-0.5f)-float(k0), 0.0f, 1.0f);
				const float	maxC0	= de::clamp((wBounds0.y()-0.5f)-float(k0), 0.0f, 1.0f);

				for (int k1 = minK1; k1 <= maxK1; k1++)
				{
					for (int j1 = minJ1; j1 <= maxJ1; j1++)
					{
						for (int i1 = minI1; i1 <= maxI1; i1++)
						{
							ColorQuad	quad10, quad11;
							float		searchStep1;

							{
								const int	x0		= wrap(sampler.wrapS, i1  , w1);
								const int	x1		= wrap(sampler.wrapS, i1+1, w1);
								const int	y0		= wrap(sampler.wrapT, j1  , h1);
								const int	y1		= wrap(sampler.wrapT, j1+1, h1);
								const int	z0		= wrap(sampler.wrapR, k1  , d1);
								const int	z1		= wrap(sampler.wrapR, k1+1, d1);
								lookupQuad(quad10, level1, sampler, x0, x1, y0, y1, z0);
								lookupQuad(quad11, level1, sampler, x0, x1, y0, y1, z1);

								if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
									searchStep1 = de::min(computeBilinearSearchStepFromFloatQuad(prec, quad10), computeBilinearSearchStepFromFloatQuad(prec, quad11));
								else
									searchStep1 = cSearchStep;
							}

							const float	minA1	= de::clamp((uBounds1.x()-0.5f)-float(i1), 0.0f, 1.0f);
							const float	maxA1	= de::clamp((uBounds1.y()-0.5f)-float(i1), 0.0f, 1.0f);
							const float	minB1	= de::clamp((vBounds1.x()-0.5f)-float(j1), 0.0f, 1.0f);
							const float	maxB1	= de::clamp((vBounds1.y()-0.5f)-float(j1), 0.0f, 1.0f);
							const float	minC1	= de::clamp((wBounds1.x()-0.5f)-float(k1), 0.0f, 1.0f);
							const float	maxC1	= de::clamp((wBounds1.y()-0.5f)-float(k1), 0.0f, 1.0f);

							if (is3DTrilinearFilterResultValid(prec, quad00, quad01, quad10, quad11,
															   Vec2(minA0, maxA0), Vec2(minB0, maxB0), Vec2(minC0, maxC0),
															   Vec2(minA1, maxA1), Vec2(minB1, maxB1), Vec2(minC1, maxC1),
															   fBounds, de::min(searchStep0, searchStep1), result))
								return true;
						}
					}
				}
			}
		}
	}

	return false;
}

static bool isLevelSampleResultValid (const ConstPixelBufferAccess&		level,
									  const Sampler&					sampler,
									  const Sampler::FilterMode			filterMode,
									  const LookupPrecision&			prec,
									  const float						coordX,
									  const int							coordY,
									  const Vec4&						result)
{
	if (filterMode == Sampler::LINEAR)
		return isLinearSampleResultValid(level, sampler, prec, coordX, coordY, result);
	else
		return isNearestSampleResultValid(level, sampler, prec, coordX, coordY, result);
}

static bool isLevelSampleResultValid (const ConstPixelBufferAccess&		level,
									  const Sampler&					sampler,
									  const Sampler::FilterMode			filterMode,
									  const LookupPrecision&			prec,
									  const Vec2&						coord,
									  const int							coordZ,
									  const Vec4&						result)
{
	if (filterMode == Sampler::LINEAR)
		return isLinearSampleResultValid(level, sampler, prec, coord, coordZ, result);
	else
		return isNearestSampleResultValid(level, sampler, prec, coord, coordZ, result);
}

static bool isMipmapLinearSampleResultValid (const ConstPixelBufferAccess&		level0,
										     const ConstPixelBufferAccess&		level1,
											 const Sampler&						sampler,
										     const Sampler::FilterMode			levelFilter,
										     const LookupPrecision&				prec,
										     const float						coordX,
											 const int							coordY,
										     const Vec2&						fBounds,
										     const Vec4&						result)
{
	if (levelFilter == Sampler::LINEAR)
		return isLinearMipmapLinearSampleResultValid(level0, level1, sampler, prec, coordX, coordY, fBounds, result);
	else
		return isNearestMipmapLinearSampleResultValid(level0, level1, sampler, prec, coordX, coordY, fBounds, result);
}

static bool isMipmapLinearSampleResultValid (const ConstPixelBufferAccess&		level0,
										     const ConstPixelBufferAccess&		level1,
											 const Sampler&						sampler,
										     const Sampler::FilterMode			levelFilter,
										     const LookupPrecision&				prec,
										     const Vec2&						coord,
											 const int							coordZ,
										     const Vec2&						fBounds,
										     const Vec4&						result)
{
	if (levelFilter == Sampler::LINEAR)
		return isLinearMipmapLinearSampleResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds, result);
	else
		return isNearestMipmapLinearSampleResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds, result);
}

bool isLookupResultValid (const Texture2DView& texture, const Sampler& sampler, const LookupPrecision& prec, const Vec2& coord, const Vec2& lodBounds, const Vec4& result)
{
	const float		minLod			= lodBounds.x();
	const float		maxLod			= lodBounds.y();
	const bool		canBeMagnified	= minLod <= sampler.lodThreshold;
	const bool		canBeMinified	= maxLod > sampler.lodThreshold;

	DE_ASSERT(isSamplerSupported(sampler));

	if (canBeMagnified)
	{
		if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, 0, result))
			return true;
	}

	if (canBeMinified)
	{
		const bool	isNearestMipmap	= isNearestMipmapFilter(sampler.minFilter);
		const bool	isLinearMipmap	= isLinearMipmapFilter(sampler.minFilter);
		const int	minTexLevel		= 0;
		const int	maxTexLevel		= texture.getNumLevels()-1;

		DE_ASSERT(minTexLevel <= maxTexLevel);

		if (isLinearMipmap && minTexLevel < maxTexLevel)
		{
			const int		minLevel		= de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel-1);
			const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel-1);

			DE_ASSERT(minLevel <= maxLevel);

			for (int level = minLevel; level <= maxLevel; level++)
			{
				const float		minF	= de::clamp(minLod - float(level), 0.0f, 1.0f);
				const float		maxF	= de::clamp(maxLod - float(level), 0.0f, 1.0f);

				if (isMipmapLinearSampleResultValid(texture.getLevel(level), texture.getLevel(level+1), sampler, getLevelFilter(sampler.minFilter), prec, coord, 0, Vec2(minF, maxF), result))
					return true;
			}
		}
		else if (isNearestMipmap)
		{
			// \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
			//		 decision to allow floor(lod + 0.5) as well.
			const int		minLevel		= de::clamp((int)deFloatCeil(minLod + 0.5f) - 1,	minTexLevel, maxTexLevel);
			const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod + 0.5f),		minTexLevel, maxTexLevel);

			DE_ASSERT(minLevel <= maxLevel);

			for (int level = minLevel; level <= maxLevel; level++)
			{
				if (isLevelSampleResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter), prec, coord, 0, result))
					return true;
			}
		}
		else
		{
			if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, 0, result))
				return true;
		}
	}

	return false;
}

bool isLookupResultValid (const Texture1DView& texture, const Sampler& sampler, const LookupPrecision& prec, const float coord, const Vec2& lodBounds, const Vec4& result)
{
	const float		minLod			= lodBounds.x();
	const float		maxLod			= lodBounds.y();
	const bool		canBeMagnified	= minLod <= sampler.lodThreshold;
	const bool		canBeMinified	= maxLod > sampler.lodThreshold;

	DE_ASSERT(isSamplerSupported(sampler));

	if (canBeMagnified)
	{
		if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, 0, result))
			return true;
	}

	if (canBeMinified)
	{
		const bool	isNearestMipmap	= isNearestMipmapFilter(sampler.minFilter);
		const bool	isLinearMipmap	= isLinearMipmapFilter(sampler.minFilter);
		const int	minTexLevel		= 0;
		const int	maxTexLevel		= texture.getNumLevels()-1;

		DE_ASSERT(minTexLevel <= maxTexLevel);

		if (isLinearMipmap && minTexLevel < maxTexLevel)
		{
			const int		minLevel		= de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel-1);
			const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel-1);

			DE_ASSERT(minLevel <= maxLevel);

			for (int level = minLevel; level <= maxLevel; level++)
			{
				const float		minF	= de::clamp(minLod - float(level), 0.0f, 1.0f);
				const float		maxF	= de::clamp(maxLod - float(level), 0.0f, 1.0f);

				if (isMipmapLinearSampleResultValid(texture.getLevel(level), texture.getLevel(level+1), sampler, getLevelFilter(sampler.minFilter), prec, coord, 0, Vec2(minF, maxF), result))
					return true;
			}
		}
		else if (isNearestMipmap)
		{
			// \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
			//		 decision to allow floor(lod + 0.5) as well.
			const int		minLevel		= de::clamp((int)deFloatCeil(minLod + 0.5f) - 1,	minTexLevel, maxTexLevel);
			const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod + 0.5f),		minTexLevel, maxTexLevel);

			DE_ASSERT(minLevel <= maxLevel);

			for (int level = minLevel; level <= maxLevel; level++)
			{
				if (isLevelSampleResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter), prec, coord, 0, result))
					return true;
			}
		}
		else
		{
			if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, 0, result))
				return true;
		}
	}

	return false;
}

static bool isSeamlessLinearSampleResultValid (const ConstPixelBufferAccess (&faces)[CUBEFACE_LAST],
											   const Sampler&				sampler,
											   const LookupPrecision&		prec,
											   const CubeFaceFloatCoords&	coords,
											   const Vec4&					result)
{
	const int					size			= faces[coords.face].getWidth();

	const Vec2					uBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.s, prec.coordBits.x(), prec.uvwBits.x());
	const Vec2					vBounds			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.t, prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinate bounds for (x0,y0) - without wrap mode
	const int					minI			= deFloorFloatToInt32(uBounds.x()-0.5f);
	const int					maxI			= deFloorFloatToInt32(uBounds.y()-0.5f);
	const int					minJ			= deFloorFloatToInt32(vBounds.x()-0.5f);
	const int					maxJ			= deFloorFloatToInt32(vBounds.y()-0.5f);

	const TextureChannelClass	texClass		= getTextureChannelClass(faces[coords.face].getFormat().type);
	float						searchStep		= texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT	? computeBilinearSearchStepForUnorm(prec) :
												  texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT	? computeBilinearSearchStepForSnorm(prec) :
												  0.0f; // Step is computed for floating-point quads based on texel values.

	for (int j = minJ; j <= maxJ; j++)
	{
		for (int i = minI; i <= maxI; i++)
		{
			const CubeFaceIntCoords	c00	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i+0, j+0)), size);
			const CubeFaceIntCoords	c10	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i+1, j+0)), size);
			const CubeFaceIntCoords	c01	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i+0, j+1)), size);
			const CubeFaceIntCoords	c11	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i+1, j+1)), size);

			// If any of samples is out of both edges, implementations can do pretty much anything according to spec.
			// \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
			if (c00.face == CUBEFACE_LAST || c01.face == CUBEFACE_LAST || c10.face == CUBEFACE_LAST || c11.face == CUBEFACE_LAST)
				return true;

			// Bounds for filtering factors
			const float	minA	= de::clamp((uBounds.x()-0.5f)-float(i), 0.0f, 1.0f);
			const float	maxA	= de::clamp((uBounds.y()-0.5f)-float(i), 0.0f, 1.0f);
			const float	minB	= de::clamp((vBounds.x()-0.5f)-float(j), 0.0f, 1.0f);
			const float	maxB	= de::clamp((vBounds.y()-0.5f)-float(j), 0.0f, 1.0f);

			ColorQuad quad;
			quad.p00 = lookup<float>(faces[c00.face], sampler, c00.s, c00.t, 0);
			quad.p10 = lookup<float>(faces[c10.face], sampler, c10.s, c10.t, 0);
			quad.p01 = lookup<float>(faces[c01.face], sampler, c01.s, c01.t, 0);
			quad.p11 = lookup<float>(faces[c11.face], sampler, c11.s, c11.t, 0);

			if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
				searchStep = computeBilinearSearchStepFromFloatQuad(prec, quad);

			if (isBilinearRangeValid(prec, quad, Vec2(minA, maxA), Vec2(minB, maxB), searchStep, result))
				return true;
		}
	}

	return false;
}

static bool isSeamplessLinearMipmapLinearSampleResultValid (const ConstPixelBufferAccess	(&faces0)[CUBEFACE_LAST],
															const ConstPixelBufferAccess	(&faces1)[CUBEFACE_LAST],
															const Sampler&					sampler,
															const LookupPrecision&			prec,
															const CubeFaceFloatCoords&		coords,
															const Vec2&						fBounds,
															const Vec4&						result)
{
	// \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
	//						   Right now this allows pairing any two valid bilinear quads.

	const int					size0			= faces0[coords.face].getWidth();
	const int					size1			= faces1[coords.face].getWidth();

	const Vec2					uBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0,	coords.s, prec.coordBits.x(), prec.uvwBits.x());
	const Vec2					uBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1,	coords.s, prec.coordBits.x(), prec.uvwBits.x());
	const Vec2					vBounds0		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0,	coords.t, prec.coordBits.y(), prec.uvwBits.y());
	const Vec2					vBounds1		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1,	coords.t, prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinates - without wrap mode
	const int					minI0			= deFloorFloatToInt32(uBounds0.x()-0.5f);
	const int					maxI0			= deFloorFloatToInt32(uBounds0.y()-0.5f);
	const int					minI1			= deFloorFloatToInt32(uBounds1.x()-0.5f);
	const int					maxI1			= deFloorFloatToInt32(uBounds1.y()-0.5f);
	const int					minJ0			= deFloorFloatToInt32(vBounds0.x()-0.5f);
	const int					maxJ0			= deFloorFloatToInt32(vBounds0.y()-0.5f);
	const int					minJ1			= deFloorFloatToInt32(vBounds1.x()-0.5f);
	const int					maxJ1			= deFloorFloatToInt32(vBounds1.y()-0.5f);

	const TextureChannelClass	texClass		= getTextureChannelClass(faces0[coords.face].getFormat().type);
	const float					cSearchStep		= texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT	? computeBilinearSearchStepForUnorm(prec) :
												  texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT	? computeBilinearSearchStepForSnorm(prec) :
												  0.0f; // Step is computed for floating-point quads based on texel values.

	for (int j0 = minJ0; j0 <= maxJ0; j0++)
	{
		for (int i0 = minI0; i0 <= maxI0; i0++)
		{
			ColorQuad	quad0;
			float		searchStep0;

			{
				const CubeFaceIntCoords	c00	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0+0, j0+0)), size0);
				const CubeFaceIntCoords	c10	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0+1, j0+0)), size0);
				const CubeFaceIntCoords	c01	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0+0, j0+1)), size0);
				const CubeFaceIntCoords	c11	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0+1, j0+1)), size0);

				// If any of samples is out of both edges, implementations can do pretty much anything according to spec.
				// \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
				if (c00.face == CUBEFACE_LAST || c01.face == CUBEFACE_LAST || c10.face == CUBEFACE_LAST || c11.face == CUBEFACE_LAST)
					return true;

				quad0.p00 = lookup<float>(faces0[c00.face], sampler, c00.s, c00.t, 0);
				quad0.p10 = lookup<float>(faces0[c10.face], sampler, c10.s, c10.t, 0);
				quad0.p01 = lookup<float>(faces0[c01.face], sampler, c01.s, c01.t, 0);
				quad0.p11 = lookup<float>(faces0[c11.face], sampler, c11.s, c11.t, 0);

				if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
					searchStep0 = computeBilinearSearchStepFromFloatQuad(prec, quad0);
				else
					searchStep0 = cSearchStep;
			}

			const float	minA0	= de::clamp((uBounds0.x()-0.5f)-float(i0), 0.0f, 1.0f);
			const float	maxA0	= de::clamp((uBounds0.y()-0.5f)-float(i0), 0.0f, 1.0f);
			const float	minB0	= de::clamp((vBounds0.x()-0.5f)-float(j0), 0.0f, 1.0f);
			const float	maxB0	= de::clamp((vBounds0.y()-0.5f)-float(j0), 0.0f, 1.0f);

			for (int j1 = minJ1; j1 <= maxJ1; j1++)
			{
				for (int i1 = minI1; i1 <= maxI1; i1++)
				{
					ColorQuad	quad1;
					float		searchStep1;

					{
						const CubeFaceIntCoords	c00	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1+0, j1+0)), size1);
						const CubeFaceIntCoords	c10	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1+1, j1+0)), size1);
						const CubeFaceIntCoords	c01	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1+0, j1+1)), size1);
						const CubeFaceIntCoords	c11	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1+1, j1+1)), size1);

						if (c00.face == CUBEFACE_LAST || c01.face == CUBEFACE_LAST || c10.face == CUBEFACE_LAST || c11.face == CUBEFACE_LAST)
							return true;

						quad1.p00 = lookup<float>(faces1[c00.face], sampler, c00.s, c00.t, 0);
						quad1.p10 = lookup<float>(faces1[c10.face], sampler, c10.s, c10.t, 0);
						quad1.p01 = lookup<float>(faces1[c01.face], sampler, c01.s, c01.t, 0);
						quad1.p11 = lookup<float>(faces1[c11.face], sampler, c11.s, c11.t, 0);

						if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
							searchStep1 = computeBilinearSearchStepFromFloatQuad(prec, quad1);
						else
							searchStep1 = cSearchStep;
					}

					const float	minA1	= de::clamp((uBounds1.x()-0.5f)-float(i1), 0.0f, 1.0f);
					const float	maxA1	= de::clamp((uBounds1.y()-0.5f)-float(i1), 0.0f, 1.0f);
					const float	minB1	= de::clamp((vBounds1.x()-0.5f)-float(j1), 0.0f, 1.0f);
					const float	maxB1	= de::clamp((vBounds1.y()-0.5f)-float(j1), 0.0f, 1.0f);

					if (is2DTrilinearFilterResultValid(prec, quad0, quad1, Vec2(minA0, maxA0), Vec2(minB0, maxB0), Vec2(minA1, maxA1), Vec2(minB1, maxB1),
													   fBounds, de::min(searchStep0, searchStep1), result))
						return true;
				}
			}
		}
	}

	return false;
}

static bool isCubeLevelSampleResultValid (const ConstPixelBufferAccess		(&level)[CUBEFACE_LAST],
										  const Sampler&					sampler,
										  const Sampler::FilterMode			filterMode,
										  const LookupPrecision&			prec,
										  const CubeFaceFloatCoords&		coords,
										  const Vec4&						result)
{
	if (filterMode == Sampler::LINEAR)
	{
		if (sampler.seamlessCubeMap)
			return isSeamlessLinearSampleResultValid(level, sampler, prec, coords, result);
		else
			return isLinearSampleResultValid(level[coords.face], sampler, prec, Vec2(coords.s, coords.t), 0, result);
	}
	else
		return isNearestSampleResultValid(level[coords.face], sampler, prec, Vec2(coords.s, coords.t), 0, result);
}

static bool isCubeMipmapLinearSampleResultValid (const ConstPixelBufferAccess	(&faces0)[CUBEFACE_LAST],
												const ConstPixelBufferAccess	(&faces1)[CUBEFACE_LAST],
												 const Sampler&					sampler,
												 const Sampler::FilterMode		levelFilter,
												 const LookupPrecision&			prec,
												 const CubeFaceFloatCoords&		coords,
												 const Vec2&					fBounds,
												 const Vec4&					result)
{
	if (levelFilter == Sampler::LINEAR)
	{
		if (sampler.seamlessCubeMap)
			return isSeamplessLinearMipmapLinearSampleResultValid(faces0, faces1, sampler, prec, coords, fBounds, result);
		else
			return isLinearMipmapLinearSampleResultValid(faces0[coords.face], faces1[coords.face], sampler, prec, Vec2(coords.s, coords.t), 0, fBounds, result);
	}
	else
		return isNearestMipmapLinearSampleResultValid(faces0[coords.face], faces1[coords.face], sampler, prec, Vec2(coords.s, coords.t), 0, fBounds, result);
}

static void getCubeLevelFaces (const TextureCubeView& texture, const int levelNdx, ConstPixelBufferAccess (&out)[CUBEFACE_LAST])
{
	for (int faceNdx = 0; faceNdx < CUBEFACE_LAST; faceNdx++)
		out[faceNdx] = texture.getLevelFace(levelNdx, (CubeFace)faceNdx);
}

bool isLookupResultValid (const TextureCubeView& texture, const Sampler& sampler, const LookupPrecision& prec, const Vec3& coord, const Vec2& lodBounds, const Vec4& result)
{
	int			numPossibleFaces				= 0;
	CubeFace	possibleFaces[CUBEFACE_LAST];

	DE_ASSERT(isSamplerSupported(sampler));

	getPossibleCubeFaces(coord, prec.coordBits, &possibleFaces[0], numPossibleFaces);

	if (numPossibleFaces == 0)
		return true; // Result is undefined.

	for (int tryFaceNdx = 0; tryFaceNdx < numPossibleFaces; tryFaceNdx++)
	{
		const CubeFaceFloatCoords	faceCoords		(possibleFaces[tryFaceNdx], projectToFace(possibleFaces[tryFaceNdx], coord));
		const float					minLod			= lodBounds.x();
		const float					maxLod			= lodBounds.y();
		const bool					canBeMagnified	= minLod <= sampler.lodThreshold;
		const bool					canBeMinified	= maxLod > sampler.lodThreshold;

		if (canBeMagnified)
		{
			ConstPixelBufferAccess faces[CUBEFACE_LAST];
			getCubeLevelFaces(texture, 0, faces);

			if (isCubeLevelSampleResultValid(faces, sampler, sampler.magFilter, prec, faceCoords, result))
				return true;
		}

		if (canBeMinified)
		{
			const bool	isNearestMipmap	= isNearestMipmapFilter(sampler.minFilter);
			const bool	isLinearMipmap	= isLinearMipmapFilter(sampler.minFilter);
			const int	minTexLevel		= 0;
			const int	maxTexLevel		= texture.getNumLevels()-1;

			DE_ASSERT(minTexLevel <= maxTexLevel);

			if (isLinearMipmap && minTexLevel < maxTexLevel)
			{
				const int	minLevel	= de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel-1);
				const int	maxLevel	= de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel-1);

				DE_ASSERT(minLevel <= maxLevel);

				for (int levelNdx = minLevel; levelNdx <= maxLevel; levelNdx++)
				{
					const float				minF	= de::clamp(minLod - float(levelNdx), 0.0f, 1.0f);
					const float				maxF	= de::clamp(maxLod - float(levelNdx), 0.0f, 1.0f);

					ConstPixelBufferAccess	faces0[CUBEFACE_LAST];
					ConstPixelBufferAccess	faces1[CUBEFACE_LAST];

					getCubeLevelFaces(texture, levelNdx,		faces0);
					getCubeLevelFaces(texture, levelNdx + 1,	faces1);

					if (isCubeMipmapLinearSampleResultValid(faces0, faces1, sampler, getLevelFilter(sampler.minFilter), prec, faceCoords, Vec2(minF, maxF), result))
						return true;
				}
			}
			else if (isNearestMipmap)
			{
				// \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
				//		 decision to allow floor(lod + 0.5) as well.
				const int	minLevel	= de::clamp((int)deFloatCeil(minLod + 0.5f) - 1,	minTexLevel, maxTexLevel);
				const int	maxLevel	= de::clamp((int)deFloatFloor(maxLod + 0.5f),		minTexLevel, maxTexLevel);

				DE_ASSERT(minLevel <= maxLevel);

				for (int levelNdx = minLevel; levelNdx <= maxLevel; levelNdx++)
				{
					ConstPixelBufferAccess faces[CUBEFACE_LAST];
					getCubeLevelFaces(texture, levelNdx, faces);

					if (isCubeLevelSampleResultValid(faces, sampler, getLevelFilter(sampler.minFilter), prec, faceCoords, result))
						return true;
				}
			}
			else
			{
				ConstPixelBufferAccess faces[CUBEFACE_LAST];
				getCubeLevelFaces(texture, 0, faces);

				if (isCubeLevelSampleResultValid(faces, sampler, sampler.minFilter, prec, faceCoords, result))
					return true;
			}
		}
	}

	return false;
}

static inline IVec2 computeLayerRange (int numLayers, int numCoordBits, float layerCoord)
{
	const float	err		= computeFloatingPointError(layerCoord, numCoordBits);
	const int	minL	= (int)deFloatFloor(layerCoord - err + 0.5f);		// Round down
	const int	maxL	= (int)deFloatCeil(layerCoord + err + 0.5f) - 1;	// Round up

	DE_ASSERT(minL <= maxL);

	return IVec2(de::clamp(minL, 0, numLayers-1), de::clamp(maxL, 0, numLayers-1));
}

bool isLookupResultValid (const Texture1DArrayView& texture, const Sampler& sampler, const LookupPrecision& prec, const Vec2& coord, const Vec2& lodBounds, const Vec4& result)
{
	const IVec2		layerRange		= computeLayerRange(texture.getNumLayers(), prec.coordBits.y(), coord.y());
	const float		coordX			= coord.x();
	const float		minLod			= lodBounds.x();
	const float		maxLod			= lodBounds.y();
	const bool		canBeMagnified	= minLod <= sampler.lodThreshold;
	const bool		canBeMinified	= maxLod > sampler.lodThreshold;

	DE_ASSERT(isSamplerSupported(sampler));

	for (int layer = layerRange.x(); layer <= layerRange.y(); layer++)
	{
		if (canBeMagnified)
		{
			if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coordX, layer, result))
				return true;
		}

		if (canBeMinified)
		{
			const bool	isNearestMipmap	= isNearestMipmapFilter(sampler.minFilter);
			const bool	isLinearMipmap	= isLinearMipmapFilter(sampler.minFilter);
			const int	minTexLevel		= 0;
			const int	maxTexLevel		= texture.getNumLevels()-1;

			DE_ASSERT(minTexLevel <= maxTexLevel);

			if (isLinearMipmap && minTexLevel < maxTexLevel)
			{
				const int		minLevel		= de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel-1);
				const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel-1);

				DE_ASSERT(minLevel <= maxLevel);

				for (int level = minLevel; level <= maxLevel; level++)
				{
					const float		minF	= de::clamp(minLod - float(level), 0.0f, 1.0f);
					const float		maxF	= de::clamp(maxLod - float(level), 0.0f, 1.0f);

					if (isMipmapLinearSampleResultValid(texture.getLevel(level), texture.getLevel(level+1), sampler, getLevelFilter(sampler.minFilter), prec, coordX, layer, Vec2(minF, maxF), result))
						return true;
				}
			}
			else if (isNearestMipmap)
			{
				// \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
				//		 decision to allow floor(lod + 0.5) as well.
				const int		minLevel		= de::clamp((int)deFloatCeil(minLod + 0.5f) - 1,	minTexLevel, maxTexLevel);
				const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod + 0.5f),		minTexLevel, maxTexLevel);

				DE_ASSERT(minLevel <= maxLevel);

				for (int level = minLevel; level <= maxLevel; level++)
				{
					if (isLevelSampleResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter), prec, coordX, layer, result))
						return true;
				}
			}
			else
			{
				if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coordX, layer, result))
					return true;
			}
		}
	}

	return false;
}

bool isLookupResultValid (const Texture2DArrayView& texture, const Sampler& sampler, const LookupPrecision& prec, const Vec3& coord, const Vec2& lodBounds, const Vec4& result)
{
	const IVec2		layerRange		= computeLayerRange(texture.getNumLayers(), prec.coordBits.z(), coord.z());
	const Vec2		coordXY			= coord.swizzle(0,1);
	const float		minLod			= lodBounds.x();
	const float		maxLod			= lodBounds.y();
	const bool		canBeMagnified	= minLod <= sampler.lodThreshold;
	const bool		canBeMinified	= maxLod > sampler.lodThreshold;

	DE_ASSERT(isSamplerSupported(sampler));

	for (int layer = layerRange.x(); layer <= layerRange.y(); layer++)
	{
		if (canBeMagnified)
		{
			if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coordXY, layer, result))
				return true;
		}

		if (canBeMinified)
		{
			const bool	isNearestMipmap	= isNearestMipmapFilter(sampler.minFilter);
			const bool	isLinearMipmap	= isLinearMipmapFilter(sampler.minFilter);
			const int	minTexLevel		= 0;
			const int	maxTexLevel		= texture.getNumLevels()-1;

			DE_ASSERT(minTexLevel <= maxTexLevel);

			if (isLinearMipmap && minTexLevel < maxTexLevel)
			{
				const int		minLevel		= de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel-1);
				const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel-1);

				DE_ASSERT(minLevel <= maxLevel);

				for (int level = minLevel; level <= maxLevel; level++)
				{
					const float		minF	= de::clamp(minLod - float(level), 0.0f, 1.0f);
					const float		maxF	= de::clamp(maxLod - float(level), 0.0f, 1.0f);

					if (isMipmapLinearSampleResultValid(texture.getLevel(level), texture.getLevel(level+1), sampler, getLevelFilter(sampler.minFilter), prec, coordXY, layer, Vec2(minF, maxF), result))
						return true;
				}
			}
			else if (isNearestMipmap)
			{
				// \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
				//		 decision to allow floor(lod + 0.5) as well.
				const int		minLevel		= de::clamp((int)deFloatCeil(minLod + 0.5f) - 1,	minTexLevel, maxTexLevel);
				const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod + 0.5f),		minTexLevel, maxTexLevel);

				DE_ASSERT(minLevel <= maxLevel);

				for (int level = minLevel; level <= maxLevel; level++)
				{
					if (isLevelSampleResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter), prec, coordXY, layer, result))
						return true;
				}
			}
			else
			{
				if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coordXY, layer, result))
					return true;
			}
		}
	}

	return false;
}

static bool isLevelSampleResultValid (const ConstPixelBufferAccess&		level,
									  const Sampler&					sampler,
									  const Sampler::FilterMode			filterMode,
									  const LookupPrecision&			prec,
									  const Vec3&						coord,
									  const Vec4&						result)
{
	if (filterMode == Sampler::LINEAR)
		return isLinearSampleResultValid(level, sampler, prec, coord, result);
	else
		return isNearestSampleResultValid(level, sampler, prec, coord, result);
}

static bool isMipmapLinearSampleResultValid (const ConstPixelBufferAccess&		level0,
										     const ConstPixelBufferAccess&		level1,
											 const Sampler&						sampler,
										     const Sampler::FilterMode			levelFilter,
										     const LookupPrecision&				prec,
										     const Vec3&						coord,
										     const Vec2&						fBounds,
										     const Vec4&						result)
{
	if (levelFilter == Sampler::LINEAR)
		return isLinearMipmapLinearSampleResultValid(level0, level1, sampler, prec, coord, fBounds, result);
	else
		return isNearestMipmapLinearSampleResultValid(level0, level1, sampler, prec, coord, fBounds, result);
}

bool isLookupResultValid (const Texture3DView& texture, const Sampler& sampler, const LookupPrecision& prec, const Vec3& coord, const Vec2& lodBounds, const Vec4& result)
{
	const float		minLod			= lodBounds.x();
	const float		maxLod			= lodBounds.y();
	const bool		canBeMagnified	= minLod <= sampler.lodThreshold;
	const bool		canBeMinified	= maxLod > sampler.lodThreshold;

	DE_ASSERT(isSamplerSupported(sampler));

	if (canBeMagnified)
	{
		if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, result))
			return true;
	}

	if (canBeMinified)
	{
		const bool	isNearestMipmap	= isNearestMipmapFilter(sampler.minFilter);
		const bool	isLinearMipmap	= isLinearMipmapFilter(sampler.minFilter);
		const int	minTexLevel		= 0;
		const int	maxTexLevel		= texture.getNumLevels()-1;

		DE_ASSERT(minTexLevel <= maxTexLevel);

		if (isLinearMipmap && minTexLevel < maxTexLevel)
		{
			const int		minLevel		= de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel-1);
			const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel-1);

			DE_ASSERT(minLevel <= maxLevel);

			for (int level = minLevel; level <= maxLevel; level++)
			{
				const float		minF	= de::clamp(minLod - float(level), 0.0f, 1.0f);
				const float		maxF	= de::clamp(maxLod - float(level), 0.0f, 1.0f);

				if (isMipmapLinearSampleResultValid(texture.getLevel(level), texture.getLevel(level+1), sampler, getLevelFilter(sampler.minFilter), prec, coord, Vec2(minF, maxF), result))
					return true;
			}
		}
		else if (isNearestMipmap)
		{
			// \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
			//		 decision to allow floor(lod + 0.5) as well.
			const int		minLevel		= de::clamp((int)deFloatCeil(minLod + 0.5f) - 1,	minTexLevel, maxTexLevel);
			const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod + 0.5f),		minTexLevel, maxTexLevel);

			DE_ASSERT(minLevel <= maxLevel);

			for (int level = minLevel; level <= maxLevel; level++)
			{
				if (isLevelSampleResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter), prec, coord, result))
					return true;
			}
		}
		else
		{
			if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, result))
				return true;
		}
	}

	return false;
}

static void getCubeArrayLevelFaces (const TextureCubeArrayView& texture, const int levelNdx, const int layerNdx, ConstPixelBufferAccess (&out)[CUBEFACE_LAST])
{
	const ConstPixelBufferAccess&	level		= texture.getLevel(levelNdx);
	const int						layerDepth	= layerNdx * 6;

	for (int faceNdx = 0; faceNdx < CUBEFACE_LAST; faceNdx++)
	{
		const CubeFace face = (CubeFace)faceNdx;
		out[faceNdx] = getSubregion(level, 0, 0, layerDepth + getCubeArrayFaceIndex(face), level.getWidth(), level.getHeight(), 1);
	}
}

bool isLookupResultValid (const TextureCubeArrayView& texture, const Sampler& sampler, const LookupPrecision& prec, const IVec4& coordBits, const Vec4& coord, const Vec2& lodBounds, const Vec4& result)
{
	const IVec2	layerRange						= computeLayerRange(texture.getNumLayers(), coordBits.w(), coord.w());
	const Vec3	layerCoord						= coord.toWidth<3>();
	int			numPossibleFaces				= 0;
	CubeFace	possibleFaces[CUBEFACE_LAST];

	DE_ASSERT(isSamplerSupported(sampler));

	getPossibleCubeFaces(layerCoord, prec.coordBits, &possibleFaces[0], numPossibleFaces);

	if (numPossibleFaces == 0)
		return true; // Result is undefined.

	for (int layerNdx = layerRange.x(); layerNdx <= layerRange.y(); layerNdx++)
	{
		for (int tryFaceNdx = 0; tryFaceNdx < numPossibleFaces; tryFaceNdx++)
		{
			const CubeFaceFloatCoords	faceCoords		(possibleFaces[tryFaceNdx], projectToFace(possibleFaces[tryFaceNdx], layerCoord));
			const float					minLod			= lodBounds.x();
			const float					maxLod			= lodBounds.y();
			const bool					canBeMagnified	= minLod <= sampler.lodThreshold;
			const bool					canBeMinified	= maxLod > sampler.lodThreshold;

			if (canBeMagnified)
			{
				ConstPixelBufferAccess faces[CUBEFACE_LAST];
				getCubeArrayLevelFaces(texture, 0, layerNdx, faces);

				if (isCubeLevelSampleResultValid(faces, sampler, sampler.magFilter, prec, faceCoords, result))
					return true;
			}

			if (canBeMinified)
			{
				const bool	isNearestMipmap	= isNearestMipmapFilter(sampler.minFilter);
				const bool	isLinearMipmap	= isLinearMipmapFilter(sampler.minFilter);
				const int	minTexLevel		= 0;
				const int	maxTexLevel		= texture.getNumLevels()-1;

				DE_ASSERT(minTexLevel <= maxTexLevel);

				if (isLinearMipmap && minTexLevel < maxTexLevel)
				{
					const int	minLevel	= de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel-1);
					const int	maxLevel	= de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel-1);

					DE_ASSERT(minLevel <= maxLevel);

					for (int levelNdx = minLevel; levelNdx <= maxLevel; levelNdx++)
					{
						const float		minF	= de::clamp(minLod - float(levelNdx), 0.0f, 1.0f);
						const float		maxF	= de::clamp(maxLod - float(levelNdx), 0.0f, 1.0f);

						ConstPixelBufferAccess	faces0[CUBEFACE_LAST];
						ConstPixelBufferAccess	faces1[CUBEFACE_LAST];

						getCubeArrayLevelFaces(texture, levelNdx,		layerNdx,	faces0);
						getCubeArrayLevelFaces(texture, levelNdx + 1,	layerNdx,	faces1);

						if (isCubeMipmapLinearSampleResultValid(faces0, faces1, sampler, getLevelFilter(sampler.minFilter), prec, faceCoords, Vec2(minF, maxF), result))
							return true;
					}
				}
				else if (isNearestMipmap)
				{
					// \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
					//		 decision to allow floor(lod + 0.5) as well.
					const int	minLevel	= de::clamp((int)deFloatCeil(minLod + 0.5f) - 1,	minTexLevel, maxTexLevel);
					const int	maxLevel	= de::clamp((int)deFloatFloor(maxLod + 0.5f),		minTexLevel, maxTexLevel);

					DE_ASSERT(minLevel <= maxLevel);

					for (int levelNdx = minLevel; levelNdx <= maxLevel; levelNdx++)
					{
						ConstPixelBufferAccess faces[CUBEFACE_LAST];
						getCubeArrayLevelFaces(texture, levelNdx, layerNdx, faces);

						if (isCubeLevelSampleResultValid(faces, sampler, getLevelFilter(sampler.minFilter), prec, faceCoords, result))
							return true;
					}
				}
				else
				{
					ConstPixelBufferAccess faces[CUBEFACE_LAST];
					getCubeArrayLevelFaces(texture, 0, layerNdx, faces);

					if (isCubeLevelSampleResultValid(faces, sampler, sampler.minFilter, prec, faceCoords, result))
						return true;
				}
			}
		}
	}

	return false;
}

Vec4 computeFixedPointThreshold (const IVec4& bits)
{
	return computeFixedPointError(bits);
}

Vec4 computeFloatingPointThreshold (const IVec4& bits, const Vec4& value)
{
	return computeFloatingPointError(value, bits);
}

Vec2 computeLodBoundsFromDerivates (const float dudx, const float dvdx, const float dwdx, const float dudy, const float dvdy, const float dwdy, const LodPrecision& prec)
{
	const float		mu			= de::max(deFloatAbs(dudx), deFloatAbs(dudy));
	const float		mv			= de::max(deFloatAbs(dvdx), deFloatAbs(dvdy));
	const float		mw			= de::max(deFloatAbs(dwdx), deFloatAbs(dwdy));
	const float		minDBound	= de::max(de::max(mu, mv), mw);
	const float		maxDBound	= mu + mv + mw;
	const float		minDErr		= computeFloatingPointError(minDBound, prec.derivateBits);
	const float		maxDErr		= computeFloatingPointError(maxDBound, prec.derivateBits);
	const float		minLod		= deFloatLog2(minDBound-minDErr);
	const float		maxLod		= deFloatLog2(maxDBound+maxDErr);
	const float		lodErr		= computeFixedPointError(prec.lodBits);

	DE_ASSERT(minLod <= maxLod);
	return Vec2(minLod-lodErr, maxLod+lodErr);
}

Vec2 computeLodBoundsFromDerivates (const float dudx, const float dvdx, const float dudy, const float dvdy, const LodPrecision& prec)
{
	return computeLodBoundsFromDerivates(dudx, dvdx, 0.0f, dudy, dvdy, 0.0f, prec);
}

Vec2 computeLodBoundsFromDerivates (const float dudx, const float dudy, const LodPrecision& prec)
{
	return computeLodBoundsFromDerivates(dudx, 0.0f, 0.0f, dudy, 0.0f, 0.0f, prec);
}

Vec2 computeCubeLodBoundsFromDerivates (const Vec3& coord, const Vec3& coordDx, const Vec3& coordDy, const int faceSize, const LodPrecision& prec)
{
	const bool			allowBrokenEdgeDerivate		= false;
	const CubeFace		face						= selectCubeFace(coord);
	int					maNdx						= 0;
	int					sNdx						= 0;
	int					tNdx						= 0;

	// \note Derivate signs don't matter when computing lod
	switch (face)
	{
		case CUBEFACE_NEGATIVE_X:
		case CUBEFACE_POSITIVE_X: maNdx = 0; sNdx = 2; tNdx = 1; break;
		case CUBEFACE_NEGATIVE_Y:
		case CUBEFACE_POSITIVE_Y: maNdx = 1; sNdx = 0; tNdx = 2; break;
		case CUBEFACE_NEGATIVE_Z:
		case CUBEFACE_POSITIVE_Z: maNdx = 2; sNdx = 0; tNdx = 1; break;
		default:
			DE_ASSERT(DE_FALSE);
	}

	{
		const float		sc		= coord[sNdx];
		const float		tc		= coord[tNdx];
		const float		ma		= de::abs(coord[maNdx]);
		const float		scdx	= coordDx[sNdx];
		const float		tcdx	= coordDx[tNdx];
		const float		madx	= de::abs(coordDx[maNdx]);
		const float		scdy	= coordDy[sNdx];
		const float		tcdy	= coordDy[tNdx];
		const float		mady	= de::abs(coordDy[maNdx]);
		const float		dudx	= float(faceSize) * 0.5f * (scdx*ma - sc*madx) / (ma*ma);
		const float		dvdx	= float(faceSize) * 0.5f * (tcdx*ma - tc*madx) / (ma*ma);
		const float		dudy	= float(faceSize) * 0.5f * (scdy*ma - sc*mady) / (ma*ma);
		const float		dvdy	= float(faceSize) * 0.5f * (tcdy*ma - tc*mady) / (ma*ma);
		const Vec2		bounds	= computeLodBoundsFromDerivates(dudx, dvdx, dudy, dvdy, prec);

		// Implementations may compute derivate from projected (s, t) resulting in incorrect values at edges.
		if (allowBrokenEdgeDerivate)
		{
			const Vec3			dxErr		= computeFloatingPointError(coordDx, IVec3(prec.derivateBits));
			const Vec3			dyErr		= computeFloatingPointError(coordDy, IVec3(prec.derivateBits));
			const Vec3			xoffs		= abs(coordDx) + dxErr;
			const Vec3			yoffs		= abs(coordDy) + dyErr;

			if (selectCubeFace(coord + xoffs) != face ||
				selectCubeFace(coord - xoffs) != face ||
				selectCubeFace(coord + yoffs) != face ||
				selectCubeFace(coord - yoffs) != face)
			{
				return Vec2(bounds.x(), 1000.0f);
			}
		}

		return bounds;
	}
}

Vec2 clampLodBounds (const Vec2& lodBounds, const Vec2& lodMinMax, const LodPrecision& prec)
{
	const float lodErr	= computeFixedPointError(prec.lodBits);
	const float	a		= lodMinMax.x();
	const float	b		= lodMinMax.y();
	return Vec2(de::clamp(lodBounds.x(), a-lodErr, b-lodErr), de::clamp(lodBounds.y(), a+lodErr, b+lodErr));
}

bool isLevel1DLookupResultValid (const ConstPixelBufferAccess&	access,
								 const Sampler&					sampler,
								 TexLookupScaleMode				scaleMode,
								 const LookupPrecision&			prec,
								 const float					coordX,
								 const int						coordY,
								 const Vec4&					result)
{
	const Sampler::FilterMode filterMode = scaleMode == TEX_LOOKUP_SCALE_MAGNIFY ? sampler.magFilter : sampler.minFilter;
	return isLevelSampleResultValid(access, sampler, filterMode, prec, coordX, coordY, result);
}

bool isLevel1DLookupResultValid (const ConstPixelBufferAccess&	access,
								 const Sampler&					sampler,
								 TexLookupScaleMode				scaleMode,
								 const IntLookupPrecision&		prec,
								 const float					coordX,
								 const int						coordY,
								 const IVec4&					result)
{
	DE_ASSERT(sampler.minFilter == Sampler::NEAREST && sampler.magFilter == Sampler::NEAREST);
	DE_UNREF(scaleMode);
	return isNearestSampleResultValid(access, sampler, prec, coordX, coordY, result);
}

bool isLevel1DLookupResultValid (const ConstPixelBufferAccess&	access,
								 const Sampler&					sampler,
								 TexLookupScaleMode				scaleMode,
								 const IntLookupPrecision&		prec,
								 const float					coordX,
								 const int						coordY,
								 const UVec4&					result)
{
	DE_ASSERT(sampler.minFilter == Sampler::NEAREST && sampler.magFilter == Sampler::NEAREST);
	DE_UNREF(scaleMode);
	return isNearestSampleResultValid(access, sampler, prec, coordX, coordY, result);
}

bool isLevel2DLookupResultValid (const ConstPixelBufferAccess&	access,
								 const Sampler&					sampler,
								 TexLookupScaleMode				scaleMode,
								 const LookupPrecision&			prec,
								 const Vec2&					coord,
								 const int						coordZ,
								 const Vec4&					result)
{
	const Sampler::FilterMode filterMode = scaleMode == TEX_LOOKUP_SCALE_MAGNIFY ? sampler.magFilter : sampler.minFilter;
	return isLevelSampleResultValid(access, sampler, filterMode, prec, coord, coordZ, result);
}

bool isLevel2DLookupResultValid (const ConstPixelBufferAccess&	access,
								 const Sampler&					sampler,
								 TexLookupScaleMode				scaleMode,
								 const IntLookupPrecision&		prec,
								 const Vec2&					coord,
								 const int						coordZ,
								 const IVec4&					result)
{
	DE_ASSERT(sampler.minFilter == Sampler::NEAREST && sampler.magFilter == Sampler::NEAREST);
	DE_UNREF(scaleMode);
	return isNearestSampleResultValid(access, sampler, prec, coord, coordZ, result);
}

bool isLevel2DLookupResultValid (const ConstPixelBufferAccess&	access,
								 const Sampler&					sampler,
								 TexLookupScaleMode				scaleMode,
								 const IntLookupPrecision&		prec,
								 const Vec2&					coord,
								 const int						coordZ,
								 const UVec4&					result)
{
	DE_ASSERT(sampler.minFilter == Sampler::NEAREST && sampler.magFilter == Sampler::NEAREST);
	DE_UNREF(scaleMode);
	return isNearestSampleResultValid(access, sampler, prec, coord, coordZ, result);
}

bool isLevel3DLookupResultValid (const ConstPixelBufferAccess&	access,
								 const Sampler&					sampler,
								 TexLookupScaleMode				scaleMode,
								 const LookupPrecision&			prec,
								 const Vec3&					coord,
								 const Vec4&					result)
{
	const tcu::Sampler::FilterMode filterMode = scaleMode == TEX_LOOKUP_SCALE_MAGNIFY ? sampler.magFilter : sampler.minFilter;
	return isLevelSampleResultValid(access, sampler, filterMode, prec, coord, result);
}

bool isLevel3DLookupResultValid (const ConstPixelBufferAccess&	access,
								 const Sampler&					sampler,
								 TexLookupScaleMode				scaleMode,
								 const IntLookupPrecision&		prec,
								 const Vec3&					coord,
								 const IVec4&					result)
{
	DE_ASSERT(sampler.minFilter == Sampler::NEAREST && sampler.magFilter == Sampler::NEAREST);
	DE_UNREF(scaleMode);
	return isNearestSampleResultValid(access, sampler, prec, coord, result);
}

bool isLevel3DLookupResultValid (const ConstPixelBufferAccess&	access,
								 const Sampler&					sampler,
								 TexLookupScaleMode				scaleMode,
								 const IntLookupPrecision&		prec,
								 const Vec3&					coord,
								 const UVec4&					result)
{
	DE_ASSERT(sampler.minFilter == Sampler::NEAREST && sampler.magFilter == Sampler::NEAREST);
	DE_UNREF(scaleMode);
	return isNearestSampleResultValid(access, sampler, prec, coord, result);
}

template<typename PrecType, typename ScalarType>
static bool isGatherOffsetsResultValid (const ConstPixelBufferAccess&	level,
										const Sampler&					sampler,
										const PrecType&					prec,
										const Vec2&						coord,
										int								coordZ,
										int								componentNdx,
										const IVec2						(&offsets)[4],
										const Vector<ScalarType, 4>&	result)
{
	const Vec2	uBounds		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(),	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2	vBounds		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(),	coord.y(), prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinate bounds for (x0, y0) - without wrap mode
	const int	minI		= deFloorFloatToInt32(uBounds.x()-0.5f);
	const int	maxI		= deFloorFloatToInt32(uBounds.y()-0.5f);
	const int	minJ		= deFloorFloatToInt32(vBounds.x()-0.5f);
	const int	maxJ		= deFloorFloatToInt32(vBounds.y()-0.5f);

	const int	w			= level.getWidth();
	const int	h			= level.getHeight();

	for (int j = minJ; j <= maxJ; j++)
	{
		for (int i = minI; i <= maxI; i++)
		{
			Vector<ScalarType, 4> color;
			for (int offNdx = 0; offNdx < 4; offNdx++)
			{
				// offNdx-th coordinate offset and then wrapped.
				const int x = wrap(sampler.wrapS, i+offsets[offNdx].x(), w);
				const int y = wrap(sampler.wrapT, j+offsets[offNdx].y(), h);
				color[offNdx] = lookup<ScalarType>(level, sampler, x, y, coordZ)[componentNdx];
			}

			if (isColorValid(prec, color, result))
				return true;
		}
	}

	return false;
}

bool isGatherOffsetsResultValid (const Texture2DView&			texture,
								 const Sampler&					sampler,
								 const LookupPrecision&			prec,
								 const Vec2&					coord,
								 int							componentNdx,
								 const IVec2					(&offsets)[4],
								 const Vec4&					result)
{
	return isGatherOffsetsResultValid(texture.getLevel(0), sampler, prec, coord, 0, componentNdx, offsets, result);
}

bool isGatherOffsetsResultValid (const Texture2DView&			texture,
								 const Sampler&					sampler,
								 const IntLookupPrecision&		prec,
								 const Vec2&					coord,
								 int							componentNdx,
								 const IVec2					(&offsets)[4],
								 const IVec4&					result)
{
	return isGatherOffsetsResultValid(texture.getLevel(0), sampler, prec, coord, 0, componentNdx, offsets, result);
}

bool isGatherOffsetsResultValid (const Texture2DView&			texture,
								 const Sampler&					sampler,
								 const IntLookupPrecision&		prec,
								 const Vec2&					coord,
								 int							componentNdx,
								 const IVec2					(&offsets)[4],
								 const UVec4&					result)
{
	return isGatherOffsetsResultValid(texture.getLevel(0), sampler, prec, coord, 0, componentNdx, offsets, result);
}

template <typename PrecType, typename ScalarType>
static bool is2DArrayGatherOffsetsResultValid (const Texture2DArrayView&		texture,
											   const Sampler&					sampler,
											   const PrecType&					prec,
											   const Vec3&						coord,
											   int								componentNdx,
											   const IVec2						(&offsets)[4],
											   const Vector<ScalarType, 4>&		result)
{
	const IVec2 layerRange = computeLayerRange(texture.getNumLayers(), prec.coordBits.z(), coord.z());
	for (int layer = layerRange.x(); layer <= layerRange.y(); layer++)
	{
		if (isGatherOffsetsResultValid(texture.getLevel(0), sampler, prec, coord.swizzle(0,1), layer, componentNdx, offsets, result))
			return true;
	}
	return false;
}

bool isGatherOffsetsResultValid (const Texture2DArrayView&		texture,
								 const Sampler&					sampler,
								 const LookupPrecision&			prec,
								 const Vec3&					coord,
								 int							componentNdx,
								 const IVec2					(&offsets)[4],
								 const Vec4&					result)
{
	return is2DArrayGatherOffsetsResultValid(texture, sampler, prec, coord, componentNdx, offsets, result);
}

bool isGatherOffsetsResultValid (const Texture2DArrayView&		texture,
								 const Sampler&					sampler,
								 const IntLookupPrecision&		prec,
								 const Vec3&					coord,
								 int							componentNdx,
								 const IVec2					(&offsets)[4],
								 const IVec4&					result)
{
	return is2DArrayGatherOffsetsResultValid(texture, sampler, prec, coord, componentNdx, offsets, result);
}

bool isGatherOffsetsResultValid (const Texture2DArrayView&		texture,
								 const Sampler&					sampler,
								 const IntLookupPrecision&		prec,
								 const Vec3&					coord,
								 int							componentNdx,
								 const IVec2					(&offsets)[4],
								 const UVec4&					result)
{
	return is2DArrayGatherOffsetsResultValid(texture, sampler, prec, coord, componentNdx, offsets, result);
}

template<typename PrecType, typename ScalarType>
static bool isGatherResultValid (const TextureCubeView&			texture,
								 const Sampler&					sampler,
								 const PrecType&				prec,
								 const CubeFaceFloatCoords&		coords,
								 int							componentNdx,
								 const Vector<ScalarType, 4>&	result)
{
	const int	size		= texture.getLevelFace(0, coords.face).getWidth();

	const Vec2	uBounds		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.s, prec.coordBits.x(), prec.uvwBits.x());
	const Vec2	vBounds		= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.t, prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinate bounds for (x0,y0) - without wrap mode
	const int	minI		= deFloorFloatToInt32(uBounds.x()-0.5f);
	const int	maxI		= deFloorFloatToInt32(uBounds.y()-0.5f);
	const int	minJ		= deFloorFloatToInt32(vBounds.x()-0.5f);
	const int	maxJ		= deFloorFloatToInt32(vBounds.y()-0.5f);

	// Face accesses
	ConstPixelBufferAccess faces[CUBEFACE_LAST];
	for (int face = 0; face < CUBEFACE_LAST; face++)
		faces[face] = texture.getLevelFace(0, CubeFace(face));

	for (int j = minJ; j <= maxJ; j++)
	{
		for (int i = minI; i <= maxI; i++)
		{
			static const IVec2 offsets[4] =
			{
				IVec2(0, 1),
				IVec2(1, 1),
				IVec2(1, 0),
				IVec2(0, 0)
			};

			Vector<ScalarType, 4> color;
			for (int offNdx = 0; offNdx < 4; offNdx++)
			{
				const CubeFaceIntCoords c = remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, i+offsets[offNdx].x(), j+offsets[offNdx].y()), size);
				// If any of samples is out of both edges, implementations can do pretty much anything according to spec.
				// \todo [2014-06-05 nuutti] Test the special case where all corner pixels have exactly the same color.
				//							 See also isSeamlessLinearSampleResultValid and similar.
				if (c.face == CUBEFACE_LAST)
					return true;

				color[offNdx] = lookup<ScalarType>(faces[c.face], sampler, c.s, c.t, 0)[componentNdx];
			}

			if (isColorValid(prec, color, result))
				return true;
		}
	}

	return false;
}

template <typename PrecType, typename ScalarType>
static bool isCubeGatherResultValid (const TextureCubeView&			texture,
									 const Sampler&					sampler,
									 const PrecType&				prec,
									 const Vec3&					coord,
									 int							componentNdx,
									 const Vector<ScalarType, 4>&	result)
{
	int			numPossibleFaces				= 0;
	CubeFace	possibleFaces[CUBEFACE_LAST];

	getPossibleCubeFaces(coord, prec.coordBits, &possibleFaces[0], numPossibleFaces);

	if (numPossibleFaces == 0)
		return true; // Result is undefined.

	for (int tryFaceNdx = 0; tryFaceNdx < numPossibleFaces; tryFaceNdx++)
	{
		const CubeFaceFloatCoords faceCoords(possibleFaces[tryFaceNdx], projectToFace(possibleFaces[tryFaceNdx], coord));

		if (isGatherResultValid(texture, sampler, prec, faceCoords, componentNdx, result))
			return true;
	}

	return false;
}

bool isGatherResultValid (const TextureCubeView&	texture,
						  const Sampler&			sampler,
						  const LookupPrecision&	prec,
						  const Vec3&				coord,
						  int						componentNdx,
						  const Vec4&				result)
{
	return isCubeGatherResultValid(texture, sampler, prec, coord, componentNdx, result);
}

bool isGatherResultValid (const TextureCubeView&		texture,
						  const Sampler&				sampler,
						  const IntLookupPrecision&		prec,
						  const Vec3&					coord,
						  int							componentNdx,
						  const IVec4&					result)
{
	return isCubeGatherResultValid(texture, sampler, prec, coord, componentNdx, result);
}

bool isGatherResultValid (const TextureCubeView&		texture,
						  const Sampler&				sampler,
						  const IntLookupPrecision&		prec,
						  const Vec3&					coord,
						  int							componentNdx,
						  const UVec4&					result)
{
	return isCubeGatherResultValid(texture, sampler, prec, coord, componentNdx, result);
}

} // tcu
