/*-------------------------------------------------------------------------
 * 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 sampleTextureBorder<ScalarType>(access.getFormat(), sampler);
}

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 sampleTextureBorder<float>(access.getFormat(), sampler);
}

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
