/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2016 The Khronos Group Inc.
 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
 * Copyright (c) 2016 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 GLSL textureGather[Offset[s]] tests.
 *//*--------------------------------------------------------------------*/

#include "vktShaderRenderTextureGatherTests.hpp"
#include "vktShaderRender.hpp"
#include "vkImageUtil.hpp"
#include "vkQueryUtil.hpp"
#include "gluTextureUtil.hpp"
#include "tcuTexture.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuSurface.hpp"
#include "tcuTestLog.hpp"
#include "tcuVectorUtil.hpp"
#include "tcuTexLookupVerifier.hpp"
#include "tcuTexCompareVerifier.hpp"
#include "tcuPixelFormat.hpp"
#include "tcuCommandLine.hpp"
#include "deUniquePtr.hpp"
#include "deStringUtil.hpp"
#include "deRandom.hpp"

#include <algorithm>
#include <iterator>

using tcu::ConstPixelBufferAccess;
using tcu::PixelBufferAccess;
using tcu::TestLog;
using tcu::IVec2;
using tcu::IVec3;
using tcu::IVec4;
using tcu::UVec4;
using tcu::Vec2;
using tcu::Vec3;
using tcu::Vec4;
using de::MovePtr;

using std::string;
using std::vector;

namespace vkt
{
namespace sr
{
namespace
{

typedef ShaderRenderCaseInstance::ImageBackingMode ImageBackingMode;

enum
{
	SPEC_MAX_MIN_OFFSET = -8,
	SPEC_MIN_MAX_OFFSET = 7
};

enum TextureType
{
	TEXTURETYPE_2D,
	TEXTURETYPE_2D_ARRAY,
	TEXTURETYPE_CUBE,

	TEXTURETYPE_LAST
};

// \note TextureTestUtil functions are copied from glsTextureTestUtil
namespace TextureTestUtil
{

inline tcu::IVec4 getBitsVec (const tcu::PixelFormat& format)
{
	return tcu::IVec4(format.redBits, format.greenBits, format.blueBits, format.alphaBits);
}

inline tcu::BVec4 getCompareMask (const tcu::PixelFormat& format)
{
	return tcu::BVec4(format.redBits	> 0,
					  format.greenBits	> 0,
					  format.blueBits	> 0,
					  format.alphaBits	> 0);
}

void computeQuadTexCoord2D (std::vector<float>& dst, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
{
	dst.resize(4*2);

	dst[0] = bottomLeft.x();	dst[1] = bottomLeft.y();
	dst[2] = bottomLeft.x();	dst[3] = topRight.y();
	dst[4] = topRight.x();		dst[5] = bottomLeft.y();
	dst[6] = topRight.x();		dst[7] = topRight.y();
}

void computeQuadTexCoord2DArray (std::vector<float>& dst, int layerNdx, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
{
	dst.resize(4*3);

	dst[0] = bottomLeft.x();	dst[ 1] = bottomLeft.y();	dst[ 2] = (float)layerNdx;
	dst[3] = bottomLeft.x();	dst[ 4] = topRight.y();		dst[ 5] = (float)layerNdx;
	dst[6] = topRight.x();		dst[ 7] = bottomLeft.y();	dst[ 8] = (float)layerNdx;
	dst[9] = topRight.x();		dst[10] = topRight.y();		dst[11] = (float)layerNdx;
}

void computeQuadTexCoordCube (std::vector<float>& dst, tcu::CubeFace face, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
{
	int		sRow		= 0;
	int		tRow		= 0;
	int		mRow		= 0;
	float	sSign		= 1.0f;
	float	tSign		= 1.0f;
	float	mSign		= 1.0f;

	switch (face)
	{
		case tcu::CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0f;				   tSign = -1.0f;	break;
		case tcu::CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1;				sSign = -1.0f; tSign = -1.0f;	break;
		case tcu::CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0f;				   tSign = -1.0f;	break;
		case tcu::CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2;												break;
		case tcu::CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0f; sSign = -1.0f; tSign = -1.0f;	break;
		case tcu::CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1;							   tSign = -1.0f;	break;
		default:
			DE_ASSERT(DE_FALSE);
			return;
	}

	dst.resize(3*4);

	dst[0+mRow] = mSign;
	dst[3+mRow] = mSign;
	dst[6+mRow] = mSign;
	dst[9+mRow] = mSign;

	dst[0+sRow] = sSign * bottomLeft.x();
	dst[3+sRow] = sSign * bottomLeft.x();
	dst[6+sRow] = sSign * topRight.x();
	dst[9+sRow] = sSign * topRight.x();

	dst[0+tRow] = tSign * bottomLeft.y();
	dst[3+tRow] = tSign * topRight.y();
	dst[6+tRow] = tSign * bottomLeft.y();
	dst[9+tRow] = tSign * topRight.y();
}

} // TextureTestUtil

// Round-to-zero int division, because pre-c++11 it's somewhat implementation-defined for negative values.
static inline int divRoundToZero (int a, int b)
{
	return de::abs(a) / de::abs(b) * deSign32(a) * deSign32(b);
}

static void fillWithRandomColorTiles (const PixelBufferAccess& dst, const Vec4& minVal, const Vec4& maxVal, deUint32 seed)
{
	const int	numCols		= dst.getWidth()  >= 7 ? 7 : dst.getWidth();
	const int	numRows		= dst.getHeight() >= 5 ? 5 : dst.getHeight();
	de::Random	rnd			(seed);

	for (int slice = 0; slice < dst.getDepth(); slice++)
	for (int row = 0; row < numRows; row++)
	for (int col = 0; col < numCols; col++)
	{
		const int	yBegin	= (row+0)*dst.getHeight()/numRows;
		const int	yEnd	= (row+1)*dst.getHeight()/numRows;
		const int	xBegin	= (col+0)*dst.getWidth()/numCols;
		const int	xEnd	= (col+1)*dst.getWidth()/numCols;
		const Vec4	color	= tcu::randomVector<float, 4>(rnd, minVal, maxVal);

		tcu::clear(tcu::getSubregion(dst, xBegin, yBegin, slice, xEnd-xBegin, yEnd-yBegin, 1), color);
	}
}

static inline bool isDepthFormat (const tcu::TextureFormat& fmt)
{
	return fmt.order == tcu::TextureFormat::D || fmt.order == tcu::TextureFormat::DS;
}

static inline bool isUnormFormatType (tcu::TextureFormat::ChannelType type)
{
	return type == tcu::TextureFormat::UNORM_INT8	||
		   type == tcu::TextureFormat::UNORM_INT16	||
		   type == tcu::TextureFormat::UNORM_INT32;
}

static inline bool isSIntFormatType (tcu::TextureFormat::ChannelType type)
{
	return type == tcu::TextureFormat::SIGNED_INT8	||
		   type == tcu::TextureFormat::SIGNED_INT16	||
		   type == tcu::TextureFormat::SIGNED_INT32;
}

static inline bool isUIntFormatType (tcu::TextureFormat::ChannelType type)
{
	return type == tcu::TextureFormat::UNSIGNED_INT8	||
		   type == tcu::TextureFormat::UNSIGNED_INT16	||
		   type == tcu::TextureFormat::UNSIGNED_INT32;
}

enum TextureSwizzleComponent
{
	TEXTURESWIZZLECOMPONENT_R = 0,
	TEXTURESWIZZLECOMPONENT_G,
	TEXTURESWIZZLECOMPONENT_B,
	TEXTURESWIZZLECOMPONENT_A,
	TEXTURESWIZZLECOMPONENT_ZERO,
	TEXTURESWIZZLECOMPONENT_ONE,

	TEXTURESWIZZLECOMPONENT_LAST
};

static std::ostream& operator<< (std::ostream& stream, TextureSwizzleComponent comp)
{
	switch (comp)
	{
		case TEXTURESWIZZLECOMPONENT_R:		return stream << "RED";
		case TEXTURESWIZZLECOMPONENT_G:		return stream << "GREEN";
		case TEXTURESWIZZLECOMPONENT_B:		return stream << "BLUE";
		case TEXTURESWIZZLECOMPONENT_A:		return stream << "ALPHA";
		case TEXTURESWIZZLECOMPONENT_ZERO:	return stream << "ZERO";
		case TEXTURESWIZZLECOMPONENT_ONE:	return stream << "ONE";
		default: DE_ASSERT(false); return stream;
	}
}

struct MaybeTextureSwizzle
{
public:
	static MaybeTextureSwizzle						createNoneTextureSwizzle	(void);
	static MaybeTextureSwizzle						createSomeTextureSwizzle	(void);

	bool											isSome						(void) const;
	bool											isNone						(void) const;
	bool											isIdentitySwizzle			(void) const;

	tcu::Vector<TextureSwizzleComponent, 4>&		getSwizzle					(void);
	const tcu::Vector<TextureSwizzleComponent, 4>&	getSwizzle					(void) const;

private:
													MaybeTextureSwizzle			(void);

	tcu::Vector<TextureSwizzleComponent, 4>			m_swizzle;
	bool											m_isSome;
};

static std::ostream& operator<< (std::ostream& stream, const MaybeTextureSwizzle& comp)
{
	if (comp.isNone())
		stream << "[default swizzle state]";
	else
		stream << "(" << comp.getSwizzle()[0]
			   << ", " << comp.getSwizzle()[1]
			   << ", " << comp.getSwizzle()[2]
			   << ", " << comp.getSwizzle()[3]
			   << ")";

	return stream;
}

MaybeTextureSwizzle MaybeTextureSwizzle::createNoneTextureSwizzle (void)
{
	MaybeTextureSwizzle swizzle;

	swizzle.m_swizzle[0] = TEXTURESWIZZLECOMPONENT_LAST;
	swizzle.m_swizzle[1] = TEXTURESWIZZLECOMPONENT_LAST;
	swizzle.m_swizzle[2] = TEXTURESWIZZLECOMPONENT_LAST;
	swizzle.m_swizzle[3] = TEXTURESWIZZLECOMPONENT_LAST;
	swizzle.m_isSome = false;

	return swizzle;
}

MaybeTextureSwizzle MaybeTextureSwizzle::createSomeTextureSwizzle (void)
{
	MaybeTextureSwizzle swizzle;

	swizzle.m_swizzle[0] = TEXTURESWIZZLECOMPONENT_R;
	swizzle.m_swizzle[1] = TEXTURESWIZZLECOMPONENT_G;
	swizzle.m_swizzle[2] = TEXTURESWIZZLECOMPONENT_B;
	swizzle.m_swizzle[3] = TEXTURESWIZZLECOMPONENT_A;
	swizzle.m_isSome = true;

	return swizzle;
}

bool MaybeTextureSwizzle::isSome (void) const
{
	return m_isSome;
}

bool MaybeTextureSwizzle::isNone (void) const
{
	return !m_isSome;
}

bool MaybeTextureSwizzle::isIdentitySwizzle (void) const
{
	return	m_isSome									&&
			m_swizzle[0] == TEXTURESWIZZLECOMPONENT_R	&&
			m_swizzle[1] == TEXTURESWIZZLECOMPONENT_G	&&
			m_swizzle[2] == TEXTURESWIZZLECOMPONENT_B	&&
			m_swizzle[3] == TEXTURESWIZZLECOMPONENT_A;
}

tcu::Vector<TextureSwizzleComponent, 4>& MaybeTextureSwizzle::getSwizzle (void)
{
	return m_swizzle;
}

const tcu::Vector<TextureSwizzleComponent, 4>& MaybeTextureSwizzle::getSwizzle (void) const
{
	return m_swizzle;
}

MaybeTextureSwizzle::MaybeTextureSwizzle (void)
	: m_swizzle	(TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST)
	, m_isSome	(false)
{
}

static vk::VkComponentSwizzle getTextureSwizzleComponent (TextureSwizzleComponent c)
{
	switch (c)
	{
		case TEXTURESWIZZLECOMPONENT_R:		return vk::VK_COMPONENT_SWIZZLE_R;
		case TEXTURESWIZZLECOMPONENT_G:		return vk::VK_COMPONENT_SWIZZLE_G;
		case TEXTURESWIZZLECOMPONENT_B:		return vk::VK_COMPONENT_SWIZZLE_B;
		case TEXTURESWIZZLECOMPONENT_A:		return vk::VK_COMPONENT_SWIZZLE_A;
		case TEXTURESWIZZLECOMPONENT_ZERO:	return vk::VK_COMPONENT_SWIZZLE_ZERO;
		case TEXTURESWIZZLECOMPONENT_ONE:	return vk::VK_COMPONENT_SWIZZLE_ONE;
		default: DE_ASSERT(false); return (vk::VkComponentSwizzle)0;
	}
}

template <typename T>
static inline T swizzleColorChannel (const tcu::Vector<T, 4>& src, TextureSwizzleComponent swizzle)
{
	switch (swizzle)
	{
		case TEXTURESWIZZLECOMPONENT_R:		return src[0];
		case TEXTURESWIZZLECOMPONENT_G:		return src[1];
		case TEXTURESWIZZLECOMPONENT_B:		return src[2];
		case TEXTURESWIZZLECOMPONENT_A:		return src[3];
		case TEXTURESWIZZLECOMPONENT_ZERO:	return (T)0;
		case TEXTURESWIZZLECOMPONENT_ONE:	return (T)1;
		default: DE_ASSERT(false); return (T)-1;
	}
}

template <typename T>
static inline tcu::Vector<T, 4> swizzleColor (const tcu::Vector<T, 4>& src, const MaybeTextureSwizzle& swizzle)
{
	DE_ASSERT(swizzle.isSome());

	tcu::Vector<T, 4> result;
	for (int i = 0; i < 4; i++)
		result[i] = swizzleColorChannel(src, swizzle.getSwizzle()[i]);
	return result;
}

template <typename T>
static void swizzlePixels (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, const MaybeTextureSwizzle& swizzle)
{
	DE_ASSERT(dst.getWidth()  == src.getWidth()  &&
			  dst.getHeight() == src.getHeight() &&
			  dst.getDepth()  == src.getDepth());
	for (int z = 0; z < src.getDepth(); z++)
	for (int y = 0; y < src.getHeight(); y++)
	for (int x = 0; x < src.getWidth(); x++)
		dst.setPixel(swizzleColor(src.getPixelT<T>(x, y, z), swizzle), x, y, z);
}

static void swizzlePixels (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, const MaybeTextureSwizzle& swizzle)
{
	if (isDepthFormat(dst.getFormat()))
		DE_ASSERT(swizzle.isNone() || swizzle.isIdentitySwizzle());

	if (swizzle.isNone() || swizzle.isIdentitySwizzle())
		tcu::copy(dst, src);
	else if (isUnormFormatType(dst.getFormat().type))
		swizzlePixels<float>(dst, src, swizzle);
	else if (isUIntFormatType(dst.getFormat().type))
		swizzlePixels<deUint32>(dst, src, swizzle);
	else if (isSIntFormatType(dst.getFormat().type))
		swizzlePixels<deInt32>(dst, src, swizzle);
	else
		DE_ASSERT(false);
}

static void swizzleTexture (tcu::Texture2D& dst, const tcu::Texture2D& src, const MaybeTextureSwizzle& swizzle)
{
	dst = tcu::Texture2D(src.getFormat(), src.getWidth(), src.getHeight());
	for (int levelNdx = 0; levelNdx < src.getNumLevels(); levelNdx++)
	{
		if (src.isLevelEmpty(levelNdx))
			continue;
		dst.allocLevel(levelNdx);
		swizzlePixels(dst.getLevel(levelNdx), src.getLevel(levelNdx), swizzle);
	}
}

static void swizzleTexture (tcu::Texture2DArray& dst, const tcu::Texture2DArray& src, const MaybeTextureSwizzle& swizzle)
{
	dst = tcu::Texture2DArray(src.getFormat(), src.getWidth(), src.getHeight(), src.getNumLayers());
	for (int levelNdx = 0; levelNdx < src.getNumLevels(); levelNdx++)
	{
		if (src.isLevelEmpty(levelNdx))
			continue;
		dst.allocLevel(levelNdx);
		swizzlePixels(dst.getLevel(levelNdx), src.getLevel(levelNdx), swizzle);
	}
}

static void swizzleTexture (tcu::TextureCube& dst, const tcu::TextureCube& src, const MaybeTextureSwizzle& swizzle)
{
	dst = tcu::TextureCube(src.getFormat(), src.getSize());
	for (int faceI = 0; faceI < tcu::CUBEFACE_LAST; faceI++)
	{
		const tcu::CubeFace face = (tcu::CubeFace)faceI;
		for (int levelNdx = 0; levelNdx < src.getNumLevels(); levelNdx++)
		{
			if (src.isLevelEmpty(face, levelNdx))
				continue;
			dst.allocLevel(face, levelNdx);
			swizzlePixels(dst.getLevelFace(levelNdx, face), src.getLevelFace(levelNdx, face), swizzle);
		}
	}
}

static tcu::Texture2DView getOneLevelSubView (const tcu::Texture2DView& view, int level)
{
	return tcu::Texture2DView(1, view.getLevels() + level);
}

static tcu::Texture2DArrayView getOneLevelSubView (const tcu::Texture2DArrayView& view, int level)
{
	return tcu::Texture2DArrayView(1, view.getLevels() + level);
}

static tcu::TextureCubeView getOneLevelSubView (const tcu::TextureCubeView& view, int level)
{
	const tcu::ConstPixelBufferAccess* levels[tcu::CUBEFACE_LAST];

	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
		levels[face] = view.getFaceLevels((tcu::CubeFace)face) + level;

	return tcu::TextureCubeView(1, levels);
}

class PixelOffsets
{
public:
	virtual void operator() (const IVec2& pixCoord, IVec2 (&dst)[4]) const = 0;
	virtual ~PixelOffsets (void) {}
};

class MultiplePixelOffsets : public PixelOffsets
{
public:
	MultiplePixelOffsets (const IVec2& a,
						  const IVec2& b,
						  const IVec2& c,
						  const IVec2& d)
	{
		m_offsets[0] = a;
		m_offsets[1] = b;
		m_offsets[2] = c;
		m_offsets[3] = d;
	}

	void operator() (const IVec2& /* pixCoord */, IVec2 (&dst)[4]) const
	{
		for (int i = 0; i < DE_LENGTH_OF_ARRAY(dst); i++)
			dst[i] = m_offsets[i];
	}

private:
	IVec2 m_offsets[4];
};

class SinglePixelOffsets : public MultiplePixelOffsets
{
public:
	SinglePixelOffsets (const IVec2& offset)
		: MultiplePixelOffsets(offset + IVec2(0, 1),
							   offset + IVec2(1, 1),
							   offset + IVec2(1, 0),
							   offset + IVec2(0, 0))
	{
	}
};

class DynamicSinglePixelOffsets : public PixelOffsets
{
public:
	DynamicSinglePixelOffsets (const IVec2& offsetRange) : m_offsetRange(offsetRange) {}

	void operator() (const IVec2& pixCoord, IVec2 (&dst)[4]) const
	{
		const int offsetRangeSize = m_offsetRange.y() - m_offsetRange.x() + 1;
		SinglePixelOffsets(tcu::mod(pixCoord.swizzle(1,0), IVec2(offsetRangeSize)) + m_offsetRange.x())(IVec2(), dst);
	}

private:
	IVec2 m_offsetRange;
};

template <typename T>
static inline T triQuadInterpolate (const T (&values)[4], float xFactor, float yFactor)
{
	if (xFactor + yFactor < 1.0f)
		return values[0] + (values[2]-values[0])*xFactor		+ (values[1]-values[0])*yFactor;
	else
		return values[3] + (values[1]-values[3])*(1.0f-xFactor)	+ (values[2]-values[3])*(1.0f-yFactor);
}

template <int N>
static inline void computeTexCoordVecs (const vector<float>& texCoords, tcu::Vector<float, N> (&dst)[4])
{
	DE_ASSERT((int)texCoords.size() == 4*N);
	for (int i = 0; i < 4; i++)
	for (int j = 0; j < N; j++)
		dst[i][j] = texCoords[i*N + j];
}

#if defined(DE_DEBUG)
// Whether offsets correspond to the sample offsets used with plain textureGather().
static inline bool isZeroOffsetOffsets (const IVec2 (&offsets)[4])
{
	IVec2 ref[4];
	SinglePixelOffsets(IVec2(0))(IVec2(), ref);
	return std::equal(DE_ARRAY_BEGIN(offsets),
					  DE_ARRAY_END(offsets),
					  DE_ARRAY_BEGIN(ref));
}
#endif

template <typename ColorScalarType>
static tcu::Vector<ColorScalarType, 4> gatherOffsets (const tcu::Texture2DView& texture, const tcu::Sampler& sampler, const Vec2& coord, int componentNdx, const IVec2 (&offsets)[4])
{
	return texture.gatherOffsets(sampler, coord.x(), coord.y(), componentNdx, offsets).cast<ColorScalarType>();
}

template <typename ColorScalarType>
static tcu::Vector<ColorScalarType, 4> gatherOffsets (const tcu::Texture2DArrayView& texture, const tcu::Sampler& sampler, const Vec3& coord, int componentNdx, const IVec2 (&offsets)[4])
{
	return texture.gatherOffsets(sampler, coord.x(), coord.y(), coord.z(), componentNdx, offsets).cast<ColorScalarType>();
}

template <typename ColorScalarType>
static tcu::Vector<ColorScalarType, 4> gatherOffsets (const tcu::TextureCubeView& texture, const tcu::Sampler& sampler, const Vec3& coord, int componentNdx, const IVec2 (&offsets)[4])
{
	DE_ASSERT(isZeroOffsetOffsets(offsets));
	DE_UNREF(offsets);
	return texture.gather(sampler, coord.x(), coord.y(), coord.z(), componentNdx).cast<ColorScalarType>();
}

static Vec4 gatherOffsetsCompare (const tcu::Texture2DView& texture, const tcu::Sampler& sampler, float refZ, const Vec2& coord, const IVec2 (&offsets)[4])
{
	return texture.gatherOffsetsCompare(sampler, refZ, coord.x(), coord.y(), offsets);
}

static Vec4 gatherOffsetsCompare (const tcu::Texture2DArrayView& texture, const tcu::Sampler& sampler, float refZ, const Vec3& coord, const IVec2 (&offsets)[4])
{
	return texture.gatherOffsetsCompare(sampler, refZ, coord.x(), coord.y(), coord.z(), offsets);
}

static Vec4 gatherOffsetsCompare (const tcu::TextureCubeView& texture, const tcu::Sampler& sampler, float refZ, const Vec3& coord, const IVec2 (&offsets)[4])
{
	DE_ASSERT(isZeroOffsetOffsets(offsets));
	DE_UNREF(offsets);
	return texture.gatherCompare(sampler, refZ, coord.x(), coord.y(), coord.z());
}

template <typename PrecType, typename ColorScalarT>
static bool isGatherOffsetsResultValid (const tcu::TextureCubeView&				texture,
										const tcu::Sampler&						sampler,
										const PrecType&							prec,
										const Vec3&								coord,
										int										componentNdx,
										const IVec2								(&offsets)[4],
										const tcu::Vector<ColorScalarT, 4>&		result)
{
	DE_ASSERT(isZeroOffsetOffsets(offsets));
	DE_UNREF(offsets);
	return tcu::isGatherResultValid(texture, sampler, prec, coord, componentNdx, result);
}

static bool isGatherOffsetsCompareResultValid (const tcu::TextureCubeView&		texture,
											   const tcu::Sampler&				sampler,
											   const tcu::TexComparePrecision&	prec,
											   const Vec3&						coord,
											   const IVec2						(&offsets)[4],
											   float							cmpReference,
											   const Vec4&						result)
{
	DE_ASSERT(isZeroOffsetOffsets(offsets));
	DE_UNREF(offsets);
	return tcu::isGatherCompareResultValid(texture, sampler, prec, coord, cmpReference, result);
}

template <typename ColorScalarType, typename PrecType, typename TexViewT, typename TexCoordT>
static bool verifyGatherOffsets (TestLog&						log,
								 const ConstPixelBufferAccess&	result,
								 const TexViewT&				texture,
								 const TexCoordT				(&texCoords)[4],
								 const tcu::Sampler&			sampler,
								 const PrecType&				lookupPrec,
								 int							componentNdx,
								 const PixelOffsets&			getPixelOffsets)
{
	typedef tcu::Vector<ColorScalarType, 4> ColorVec;

	const int					width			= result.getWidth();
	const int					height			= result.getWidth();
	tcu::TextureLevel			ideal			(result.getFormat(), width, height);
	const PixelBufferAccess		idealAccess		= ideal.getAccess();
	tcu::Surface				errorMask		(width, height);
	bool						success			= true;

	tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());

	for (int py = 0; py < height; py++)
	for (int px = 0; px < width; px++)
	{
		IVec2		offsets[4];
		getPixelOffsets(IVec2(px, py), offsets);

		const Vec2			viewportCoord	= (Vec2((float)px, (float)py) + 0.5f) / Vec2((float)width, (float)height);
		const TexCoordT		texCoord		= triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y());
		const ColorVec		resultPix		= result.getPixelT<ColorScalarType>(px, py);
		const ColorVec		idealPix		= gatherOffsets<ColorScalarType>(texture, sampler, texCoord, componentNdx, offsets);

		idealAccess.setPixel(idealPix, px, py);

		if (tcu::boolAny(tcu::logicalAnd(lookupPrec.colorMask,
										 tcu::greaterThan(tcu::absDiff(resultPix, idealPix),
														  lookupPrec.colorThreshold.template cast<ColorScalarType>()))))
		{
			if (!isGatherOffsetsResultValid(texture, sampler, lookupPrec, texCoord, componentNdx, offsets, resultPix))
			{
				errorMask.setPixel(px, py, tcu::RGBA::red());
				success = false;
			}
		}
	}

	log << TestLog::ImageSet("VerifyResult", "Verification result")
		<< TestLog::Image("Rendered", "Rendered image", result);

	if (!success)
	{
		log << TestLog::Image("Reference", "Ideal reference image", ideal)
			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
	}

	log << TestLog::EndImageSet;

	return success;
}

class PixelCompareRefZ
{
public:
	virtual float operator() (const IVec2& pixCoord) const = 0;
};

class PixelCompareRefZDefault : public PixelCompareRefZ
{
public:
	PixelCompareRefZDefault (const IVec2& renderSize) : m_renderSize(renderSize) {}

	float operator() (const IVec2& pixCoord) const
	{
		return ((float)pixCoord.x() + 0.5f) / (float)m_renderSize.x();
	}

private:
	IVec2 m_renderSize;
};

template <typename TexViewT, typename TexCoordT>
static bool verifyGatherOffsetsCompare (TestLog&							log,
										const ConstPixelBufferAccess&		result,
										const TexViewT&						texture,
										const TexCoordT						(&texCoords)[4],
										const tcu::Sampler&					sampler,
										const tcu::TexComparePrecision&		compPrec,
										const PixelCompareRefZ&				getPixelRefZ,
										const PixelOffsets&					getPixelOffsets)
{
	const int					width			= result.getWidth();
	const int					height			= result.getWidth();
	tcu::Surface				ideal			(width, height);
	const PixelBufferAccess		idealAccess		= ideal.getAccess();
	tcu::Surface				errorMask		(width, height);
	bool						success			= true;

	tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());

	for (int py = 0; py < height; py++)
	for (int px = 0; px < width; px++)
	{
		IVec2		offsets[4];
		getPixelOffsets(IVec2(px, py), offsets);

		const Vec2			viewportCoord	= (Vec2((float)px, (float)py) + 0.5f) / Vec2((float)width, (float)height);
		const TexCoordT		texCoord		= triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y());
		const float			refZ			= getPixelRefZ(IVec2(px, py));
		const Vec4			resultPix		= result.getPixel(px, py);
		const Vec4			idealPix		= gatherOffsetsCompare(texture, sampler, refZ, texCoord, offsets);

		idealAccess.setPixel(idealPix, px, py);

		if (!tcu::boolAll(tcu::equal(resultPix, idealPix)))
		{
			if (!isGatherOffsetsCompareResultValid(texture, sampler, compPrec, texCoord, offsets, refZ, resultPix))
			{
				errorMask.setPixel(px, py, tcu::RGBA::red());
				success = false;
			}
		}
	}

	log << TestLog::ImageSet("VerifyResult", "Verification result")
		<< TestLog::Image("Rendered", "Rendered image", result);

	if (!success)
	{
		log << TestLog::Image("Reference", "Ideal reference image", ideal)
			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
	}

	log << TestLog::EndImageSet;

	return success;
}

enum GatherType
{
	GATHERTYPE_BASIC = 0,
	GATHERTYPE_OFFSET,
	GATHERTYPE_OFFSET_DYNAMIC,
	GATHERTYPE_OFFSETS,

	GATHERTYPE_LAST
};

enum GatherCaseFlags
{
	GATHERCASE_DONT_SAMPLE_CUBE_CORNERS	= (1<<0)	//!< For cube map cases: do not sample cube corners
};

enum OffsetSize
{
	OFFSETSIZE_NONE = 0,
	OFFSETSIZE_MINIMUM_REQUIRED,
	OFFSETSIZE_IMPLEMENTATION_MAXIMUM,

	OFFSETSIZE_LAST
};

static inline const char* gatherTypeName (GatherType type)
{
	switch (type)
	{
		case GATHERTYPE_BASIC:				return "basic";
		case GATHERTYPE_OFFSET:				return "offset";
		case GATHERTYPE_OFFSET_DYNAMIC:		return "offset_dynamic";
		case GATHERTYPE_OFFSETS:			return "offsets";
		default: DE_ASSERT(false); return DE_NULL;
	}
}

static inline const char* gatherTypeDescription (GatherType type)
{
	switch (type)
	{
		case GATHERTYPE_BASIC:				return "textureGather";
		case GATHERTYPE_OFFSET:				return "textureGatherOffset";
		case GATHERTYPE_OFFSET_DYNAMIC:		return "textureGatherOffset with dynamic offsets";
		case GATHERTYPE_OFFSETS:			return "textureGatherOffsets";
		default: DE_ASSERT(false); return DE_NULL;
	}
}

static inline bool requireGpuShader5 (GatherType gatherType, OffsetSize offsetSize)
{
	return gatherType == GATHERTYPE_OFFSET_DYNAMIC || gatherType == GATHERTYPE_OFFSETS
		|| offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM; // \note Implementation limits are not available while generating the shaders, they are passed dynamically at runtime
}

struct GatherArgs
{
	int		componentNdx;	// If negative, implicit component index 0 is used (i.e. the parameter is not given).
	IVec2	offsets[4];		// \note Unless GATHERTYPE_OFFSETS is used, only offsets[0] is relevant; also, for GATHERTYPE_OFFSET_DYNAMIC, none are relevant.

	GatherArgs (void)
		: componentNdx(-1)
	{
		std::fill(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), IVec2());
	}

	GatherArgs (int comp,
				const IVec2& off0 = IVec2(),
				const IVec2& off1 = IVec2(),
				const IVec2& off2 = IVec2(),
				const IVec2& off3 = IVec2())
		: componentNdx(comp)
	{
		offsets[0] = off0;
		offsets[1] = off1;
		offsets[2] = off2;
		offsets[3] = off3;
	}
};

static MovePtr<PixelOffsets> makePixelOffsetsFunctor (GatherType gatherType, const GatherArgs& gatherArgs, const IVec2& offsetRange)
{
	if (gatherType == GATHERTYPE_BASIC || gatherType == GATHERTYPE_OFFSET)
	{
		const IVec2 offset = gatherType == GATHERTYPE_BASIC ? IVec2(0) : gatherArgs.offsets[0];
		return MovePtr<PixelOffsets>(new SinglePixelOffsets(offset));
	}
	else if (gatherType == GATHERTYPE_OFFSET_DYNAMIC)
	{
		return MovePtr<PixelOffsets>(new DynamicSinglePixelOffsets(offsetRange));
	}
	else if (gatherType == GATHERTYPE_OFFSETS)
		return MovePtr<PixelOffsets>(new MultiplePixelOffsets(gatherArgs.offsets[0],
															  gatherArgs.offsets[1],
															  gatherArgs.offsets[2],
															  gatherArgs.offsets[3]));
	else
	{
		DE_ASSERT(false);
		return MovePtr<PixelOffsets>(DE_NULL);
	}
}

static inline glu::DataType getSamplerType (TextureType textureType, const tcu::TextureFormat& format)
{
	if (isDepthFormat(format))
	{
		switch (textureType)
		{
			case TEXTURETYPE_2D:		return glu::TYPE_SAMPLER_2D_SHADOW;
			case TEXTURETYPE_2D_ARRAY:	return glu::TYPE_SAMPLER_2D_ARRAY_SHADOW;
			case TEXTURETYPE_CUBE:		return glu::TYPE_SAMPLER_CUBE_SHADOW;
			default: DE_ASSERT(false); return glu::TYPE_LAST;
		}
	}
	else
	{
		switch (textureType)
		{
			case TEXTURETYPE_2D:		return glu::getSampler2DType(format);
			case TEXTURETYPE_2D_ARRAY:	return glu::getSampler2DArrayType(format);
			case TEXTURETYPE_CUBE:		return glu::getSamplerCubeType(format);
			default: DE_ASSERT(false); return glu::TYPE_LAST;
		}
	}
}

static inline glu::DataType getSamplerGatherResultType (glu::DataType samplerType)
{
	switch (samplerType)
	{
		case glu::TYPE_SAMPLER_2D_SHADOW:
		case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW:
		case glu::TYPE_SAMPLER_CUBE_SHADOW:
		case glu::TYPE_SAMPLER_2D:
		case glu::TYPE_SAMPLER_2D_ARRAY:
		case glu::TYPE_SAMPLER_CUBE:
			return glu::TYPE_FLOAT_VEC4;

		case glu::TYPE_INT_SAMPLER_2D:
		case glu::TYPE_INT_SAMPLER_2D_ARRAY:
		case glu::TYPE_INT_SAMPLER_CUBE:
			return glu::TYPE_INT_VEC4;

		case glu::TYPE_UINT_SAMPLER_2D:
		case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
		case glu::TYPE_UINT_SAMPLER_CUBE:
			return glu::TYPE_UINT_VEC4;

		default:
			DE_ASSERT(false);
			return glu::TYPE_LAST;
	}
}

static inline int getNumTextureSamplingDimensions (TextureType type)
{
	switch (type)
	{
		case TEXTURETYPE_2D:		return 2;
		case TEXTURETYPE_2D_ARRAY:	return 3;
		case TEXTURETYPE_CUBE:		return 3;
		default: DE_ASSERT(false); return -1;
	}
}

enum class LevelMode
{
	NORMAL = 0,
	AMD_BIAS,
	AMD_LOD,
};

vector<GatherArgs> generateBasic2DCaseIterations (GatherType gatherType, LevelMode levelMode, const tcu::TextureFormat& textureFormat, const IVec2& offsetRange)
{
	const int			numComponentCases	= isDepthFormat(textureFormat) ? 1 : 4+1; // \note For non-depth textures, test explicit components 0 to 3 and implicit component 0.
	const bool			skipImplicitCase	= (levelMode == LevelMode::AMD_BIAS);
	vector<GatherArgs>	result;

	for (int componentCaseNdx = (skipImplicitCase ? 1 : 0); componentCaseNdx < numComponentCases; componentCaseNdx++)
	{
		const int componentNdx = componentCaseNdx - 1;

		switch (gatherType)
		{
			case GATHERTYPE_BASIC:
				result.push_back(GatherArgs(componentNdx));
				break;

			case GATHERTYPE_OFFSET:
			{
				const int min	= offsetRange.x();
				const int max	= offsetRange.y();
				const int hmin	= divRoundToZero(min, 2);
				const int hmax	= divRoundToZero(max, 2);

				result.push_back(GatherArgs(componentNdx, IVec2(min, max)));

				if (componentCaseNdx == 0) // Don't test all offsets variants for all color components (they should be pretty orthogonal).
				{
					result.push_back(GatherArgs(componentNdx, IVec2(min,	min)));
					result.push_back(GatherArgs(componentNdx, IVec2(max,	min)));
					result.push_back(GatherArgs(componentNdx, IVec2(max,	max)));

					result.push_back(GatherArgs(componentNdx, IVec2(0,		hmax)));
					result.push_back(GatherArgs(componentNdx, IVec2(hmin,	0)));
					result.push_back(GatherArgs(componentNdx, IVec2(0,		0)));
				}

				break;
			}

			case GATHERTYPE_OFFSET_DYNAMIC:
				result.push_back(GatherArgs(componentNdx));
				break;

			case GATHERTYPE_OFFSETS:
			{
				const int min	= offsetRange.x();
				const int max	= offsetRange.y();
				const int hmin	= divRoundToZero(min, 2);
				const int hmax	= divRoundToZero(max, 2);

				result.push_back(GatherArgs(componentNdx,
											IVec2(min,	min),
											IVec2(min,	max),
											IVec2(max,	min),
											IVec2(max,	max)));

				if (componentCaseNdx == 0) // Don't test all offsets variants for all color components (they should be pretty orthogonal).
					result.push_back(GatherArgs(componentNdx,
												IVec2(min,	hmax),
												IVec2(hmin,	max),
												IVec2(0,	hmax),
												IVec2(hmax,	0)));
				break;
			}

			default:
				DE_ASSERT(false);
		}
	}

	return result;
}

struct GatherCaseBaseParams
{
	GatherType					gatherType;
	OffsetSize					offsetSize;
	tcu::TextureFormat			textureFormat;
	tcu::Sampler::CompareMode	shadowCompareMode;
	tcu::Sampler::WrapMode		wrapS;
	tcu::Sampler::WrapMode		wrapT;
	MaybeTextureSwizzle			textureSwizzle;
	tcu::Sampler::FilterMode	minFilter;
	tcu::Sampler::FilterMode	magFilter;
	LevelMode					levelMode;
	int							baseLevel;
	deUint32					flags;
	TextureType					textureType;
	ImageBackingMode			sparseCase;

	GatherCaseBaseParams (const TextureType					textureType_,
						  const GatherType					gatherType_,
						  const OffsetSize					offsetSize_,
						  const tcu::TextureFormat			textureFormat_,
						  const tcu::Sampler::CompareMode	shadowCompareMode_,
						  const tcu::Sampler::WrapMode		wrapS_,
						  const tcu::Sampler::WrapMode		wrapT_,
						  const MaybeTextureSwizzle&		textureSwizzle_,
						  const tcu::Sampler::FilterMode	minFilter_,
						  const tcu::Sampler::FilterMode	magFilter_,
						  const LevelMode					levelMode_,
						  const int							baseLevel_,
						  const deUint32					flags_,
						  const ImageBackingMode			sparseCase_)
		: gatherType			(gatherType_)
		, offsetSize			(offsetSize_)
		, textureFormat			(textureFormat_)
		, shadowCompareMode		(shadowCompareMode_)
		, wrapS					(wrapS_)
		, wrapT					(wrapT_)
		, textureSwizzle		(textureSwizzle_)
		, minFilter				(minFilter_)
		, magFilter				(magFilter_)
		, levelMode				(levelMode_)
		, baseLevel				(baseLevel_)
		, flags					(flags_)
		, textureType			(textureType_)
		, sparseCase			(sparseCase_)
	{}

	GatherCaseBaseParams (void)
		: gatherType			(GATHERTYPE_LAST)
		, offsetSize			(OFFSETSIZE_LAST)
		, textureFormat			()
		, shadowCompareMode		(tcu::Sampler::COMPAREMODE_LAST)
		, wrapS					(tcu::Sampler::WRAPMODE_LAST)
		, wrapT					(tcu::Sampler::WRAPMODE_LAST)
		, textureSwizzle		(MaybeTextureSwizzle::createNoneTextureSwizzle())
		, minFilter				(tcu::Sampler::FILTERMODE_LAST)
		, magFilter				(tcu::Sampler::FILTERMODE_LAST)
		, levelMode				(LevelMode::NORMAL)
		, baseLevel				(0)
		, flags					(0)
		, textureType			(TEXTURETYPE_LAST)
		, sparseCase			(ShaderRenderCaseInstance::IMAGE_BACKING_MODE_REGULAR)
	{}
};

IVec2 getOffsetRange (const OffsetSize offsetSize, const vk::VkPhysicalDeviceLimits& deviceLimits)
{
	switch (offsetSize)
	{
		case OFFSETSIZE_NONE:
			return IVec2(0);

		case OFFSETSIZE_MINIMUM_REQUIRED:
			// \note Defined by spec.
			return IVec2(SPEC_MAX_MIN_OFFSET,
						 SPEC_MIN_MAX_OFFSET);

		case OFFSETSIZE_IMPLEMENTATION_MAXIMUM:
			return IVec2(deviceLimits.minTexelGatherOffset, deviceLimits.maxTexelGatherOffset);

		default:
			DE_ASSERT(false);
			return IVec2(-1);
	}
}

IVec2 getOffsetRange (const OffsetSize offsetSize)
{
	switch (offsetSize)
	{
		case OFFSETSIZE_NONE:
			return IVec2(0);

		case OFFSETSIZE_MINIMUM_REQUIRED:
			// \note Defined by spec.
			return IVec2(SPEC_MAX_MIN_OFFSET,
						 SPEC_MIN_MAX_OFFSET);

		case OFFSETSIZE_IMPLEMENTATION_MAXIMUM:
			DE_FATAL("Not known");
			return IVec2(-1);

		default:
			DE_ASSERT(false);
			return IVec2(-1);
	}
}

class TextureGatherInstance : public ShaderRenderCaseInstance
{
public:
										TextureGatherInstance		(Context&						context,
																	 const GatherCaseBaseParams&	baseParams);
	virtual								~TextureGatherInstance		(void);

	virtual tcu::TestStatus				iterate						(void);

protected:
	void								init						(void);

	virtual int							getNumIterations			(void) const = 0;
	virtual GatherArgs					getGatherArgs				(int iterationNdx) const = 0;

	virtual void						setupDefaultInputs			(void);
	virtual void						setupUniforms				(const tcu::Vec4&);

	template <typename TexViewT, typename TexCoordT>
	bool								verify						(const ConstPixelBufferAccess&		rendered,
																	 const TexViewT&					texture,
																	 const TexCoordT					(&bottomLeft)[4],
																	 const GatherArgs&					gatherArgs) const;

	virtual TextureBindingSp			createTexture				(void) = 0;
	virtual vector<float>				computeQuadTexCoord			(int iterationNdx) const = 0;
	virtual bool						verify						(int iterationNdx, const ConstPixelBufferAccess& rendered) const = 0;

protected:
	static const IVec2					RENDER_SIZE;

	const GatherCaseBaseParams			m_baseParams;

private:
	const tcu::TextureFormat			m_colorBufferFormat;
	int									m_currentIteration;
};

const IVec2 TextureGatherInstance::RENDER_SIZE = IVec2(64, 64);

TextureGatherInstance::TextureGatherInstance (Context&						context,
											  const GatherCaseBaseParams&	baseParams)
	: ShaderRenderCaseInstance	(context, false, DE_NULL, DE_NULL, DE_NULL, baseParams.sparseCase)
	, m_baseParams				(baseParams)
	, m_colorBufferFormat		(tcu::TextureFormat(tcu::TextureFormat::RGBA,
													isDepthFormat(baseParams.textureFormat) ? tcu::TextureFormat::UNORM_INT8 : baseParams.textureFormat.type))
	, m_currentIteration		(0)
{
	DE_ASSERT((m_baseParams.gatherType == GATHERTYPE_BASIC) == (m_baseParams.offsetSize == OFFSETSIZE_NONE));
	DE_ASSERT((m_baseParams.shadowCompareMode != tcu::Sampler::COMPAREMODE_NONE) == isDepthFormat(m_baseParams.textureFormat));
	DE_ASSERT(isUnormFormatType(m_colorBufferFormat.type)						||
			  m_colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT8		||
			  m_colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT16	||
			  m_colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT8		||
			  m_colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT16);
	DE_ASSERT(glu::isGLInternalColorFormatFilterable(glu::getInternalFormat(m_colorBufferFormat)) ||
			  (m_baseParams.magFilter == tcu::Sampler::NEAREST && (m_baseParams.minFilter == tcu::Sampler::NEAREST || m_baseParams.minFilter == tcu::Sampler::NEAREST_MIPMAP_NEAREST)));
	DE_ASSERT(m_baseParams.textureType == TEXTURETYPE_CUBE || !(m_baseParams.flags & GATHERCASE_DONT_SAMPLE_CUBE_CORNERS));

	m_renderSize				= RENDER_SIZE.asUint();
	m_colorFormat				= vk::mapTextureFormat(m_colorBufferFormat);
}

TextureGatherInstance::~TextureGatherInstance (void)
{
}

void TextureGatherInstance::init (void)
{
	TestLog&						log					= m_context.getTestContext().getLog();
	TextureBindingSp				textureBinding;
	TextureBinding::Parameters		textureParams;

	// Check prerequisites.
	if (requireGpuShader5(m_baseParams.gatherType, m_baseParams.offsetSize))
	{
		const vk::VkPhysicalDeviceFeatures&		deviceFeatures	= m_context.getDeviceFeatures();
		if (!deviceFeatures.shaderImageGatherExtended)
			TCU_THROW(NotSupportedError, "Extended set of image gather instructions are not supported");
	}

	// Check general extension support.
	if (m_baseParams.levelMode != LevelMode::NORMAL)
	{
		m_context.requireDeviceFunctionality("VK_AMD_texture_gather_bias_lod");
	}

	// Log and check implementation offset limits, if appropriate.
	if (m_baseParams.offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
	{
		const IVec2		offsetRange		= getOffsetRange(m_baseParams.offsetSize, m_context.getDeviceProperties().limits);
		log << TestLog::Integer("ImplementationMinTextureGatherOffset", "Implementation's value for minTexelGatherOffset", "", QP_KEY_TAG_NONE, offsetRange[0])
			<< TestLog::Integer("ImplementationMaxTextureGatherOffset", "Implementation's value for maxTexelGatherOffset", "", QP_KEY_TAG_NONE, offsetRange[1]);
		TCU_CHECK_MSG(offsetRange[0] <= SPEC_MAX_MIN_OFFSET, ("minTexelGatherOffset must be at most " + de::toString((int)SPEC_MAX_MIN_OFFSET)).c_str());
		TCU_CHECK_MSG(offsetRange[1] >= SPEC_MIN_MAX_OFFSET, ("maxTexelGatherOffset must be at least " + de::toString((int)SPEC_MIN_MAX_OFFSET)).c_str());
	}

	// Initialize texture.
	textureBinding = createTexture();

	// Check image format support.
	// This should happen earlier but it's easier to retrieve texture parameters once created and this is not expected to fail.
	if (m_baseParams.levelMode != LevelMode::NORMAL)
	{
		const auto						format				= vk::mapTextureFormat(m_baseParams.textureFormat);
		const auto						bindingType			= textureBinding->getType();
		const auto						imageViewType		= textureTypeToImageViewType(bindingType);
		const auto						imageType			= viewTypeToImageType(imageViewType);
		const vk::VkImageUsageFlags		usageFlags			= textureUsageFlags();
		const vk::VkImageCreateFlags	imageCreateFlags	= textureCreateFlags(imageViewType, m_baseParams.sparseCase);

		const vk::VkPhysicalDeviceImageFormatInfo2 formatInfo =
		{
			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,	//	VkStructureType		sType;
			nullptr,													//	const void*			pNext;
			format,														//	VkFormat			format;
			imageType,													//	VkImageType			type;
			vk::VK_IMAGE_TILING_OPTIMAL,								//	VkImageTiling		tiling;
			usageFlags,													//	VkImageUsageFlags	usage;
			imageCreateFlags,											//	VkImageCreateFlags	flags;
		};

		vk::VkTextureLODGatherFormatPropertiesAMD lodGatherProperties =
		{
			vk::VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD,	//	VkStructureType	sType;
			nullptr,														//	void*			pNext;
			VK_FALSE,														//	VkBool32		supportsTextureGatherLODBiasAMD;
		};

		vk::VkImageFormatProperties2 properties2 = vk::initVulkanStructure();
		properties2.pNext = &lodGatherProperties;

		const auto retCode = m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(m_context.getPhysicalDevice(), &formatInfo, &properties2);

		if (retCode != vk::VK_SUCCESS && retCode != vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
			TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties2 returned " + de::toString(retCode));

		if (retCode == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
			TCU_THROW(NotSupportedError, "Format does not support the required parameters");

		if (!lodGatherProperties.supportsTextureGatherLODBiasAMD)
			TCU_THROW(NotSupportedError, "Format does not support texture gather LOD/Bias operations");
	}

	if (m_baseParams.textureSwizzle.isSome())
	{
		const tcu::Vector<TextureSwizzleComponent, 4>&	swizzle		= m_baseParams.textureSwizzle.getSwizzle();

		const vk::VkComponentMapping					components	=
		{
			getTextureSwizzleComponent(swizzle[0]),
			getTextureSwizzleComponent(swizzle[1]),
			getTextureSwizzleComponent(swizzle[2]),
			getTextureSwizzleComponent(swizzle[3])
		};

		textureParams.componentMapping = components;
	}

	// Set base mip level and mode.
	if (m_baseParams.levelMode == LevelMode::NORMAL)
	{
		textureParams.baseMipLevel = m_baseParams.baseLevel;
	}
	else
	{
		const auto	textureType	= textureBinding->getType();
		int			levels		= 0;

		switch (textureType)
		{
		case TextureBinding::TYPE_1D:			levels = textureBinding->get1D().getNumLevels();		break;
		case TextureBinding::TYPE_2D:			levels = textureBinding->get2D().getNumLevels();		break;
		case TextureBinding::TYPE_3D:			levels = textureBinding->get3D().getNumLevels();		break;
		case TextureBinding::TYPE_CUBE_MAP:		levels = textureBinding->getCube().getNumLevels();		break;
		case TextureBinding::TYPE_1D_ARRAY:		levels = textureBinding->get1DArray().getNumLevels();	break;
		case TextureBinding::TYPE_2D_ARRAY:		levels = textureBinding->get2DArray().getNumLevels();	break;
		case TextureBinding::TYPE_CUBE_ARRAY:	levels = textureBinding->getCubeArray().getNumLevels();	break;
		default:
			DE_ASSERT(false); break;
		}

		DE_ASSERT(levels > 0);
		textureParams.minMaxLod = tcu::just(TextureBinding::MinMaxLod(0.0f, static_cast<float>(levels - 1)));
	}

	textureBinding->setParameters(textureParams);
	m_textures.push_back(textureBinding);

	log << TestLog::Message << "Texture base level is " << textureParams.baseMipLevel << TestLog::EndMessage
		<< TestLog::Message << "s and t wrap modes are "
							<< vk::mapWrapMode(m_baseParams.wrapS) << " and "
							<< vk::mapWrapMode(m_baseParams.wrapT) << ", respectively" << TestLog::EndMessage
		<< TestLog::Message << "Minification and magnification filter modes are "
							<< vk::mapFilterMode(m_baseParams.minFilter) << " and "
							<< vk::mapFilterMode(m_baseParams.magFilter) << ", respectively "
							<< "(note that they should have no effect on gather result)"
							<< TestLog::EndMessage
		<< TestLog::Message << "Using texture swizzle " << m_baseParams.textureSwizzle << TestLog::EndMessage;

	if (m_baseParams.shadowCompareMode != tcu::Sampler::COMPAREMODE_NONE)
		log << TestLog::Message << "Using texture compare func " << vk::mapCompareMode(m_baseParams.shadowCompareMode) << TestLog::EndMessage;
}

void TextureGatherInstance::setupDefaultInputs (void)
{
	const int				numVertices						= 4;
	const float				position[4*2]					=
	{
		-1.0f, -1.0f,
		-1.0f, +1.0f,
		+1.0f, -1.0f,
		+1.0f, +1.0f,
	};
	const float				normalizedCoord[4*2]			=
	{
		0.0f, 0.0f,
		0.0f, 1.0f,
		1.0f, 0.0f,
		1.0f, 1.0f,
	};
	const vector<float>		texCoord						= computeQuadTexCoord(m_currentIteration);
	const bool				needNormalizedCoordInShader		= m_baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC || isDepthFormat(m_baseParams.textureFormat);

	addAttribute(0u, vk::VK_FORMAT_R32G32_SFLOAT, 2 * (deUint32)sizeof(float), numVertices, position);

	if (texCoord.size() == 2*4)
		addAttribute(1u, vk::VK_FORMAT_R32G32_SFLOAT, 2 * (deUint32)sizeof(float), numVertices, texCoord.data());
	else if (texCoord.size() == 3*4)
		addAttribute(1u, vk::VK_FORMAT_R32G32B32_SFLOAT, 3 * (deUint32)sizeof(float), numVertices, texCoord.data());
	else
		DE_ASSERT(false);

	if (needNormalizedCoordInShader)
		addAttribute(2u, vk::VK_FORMAT_R32G32_SFLOAT, 2 * (deUint32)sizeof(float), numVertices, normalizedCoord);
}

tcu::TestStatus TextureGatherInstance::iterate (void)
{
	TestLog&						log						= m_context.getTestContext().getLog();
	const tcu::ScopedLogSection		iterationSection		(log, "Iteration" + de::toString(m_currentIteration), "Iteration " + de::toString(m_currentIteration));

	// Render.

	{
		const deUint32				numVertices		= 4;
		const deUint32				numTriangles	= 2;
		const deUint16				indices[6]		= { 0, 1, 2, 2, 1, 3 };
		const vector<float>			texCoord		= computeQuadTexCoord(m_currentIteration);

		if (texCoord.size() == 2*4)
		{
			Vec2 texCoordVec[4];
			computeTexCoordVecs(texCoord, texCoordVec);
			log << TestLog::Message << "Texture coordinates run from " << texCoordVec[0] << " to " << texCoordVec[3] << TestLog::EndMessage;
		}
		else if (texCoord.size() == 3*4)
		{
			Vec3 texCoordVec[4];
			computeTexCoordVecs(texCoord, texCoordVec);
			log << TestLog::Message << "Texture coordinates run from " << texCoordVec[0] << " to " << texCoordVec[3] << TestLog::EndMessage;
		}
		else
			DE_ASSERT(false);

		m_vertexShaderName		= "vert";
		m_fragmentShaderName	= "frag_" + de::toString(m_currentIteration);

		setup();

		render(numVertices, numTriangles, indices);
	}

	// Verify result.

	if (!verify(m_currentIteration, getResultImage().getAccess()))
		return tcu::TestStatus::fail("Result verification failed");

	m_currentIteration++;
	if (m_currentIteration == getNumIterations())
		return tcu::TestStatus::pass("Pass");
	else
		return tcu::TestStatus::incomplete();
}

void TextureGatherInstance::setupUniforms (const tcu::Vec4&)
{
	deUint32	binding		= 0;

	useSampler(binding++, 0u);

	if (m_baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC)
		addUniform(binding++, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::Vec2), RENDER_SIZE.asFloat().getPtr());

	if (m_baseParams.offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
	{
		if (m_baseParams.gatherType == GATHERTYPE_OFFSET)
		{
			const GatherArgs&	gatherArgs		= getGatherArgs(m_currentIteration);
			addUniform(binding++, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::IVec2), gatherArgs.offsets[0].getPtr());
		}
		else if (m_baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC)
		{
			const IVec2&		offsetRange		= getOffsetRange(m_baseParams.offsetSize, m_context.getDeviceProperties().limits);
			addUniform(binding++, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::IVec2), offsetRange.getPtr());
		}
		else
			DE_ASSERT(false);
	}
}

template <typename TexViewT, typename TexCoordT>
bool TextureGatherInstance::verify (const ConstPixelBufferAccess&	rendered,
								const TexViewT&					texture,
								const TexCoordT					(&texCoords)[4],
								const GatherArgs&				gatherArgs) const
{
	TestLog& log = m_context.getTestContext().getLog();

	{
		DE_ASSERT(m_colorBufferFormat.order == tcu::TextureFormat::RGBA);
		DE_ASSERT(m_colorBufferFormat.type == tcu::TextureFormat::UNORM_INT8		||
				  m_colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT8		||
				  m_colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT8);

		const MovePtr<PixelOffsets>		pixelOffsets	= makePixelOffsetsFunctor(m_baseParams.gatherType, gatherArgs, getOffsetRange(m_baseParams.offsetSize, m_context.getDeviceProperties().limits));
		const tcu::PixelFormat			pixelFormat		= tcu::PixelFormat(8,8,8,8);
		const IVec4						colorBits		= tcu::max(TextureTestUtil::getBitsVec(pixelFormat) - 1, tcu::IVec4(0));
		const IVec3						coordBits		= m_baseParams.textureType == TEXTURETYPE_2D			? IVec3(20,20,0)
														: m_baseParams.textureType == TEXTURETYPE_CUBE			? IVec3(10,10,10)
														: m_baseParams.textureType == TEXTURETYPE_2D_ARRAY		? IVec3(20,20,20)
														: IVec3(-1);
		const IVec3						uvwBits			= m_baseParams.textureType == TEXTURETYPE_2D			? IVec3(7,7,0)
														: m_baseParams.textureType == TEXTURETYPE_CUBE			? IVec3(6,6,0)
														: m_baseParams.textureType == TEXTURETYPE_2D_ARRAY		? IVec3(7,7,7)
														: IVec3(-1);
		tcu::Sampler					sampler;
		sampler.wrapS		= m_baseParams.wrapS;
		sampler.wrapT		= m_baseParams.wrapT;
		sampler.compare		= m_baseParams.shadowCompareMode;

		if (isDepthFormat(m_baseParams.textureFormat))
		{
			tcu::TexComparePrecision comparePrec;
			comparePrec.coordBits		= coordBits;
			comparePrec.uvwBits			= uvwBits;
			comparePrec.referenceBits	= 16;
			comparePrec.resultBits		= pixelFormat.redBits-1;

			return verifyGatherOffsetsCompare(log, rendered, texture, texCoords, sampler, comparePrec, PixelCompareRefZDefault(RENDER_SIZE), *pixelOffsets);
		}
		else
		{
			const int componentNdx = de::max(0, gatherArgs.componentNdx);

			if (isUnormFormatType(m_baseParams.textureFormat.type))
			{
				tcu::LookupPrecision lookupPrec;
				lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(colorBits);
				lookupPrec.coordBits		= coordBits;
				lookupPrec.uvwBits			= uvwBits;
				lookupPrec.colorMask		= TextureTestUtil::getCompareMask(pixelFormat);
				return verifyGatherOffsets<float>(log, rendered, texture, texCoords, sampler, lookupPrec, componentNdx, *pixelOffsets);
			}
			else if (isUIntFormatType(m_baseParams.textureFormat.type) || isSIntFormatType(m_baseParams.textureFormat.type))
			{
				tcu::IntLookupPrecision		lookupPrec;
				lookupPrec.colorThreshold	= UVec4(0);
				lookupPrec.coordBits		= coordBits;
				lookupPrec.uvwBits			= uvwBits;
				lookupPrec.colorMask		= TextureTestUtil::getCompareMask(pixelFormat);

				if (isUIntFormatType(m_baseParams.textureFormat.type))
					return verifyGatherOffsets<deUint32>(log, rendered, texture, texCoords, sampler, lookupPrec, componentNdx, *pixelOffsets);
				else if (isSIntFormatType(m_baseParams.textureFormat.type))
					return verifyGatherOffsets<deInt32>(log, rendered, texture, texCoords, sampler, lookupPrec, componentNdx, *pixelOffsets);
				else
				{
					DE_ASSERT(false);
					return false;
				}
			}
			else
			{
				DE_ASSERT(false);
				return false;
			}
		}
	}
}

glu::VertexSource genVertexShaderSource (bool requireGpuShader5, int numTexCoordComponents, bool useNormalizedCoordInput)
{
	DE_ASSERT(numTexCoordComponents == 2 || numTexCoordComponents == 3);

	const string		texCoordType	= "vec" + de::toString(numTexCoordComponents);
	std::ostringstream	vert;

	vert << "#version 310 es\n";

	if (requireGpuShader5)
		vert << "#extension GL_EXT_gpu_shader5 : require\n";

	vert << "\n"
			"layout (location = 0) in highp vec2 a_position;\n"
			"layout (location = 1) in highp " << texCoordType << " a_texCoord;\n";

	if (useNormalizedCoordInput)
		vert << "layout (location = 2) in highp vec2 a_normalizedCoord; // (0,0) to (1,1)\n";

	vert << "\n"
			"layout (location = 0) out highp " << texCoordType << " v_texCoord;\n";

	if (useNormalizedCoordInput)
		vert << "layout (location = 1) out highp vec2 v_normalizedCoord;\n";

	vert << "\n"
			"void main (void)\n"
			"{\n"
			"	gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0);\n"
			"	v_texCoord = a_texCoord;\n";

	if (useNormalizedCoordInput)
		vert << "	v_normalizedCoord = a_normalizedCoord;\n";

	vert << "}\n";

	return glu::VertexSource(vert.str());
}

glu::FragmentSource genFragmentShaderSource (bool					requireGpuShader5,
											 int					numTexCoordComponents,
											 glu::DataType			samplerType,
											 const string&			funcCall,
											 bool					useNormalizedCoordInput,
											 bool					usePixCoord,
											 OffsetSize				offsetSize,
											 const ImageBackingMode	sparseCase,
											 LevelMode				levelMode)
{
	DE_ASSERT(glu::isDataTypeSampler(samplerType));
	DE_ASSERT(de::inRange(numTexCoordComponents, 2, 3));
	DE_ASSERT(!usePixCoord || useNormalizedCoordInput);

	const string		texCoordType	= "vec" + de::toString(numTexCoordComponents);
	deUint32			binding			= 0;
	std::ostringstream	frag;
	const string		outType			= glu::getDataTypeName(getSamplerGatherResultType(samplerType));

	frag << "#version 450\n";

	if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
		frag << "#extension GL_ARB_sparse_texture2 : require\n";

	if (levelMode != LevelMode::NORMAL)
		frag << "#extension GL_AMD_texture_gather_bias_lod : require\n";

	if (requireGpuShader5)
		frag << "#extension GL_EXT_gpu_shader5 : require\n";

	frag << "\n"
			"layout (location = 0) out mediump " << outType << " o_color;\n"
			"\n"
			"layout (location = 0) in highp " << texCoordType << " v_texCoord;\n";

	if (useNormalizedCoordInput)
		frag << "layout (location = 1) in highp vec2 v_normalizedCoord;\n";

	frag << "\n"
			"layout (binding = " << binding++ << ") uniform highp " << glu::getDataTypeName(samplerType) << " u_sampler;\n";

	if (usePixCoord)
		frag << "layout (binding = " << binding++ << ") uniform viewportSize { highp vec2 u_viewportSize; };\n";

	if (offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
		frag << "layout (binding = " << binding++ << ") uniform offset { highp ivec2 u_offset; };\n";

	frag << "\n"
			"void main(void)\n"
			"{\n";

	if (usePixCoord)
		frag << "	ivec2 pixCoord = ivec2(v_normalizedCoord*u_viewportSize);\n";

	if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
	{
		// Texel declaration
		frag << "\t" << outType << " texel;\n";
		frag << "\tint success = " << funcCall << ";\n";

		// Check sparse validity, and handle each case
		frag << "\tif (sparseTexelsResidentARB(success))\n"
			 << "\t\to_color = texel;\n"
			 <<	"\telse\n"
			 << "\t\to_color = " << outType << "(0.0, 0.0, 0.0, 1.0);\n";
	}
	else
	{
		frag << "\t\to_color = " << funcCall << ";\n";
	}

	frag << "}\n";

	return glu::FragmentSource(frag.str());
}

string genGatherFuncCall (GatherType				gatherType,
						  const tcu::TextureFormat&	textureFormat,
						  const GatherArgs&			gatherArgs,
						  LevelMode					levelMode,
						  deUint32					baseLevel,
						  const string&				refZExpr,
						  const IVec2&				offsetRange,
						  int						indentationDepth,
						  OffsetSize				offsetSize,
						  const ImageBackingMode	sparseCase)
{
	string result;
	string levelStr;

	if (levelMode != LevelMode::NORMAL)
	{
		levelStr = de::toString(baseLevel) + ".0";
	}

	if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
	{
		if (levelMode == LevelMode::NORMAL || levelMode == LevelMode::AMD_BIAS)
		{
			switch (gatherType)
			{
				case GATHERTYPE_BASIC:
					result += "sparseTextureGatherARB";
					break;
				case GATHERTYPE_OFFSET: // \note Fallthrough.
				case GATHERTYPE_OFFSET_DYNAMIC:
					result += "sparseTextureGatherOffsetARB";
					break;
				case GATHERTYPE_OFFSETS:
					result += "sparseTextureGatherOffsetsARB";
					break;
				default:
					DE_ASSERT(false);
			}
		}
		else // LevelMode::AMD_LOD
		{
			switch (gatherType)
			{
				case GATHERTYPE_BASIC:
					result += "sparseTextureGatherLodAMD";
					break;
				case GATHERTYPE_OFFSET: // \note Fallthrough.
				case GATHERTYPE_OFFSET_DYNAMIC:
					result += "sparseTextureGatherLodOffsetAMD";
					break;
				case GATHERTYPE_OFFSETS:
					result += "sparseTextureGatherLodOffsetsAMD";
					break;
				default:
					DE_ASSERT(false);
			}
		}
	}
	else
	{
		if (levelMode == LevelMode::NORMAL || levelMode == LevelMode::AMD_BIAS)
		{
			switch (gatherType)
			{
				case GATHERTYPE_BASIC:
					result += "textureGather";
					break;
				case GATHERTYPE_OFFSET: // \note Fallthrough.
				case GATHERTYPE_OFFSET_DYNAMIC:
					result += "textureGatherOffset";
					break;
				case GATHERTYPE_OFFSETS:
					result += "textureGatherOffsets";
					break;
				default:
					DE_ASSERT(false);
			}
		}
		else // LevelMode::AMD_LOD
		{
			switch (gatherType)
			{
				case GATHERTYPE_BASIC:
					result += "textureGatherLodAMD";
					break;
				case GATHERTYPE_OFFSET: // \note Fallthrough.
				case GATHERTYPE_OFFSET_DYNAMIC:
					result += "textureGatherLodOffsetAMD";
					break;
				case GATHERTYPE_OFFSETS:
					result += "textureGatherLodOffsetsAMD";
					break;
				default:
					DE_ASSERT(false);
			}
		}
	}

	result += "(u_sampler, v_texCoord";

	if (isDepthFormat(textureFormat))
	{
		DE_ASSERT(gatherArgs.componentNdx < 0);
		result += ", " + refZExpr;
	}

	if (levelMode == LevelMode::AMD_LOD)
	{
		result += ", " + levelStr;
	}

	if (gatherType == GATHERTYPE_OFFSET ||
		gatherType == GATHERTYPE_OFFSET_DYNAMIC ||
		gatherType == GATHERTYPE_OFFSETS)
	{
		result += ", ";
		switch (gatherType)
		{
			case GATHERTYPE_OFFSET:
				if (offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
					result += "u_offset";
				else
					result += "ivec2" + de::toString(gatherArgs.offsets[0]);
				break;

			case GATHERTYPE_OFFSET_DYNAMIC:
				if (offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
					result += "pixCoord.yx % ivec2(u_offset.y - u_offset.x + 1) + u_offset.x";
				else
					result += "pixCoord.yx % ivec2(" + de::toString(offsetRange.y() - offsetRange.x() + 1) + ") + " + de::toString(offsetRange.x());
				break;

			case GATHERTYPE_OFFSETS:
				DE_ASSERT(offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM);
				result += "ivec2[4](\n"
						  + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[0]) + ",\n"
						  + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[1]) + ",\n"
						  + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[2]) + ",\n"
						  + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[3]) + ")\n"
						  + string(indentationDepth, '\t') + "\t";
				break;

			default:
				DE_ASSERT(false);
		}
	}

	if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
		result += ", texel";

	if (gatherArgs.componentNdx >= 0)
	{
		DE_ASSERT(gatherArgs.componentNdx < 4);
		result += ", " + de::toString(gatherArgs.componentNdx);
	}

	if (levelMode == LevelMode::AMD_BIAS)
	{
		result += ", " + levelStr;
	}

	result += ")";

	return result;
}

// \todo [2016-07-08 pyry] Re-use programs if sources are identical

void genGatherPrograms (vk::SourceCollections& programCollection, const GatherCaseBaseParams& baseParams, const vector<GatherArgs>& iterations)
{
	const int					numIterations		= (int)iterations.size();
	const string				refZExpr			= "v_normalizedCoord.x";
	const IVec2&				offsetRange			= baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(baseParams.offsetSize) : IVec2(0);
	const bool					usePixCoord			= baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC;
	const bool					useNormalizedCoord	= usePixCoord || isDepthFormat(baseParams.textureFormat);
	const bool					isDynamicOffset		= baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC;
	const bool					isShadow			= isDepthFormat(baseParams.textureFormat);
	const glu::DataType			samplerType			= getSamplerType(baseParams.textureType, baseParams.textureFormat);
	const int					numDims				= getNumTextureSamplingDimensions(baseParams.textureType);
	glu::VertexSource			vert				= genVertexShaderSource(requireGpuShader5(baseParams.gatherType, baseParams.offsetSize), numDims, isDynamicOffset || isShadow);

	// Check sampler type is valid.
	if (baseParams.levelMode != LevelMode::NORMAL)
	{
		std::vector<glu::DataType> validSamplerTypes =
		{
			glu::TYPE_SAMPLER_2D,
			glu::TYPE_SAMPLER_2D_ARRAY,
			glu::TYPE_INT_SAMPLER_2D,
			glu::TYPE_INT_SAMPLER_2D_ARRAY,
			glu::TYPE_UINT_SAMPLER_2D,
			glu::TYPE_UINT_SAMPLER_2D_ARRAY,
		};

		if (baseParams.gatherType == GATHERTYPE_BASIC)
		{
			static const std::vector<glu::DataType> kAdditionalTypes =
			{
				glu::TYPE_SAMPLER_CUBE,
				glu::TYPE_SAMPLER_CUBE_ARRAY,
				glu::TYPE_INT_SAMPLER_CUBE,
				glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
				glu::TYPE_UINT_SAMPLER_CUBE,
				glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
			};

			std::copy(begin(kAdditionalTypes), end(kAdditionalTypes), std::back_inserter(validSamplerTypes));
		}

		const auto itr = std::find(begin(validSamplerTypes), end(validSamplerTypes), samplerType);
		DE_ASSERT(itr != end(validSamplerTypes));
		DE_UNREF(itr); // For release builds.
	}

	programCollection.glslSources.add("vert") << vert;

	for (int iterNdx = 0; iterNdx < numIterations; iterNdx++)
	{
		const GatherArgs&		gatherArgs			= iterations[iterNdx];
		const string			funcCall			= genGatherFuncCall(baseParams.gatherType, baseParams.textureFormat, gatherArgs, baseParams.levelMode, baseParams.baseLevel, refZExpr, offsetRange, 1, baseParams.offsetSize, baseParams.sparseCase);
		glu::FragmentSource		frag				= genFragmentShaderSource(requireGpuShader5(baseParams.gatherType, baseParams.offsetSize), numDims, samplerType, funcCall, useNormalizedCoord, usePixCoord, baseParams.offsetSize, baseParams.sparseCase, baseParams.levelMode);

		programCollection.glslSources.add("frag_" + de::toString(iterNdx)) << frag;
	}
}

// 2D

class TextureGather2DInstance : public TextureGatherInstance
{
public:
									TextureGather2DInstance				(Context&						context,
																		 const GatherCaseBaseParams&	baseParams,
																		 const IVec2&					textureSize,
																		 const vector<GatherArgs>&		iterations);
	virtual							~TextureGather2DInstance			(void);

protected:
	virtual int						getNumIterations					(void) const				{ return (int)m_iterations.size();	}
	virtual GatherArgs				getGatherArgs						(int iterationNdx) const	{ return m_iterations[iterationNdx];}

	virtual TextureBindingSp		createTexture						(void);
	virtual vector<float>			computeQuadTexCoord					(int iterationNdx) const;
	virtual bool					verify								(int iterationNdx, const ConstPixelBufferAccess& rendered) const;

private:
	const IVec2						m_textureSize;
	const vector<GatherArgs>		m_iterations;

	tcu::Texture2D					m_swizzledTexture;
};

TextureGather2DInstance::TextureGather2DInstance (Context&						context,
												  const GatherCaseBaseParams&	baseParams,
												  const IVec2&					textureSize,
												  const vector<GatherArgs>&		iterations)
	: TextureGatherInstance		(context, baseParams)
	, m_textureSize				(textureSize)
	, m_iterations				(iterations)
	, m_swizzledTexture			(tcu::TextureFormat(), 1, 1)
{
	init();
}

TextureGather2DInstance::~TextureGather2DInstance (void)
{
}

vector<float> TextureGather2DInstance::computeQuadTexCoord (int /* iterationNdx */) const
{
	const bool		biasMode	= (m_baseParams.levelMode == LevelMode::AMD_BIAS);
	const auto		bottomLeft	= (biasMode ? Vec2(0.0f, 0.0f) : Vec2(-0.3f, -0.4f));
	const auto		topRight	= (biasMode ? Vec2(1.0f, 1.0f) : Vec2(1.5f, 1.6f));
	vector<float>	res;
	TextureTestUtil::computeQuadTexCoord2D(res, bottomLeft, topRight);
	return res;
}

TextureBindingSp TextureGather2DInstance::createTexture (void)
{
	TestLog&						log			= m_context.getTestContext().getLog();
	const tcu::TextureFormatInfo	texFmtInfo	= tcu::getTextureFormatInfo(m_baseParams.textureFormat);
	MovePtr<tcu::Texture2D>			texture		= MovePtr<tcu::Texture2D>(new tcu::Texture2D(m_baseParams.textureFormat, m_textureSize.x(), m_textureSize.y()));
	const tcu::Sampler				sampler		(m_baseParams.wrapS, m_baseParams.wrapT, tcu::Sampler::REPEAT_GL,
												 m_baseParams.minFilter, m_baseParams.magFilter,
												 0.0f /* LOD threshold */, true /* normalized coords */, m_baseParams.shadowCompareMode);

	{
		const int	levelBegin	= ((m_baseParams.levelMode == LevelMode::NORMAL) ? m_baseParams.baseLevel : 0);
		const int	levelEnd	= texture->getNumLevels();
		DE_ASSERT(m_baseParams.baseLevel < texture->getNumLevels());

		for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
		{
			texture->allocLevel(levelNdx);
			const PixelBufferAccess& level = texture->getLevel(levelNdx);
			fillWithRandomColorTiles(level, texFmtInfo.valueMin, texFmtInfo.valueMax, (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed());
			log << TestLog::Image("InputTextureLevel" + de::toString(levelNdx), "Input texture, level " + de::toString(levelNdx), level)
				<< TestLog::Message << "Note: texture level's size is " << IVec2(level.getWidth(), level.getHeight()) << TestLog::EndMessage;
		}

		swizzleTexture(m_swizzledTexture, *texture, m_baseParams.textureSwizzle);
	}

	return TextureBindingSp(new TextureBinding(texture.release(), sampler));
}

bool TextureGather2DInstance::verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const
{
	Vec2 texCoords[4];
	computeTexCoordVecs(computeQuadTexCoord(iterationNdx), texCoords);
	return TextureGatherInstance::verify(rendered, getOneLevelSubView(tcu::Texture2DView(m_swizzledTexture), m_baseParams.baseLevel), texCoords, m_iterations[iterationNdx]);
}

class TextureGather2DCase : public TestCase
{
public:
									TextureGather2DCase					(tcu::TestContext&					testCtx,
																		 const string&						name,
																		 const string&						description,
																		 const GatherType					gatherType,
																		 const OffsetSize					offsetSize,
																		 const tcu::TextureFormat			textureFormat,
																		 const tcu::Sampler::CompareMode	shadowCompareMode,
																		 const tcu::Sampler::WrapMode		wrapS,
																		 const tcu::Sampler::WrapMode		wrapT,
																		 const MaybeTextureSwizzle&			textureSwizzle,
																		 const tcu::Sampler::FilterMode		minFilter,
																		 const tcu::Sampler::FilterMode		magFilter,
																		 const LevelMode					levelMode,
																		 const int							baseLevel,
																		 const deUint32						flags,
																		 const IVec2&						textureSize,
																		 const ImageBackingMode				sparseCase);
	virtual							~TextureGather2DCase				(void);

	virtual void					initPrograms						(vk::SourceCollections& dst) const;
	virtual	TestInstance*			createInstance						(Context& context) const;

private:
	const GatherCaseBaseParams		m_baseParams;
	const IVec2						m_textureSize;
};

TextureGather2DCase::TextureGather2DCase (tcu::TestContext&						testCtx,
										  const string&							name,
										  const string&							description,
										  const GatherType						gatherType,
										  const OffsetSize						offsetSize,
										  const tcu::TextureFormat				textureFormat,
										  const tcu::Sampler::CompareMode		shadowCompareMode,
										  const tcu::Sampler::WrapMode			wrapS,
										  const tcu::Sampler::WrapMode			wrapT,
										  const MaybeTextureSwizzle&			textureSwizzle,
										  const tcu::Sampler::FilterMode		minFilter,
										  const tcu::Sampler::FilterMode		magFilter,
										  const LevelMode						levelMode,
										  const int								baseLevel,
										  const deUint32						flags,
										  const IVec2&							textureSize,
										  const ImageBackingMode				sparseCase)
	: TestCase		(testCtx, name, description)
	, m_baseParams	(TEXTURETYPE_2D, gatherType, offsetSize, textureFormat, shadowCompareMode, wrapS, wrapT, textureSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, sparseCase)
	, m_textureSize	(textureSize)
{
}

TextureGather2DCase::~TextureGather2DCase (void)
{
}

void TextureGather2DCase::initPrograms (vk::SourceCollections& dst) const
{
	const vector<GatherArgs>	iterations	= generateBasic2DCaseIterations(m_baseParams.gatherType,
																			m_baseParams.levelMode,
																			m_baseParams.textureFormat,
																			m_baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(m_baseParams.offsetSize) : IVec2(0));

	genGatherPrograms(dst, m_baseParams, iterations);
}

TestInstance* TextureGather2DCase::createInstance (Context& context) const
{
	const vector<GatherArgs>	iterations	= generateBasic2DCaseIterations(m_baseParams.gatherType,
																			m_baseParams.levelMode,
																			m_baseParams.textureFormat,
																			getOffsetRange(m_baseParams.offsetSize, context.getDeviceProperties().limits));

	return new TextureGather2DInstance(context, m_baseParams, m_textureSize, iterations);
}

// 2D array

struct Gather2DArrayArgs
{
	GatherArgs	gatherArgs;
	int			layerNdx;

	operator GatherArgs() const { return gatherArgs; }
};

vector<Gather2DArrayArgs> generate2DArrayCaseIterations (GatherType					gatherType,
														 LevelMode					levelMode,
														 const tcu::TextureFormat&	textureFormat,
														 const IVec2&				offsetRange,
														 const IVec3&				textureSize)
{
	const vector<GatherArgs>	basicIterations	= generateBasic2DCaseIterations(gatherType, levelMode, textureFormat, offsetRange);
	vector<Gather2DArrayArgs>	iterations;

	// \note Out-of-bounds layer indices are tested too.
	for (int layerNdx = -1; layerNdx < textureSize.z()+1; layerNdx++)
	{
		// Don't duplicate all cases for all layers.
		if (layerNdx == 0)
		{
			for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
			{
				iterations.push_back(Gather2DArrayArgs());
				iterations.back().gatherArgs = basicIterations[basicNdx];
				iterations.back().layerNdx = layerNdx;
			}
		}
		else
		{
			// For other layers than 0, only test one component and one set of offsets per layer.
			for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
			{
				if (isDepthFormat(textureFormat) || basicIterations[basicNdx].componentNdx == (layerNdx + 2) % 4)
				{
					iterations.push_back(Gather2DArrayArgs());
					iterations.back().gatherArgs = basicIterations[basicNdx];
					iterations.back().layerNdx = layerNdx;
					break;
				}
			}
		}
	}

	return iterations;
}

class TextureGather2DArrayInstance : public TextureGatherInstance
{
public:
									TextureGather2DArrayInstance		(Context&							context,
																		 const GatherCaseBaseParams&		baseParams,
																		 const IVec3&						textureSize,
																		 const vector<Gather2DArrayArgs>&	iterations);
	virtual							~TextureGather2DArrayInstance		(void);

protected:
	virtual int						getNumIterations					(void) const				{ return (int)m_iterations.size();				}
	virtual GatherArgs				getGatherArgs						(int iterationNdx) const	{ return m_iterations[iterationNdx].gatherArgs;	}

	virtual TextureBindingSp		createTexture						(void);
	virtual vector<float>			computeQuadTexCoord					(int iterationNdx) const;
	virtual bool					verify								(int iterationNdx, const ConstPixelBufferAccess& rendered) const;

private:
	const IVec3						m_textureSize;
	const vector<Gather2DArrayArgs>	m_iterations;

	tcu::Texture2DArray				m_swizzledTexture;
};

TextureGather2DArrayInstance::TextureGather2DArrayInstance (Context&							context,
															const GatherCaseBaseParams&			baseParams,
															const IVec3&						textureSize,
															const vector<Gather2DArrayArgs>&	iterations)
	: TextureGatherInstance		(context, baseParams)
	, m_textureSize				(textureSize)
	, m_iterations				(iterations)
	, m_swizzledTexture			(tcu::TextureFormat(), 1, 1, 1)
{
	init();
}

TextureGather2DArrayInstance::~TextureGather2DArrayInstance (void)
{
}

vector<float> TextureGather2DArrayInstance::computeQuadTexCoord (int iterationNdx) const
{
	const bool		biasMode	= (m_baseParams.levelMode == LevelMode::AMD_BIAS);
	const auto		bottomLeft	= (biasMode ? Vec2(0.0f, 0.0f) : Vec2(-0.3f, -0.4f));
	const auto		topRight	= (biasMode ? Vec2(1.0f, 1.0f) : Vec2(1.5f, 1.6f));
	vector<float> res;
	TextureTestUtil::computeQuadTexCoord2DArray(res, m_iterations[iterationNdx].layerNdx, bottomLeft, topRight);
	return res;
}

TextureBindingSp TextureGather2DArrayInstance::createTexture (void)
{
	TestLog&						log			= m_context.getTestContext().getLog();
	const tcu::TextureFormatInfo	texFmtInfo	= tcu::getTextureFormatInfo(m_baseParams.textureFormat);
	MovePtr<tcu::Texture2DArray>	texture		= MovePtr<tcu::Texture2DArray>(new tcu::Texture2DArray(m_baseParams.textureFormat, m_textureSize.x(), m_textureSize.y(), m_textureSize.z()));
	const tcu::Sampler				sampler		(m_baseParams.wrapS, m_baseParams.wrapT, tcu::Sampler::REPEAT_GL,
												 m_baseParams.minFilter, m_baseParams.magFilter,
												 0.0f /* LOD threshold */, true /* normalized coords */, m_baseParams.shadowCompareMode);

	{
		const int	levelBegin	= ((m_baseParams.levelMode == LevelMode::NORMAL) ? m_baseParams.baseLevel : 0);
		const int	levelEnd	= texture->getNumLevels();
		DE_ASSERT(m_baseParams.baseLevel < texture->getNumLevels());

		for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
		{
			texture->allocLevel(levelNdx);
			const PixelBufferAccess& level = texture->getLevel(levelNdx);
			fillWithRandomColorTiles(level, texFmtInfo.valueMin, texFmtInfo.valueMax, (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed());

			log << TestLog::ImageSet("InputTextureLevel", "Input texture, level " + de::toString(levelNdx));
			for (int layerNdx = 0; layerNdx < m_textureSize.z(); layerNdx++)
				log << TestLog::Image("InputTextureLevel" + de::toString(layerNdx) + "Layer" + de::toString(layerNdx),
									  "Layer " + de::toString(layerNdx),
									  tcu::getSubregion(level, 0, 0, layerNdx, level.getWidth(), level.getHeight(), 1));
			log << TestLog::EndImageSet
				<< TestLog::Message << "Note: texture level's size is " << IVec3(level.getWidth(), level.getHeight(), level.getDepth()) << TestLog::EndMessage;
		}

		swizzleTexture(m_swizzledTexture, *texture, m_baseParams.textureSwizzle);
	}

	return TextureBindingSp(new TextureBinding(texture.release(), sampler));
}

bool TextureGather2DArrayInstance::verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const
{
	Vec3 texCoords[4];
	computeTexCoordVecs(computeQuadTexCoord(iterationNdx), texCoords);
	return TextureGatherInstance::verify(rendered, getOneLevelSubView(tcu::Texture2DArrayView(m_swizzledTexture), m_baseParams.baseLevel), texCoords, m_iterations[iterationNdx].gatherArgs);
}

class TextureGather2DArrayCase : public TestCase
{
public:
									TextureGather2DArrayCase			(tcu::TestContext&					testCtx,
																		 const string&						name,
																		 const string&						description,
																		 const GatherType					gatherType,
																		 const OffsetSize					offsetSize,
																		 const tcu::TextureFormat			textureFormat,
																		 const tcu::Sampler::CompareMode	shadowCompareMode,
																		 const tcu::Sampler::WrapMode		wrapS,
																		 const tcu::Sampler::WrapMode		wrapT,
																		 const MaybeTextureSwizzle&			textureSwizzle,
																		 const tcu::Sampler::FilterMode		minFilter,
																		 const tcu::Sampler::FilterMode		magFilter,
																		 const LevelMode					levelMode,
																		 const int							baseLevel,
																		 const deUint32						flags,
																		 const IVec3&						textureSize,
																		 const ImageBackingMode				sparseCase);
	virtual							~TextureGather2DArrayCase			(void);

	virtual void					initPrograms						(vk::SourceCollections& dst) const;
	virtual	TestInstance*			createInstance						(Context& context) const;

private:
	const GatherCaseBaseParams		m_baseParams;
	const IVec3						m_textureSize;
};

TextureGather2DArrayCase::TextureGather2DArrayCase (tcu::TestContext&					testCtx,
													const string&						name,
													const string&						description,
													const GatherType					gatherType,
													const OffsetSize					offsetSize,
													const tcu::TextureFormat			textureFormat,
													const tcu::Sampler::CompareMode		shadowCompareMode,
													const tcu::Sampler::WrapMode		wrapS,
													const tcu::Sampler::WrapMode		wrapT,
													const MaybeTextureSwizzle&			textureSwizzle,
													const tcu::Sampler::FilterMode		minFilter,
													const tcu::Sampler::FilterMode		magFilter,
													const LevelMode						levelMode,
													const int							baseLevel,
													const deUint32						flags,
													const IVec3&						textureSize,
													const ImageBackingMode				sparseCase)
	: TestCase			(testCtx, name, description)
	, m_baseParams		(TEXTURETYPE_2D_ARRAY, gatherType, offsetSize, textureFormat, shadowCompareMode, wrapS, wrapT, textureSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, sparseCase)
	, m_textureSize		(textureSize)
{
}

TextureGather2DArrayCase::~TextureGather2DArrayCase (void)
{
}

void TextureGather2DArrayCase::initPrograms (vk::SourceCollections& dst) const
{
	const vector<Gather2DArrayArgs>		iterations	= generate2DArrayCaseIterations(m_baseParams.gatherType,
																					m_baseParams.levelMode,
																					m_baseParams.textureFormat,
																					m_baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(m_baseParams.offsetSize) : IVec2(0),
																					m_textureSize);

	genGatherPrograms(dst, m_baseParams, vector<GatherArgs>(iterations.begin(), iterations.end()));
}

TestInstance* TextureGather2DArrayCase::createInstance (Context& context) const
{
	const vector<Gather2DArrayArgs>		iterations	= generate2DArrayCaseIterations(m_baseParams.gatherType,
																					m_baseParams.levelMode,
																					m_baseParams.textureFormat,
																					getOffsetRange(m_baseParams.offsetSize, context.getDeviceProperties().limits),
																					m_textureSize);

	return new TextureGather2DArrayInstance(context, m_baseParams, m_textureSize, iterations);
}

// Cube

struct GatherCubeArgs
{
	GatherArgs		gatherArgs;
	tcu::CubeFace	face;

	operator GatherArgs() const { return gatherArgs; }
};

vector<GatherCubeArgs> generateCubeCaseIterations (GatherType gatherType, LevelMode levelMode, const tcu::TextureFormat& textureFormat, const IVec2& offsetRange)
{
	const vector<GatherArgs>	basicIterations = generateBasic2DCaseIterations(gatherType, levelMode, textureFormat, offsetRange);
	vector<GatherCubeArgs>		iterations;

	for (int cubeFaceI = 0; cubeFaceI < tcu::CUBEFACE_LAST; cubeFaceI++)
	{
		const tcu::CubeFace cubeFace = (tcu::CubeFace)cubeFaceI;

		// Don't duplicate all cases for all faces.
		if (cubeFaceI == 0)
		{
			for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
			{
				iterations.push_back(GatherCubeArgs());
				iterations.back().gatherArgs = basicIterations[basicNdx];
				iterations.back().face = cubeFace;
			}
		}
		else
		{
			// For other faces than first, only test one component per face.
			for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
			{
				if (isDepthFormat(textureFormat) || basicIterations[basicNdx].componentNdx == cubeFaceI % 4)
				{
					iterations.push_back(GatherCubeArgs());
					iterations.back().gatherArgs = basicIterations[basicNdx];
					iterations.back().face = cubeFace;
					break;
				}
			}
		}
	}

	return iterations;
}

class TextureGatherCubeInstance : public TextureGatherInstance
{
public:
									TextureGatherCubeInstance			(Context&							context,
																		 const GatherCaseBaseParams&		baseParams,
																		 const int							textureSize,
																		 const vector<GatherCubeArgs>&		iterations);
	virtual							~TextureGatherCubeInstance			(void);

protected:
	virtual int						getNumIterations					(void) const				{ return (int)m_iterations.size();				}
	virtual GatherArgs				getGatherArgs						(int iterationNdx) const	{ return m_iterations[iterationNdx].gatherArgs;	}

	virtual TextureBindingSp		createTexture						(void);
	virtual vector<float>			computeQuadTexCoord					(int iterationNdx) const;
	virtual bool					verify								(int iterationNdx, const ConstPixelBufferAccess& rendered) const;

private:
	const int						m_textureSize;
	const vector<GatherCubeArgs>	m_iterations;

	tcu::TextureCube				m_swizzledTexture;
};

TextureGatherCubeInstance::TextureGatherCubeInstance (Context&							context,
													  const GatherCaseBaseParams&		baseParams,
													  const int							textureSize,
													  const vector<GatherCubeArgs>&		iterations)
	: TextureGatherInstance		(context, baseParams)
	, m_textureSize				(textureSize)
	, m_iterations				(iterations)
	, m_swizzledTexture			(tcu::TextureFormat(), 1)
{
	init();
}

TextureGatherCubeInstance::~TextureGatherCubeInstance (void)
{
}

vector<float> TextureGatherCubeInstance::computeQuadTexCoord (int iterationNdx) const
{
	const bool		biasMode	= (m_baseParams.levelMode == LevelMode::AMD_BIAS);
	const bool		corners		= (m_baseParams.flags & GATHERCASE_DONT_SAMPLE_CUBE_CORNERS) == 0;
	const Vec2		minC		= (biasMode ? Vec2(-1.0f) : (corners ? Vec2(-1.2f) : Vec2(-0.6f, -1.2f)));
	const Vec2		maxC		= (biasMode ? Vec2( 1.0f) : (corners ? Vec2( 1.2f) : Vec2( 0.6f,  1.2f)));
	vector<float>	res;
	TextureTestUtil::computeQuadTexCoordCube(res, m_iterations[iterationNdx].face, minC, maxC);
	return res;
}

TextureBindingSp TextureGatherCubeInstance::createTexture (void)
{
	TestLog&						log			= m_context.getTestContext().getLog();
	const tcu::TextureFormatInfo	texFmtInfo	= tcu::getTextureFormatInfo(m_baseParams.textureFormat);
	MovePtr<tcu::TextureCube>		texture		= MovePtr<tcu::TextureCube>(new tcu::TextureCube(m_baseParams.textureFormat, m_textureSize));
	const tcu::Sampler				sampler		(m_baseParams.wrapS, m_baseParams.wrapT, tcu::Sampler::REPEAT_GL,
												 m_baseParams.minFilter, m_baseParams.magFilter,
												 0.0f /* LOD threshold */, true /* normalized coords */, m_baseParams.shadowCompareMode,
												 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */);

	{
		const int	levelBegin	= ((m_baseParams.levelMode == LevelMode::NORMAL) ? m_baseParams.baseLevel : 0);
		const int	levelEnd	= texture->getNumLevels();
		DE_ASSERT(m_baseParams.baseLevel < texture->getNumLevels());

		for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
		{
			log << TestLog::ImageSet("InputTextureLevel" + de::toString(levelNdx), "Input texture, level " + de::toString(levelNdx));

			for (int cubeFaceI = 0; cubeFaceI < tcu::CUBEFACE_LAST; cubeFaceI++)
			{
				const tcu::CubeFace			cubeFace	= (tcu::CubeFace)cubeFaceI;
				texture->allocLevel(cubeFace, levelNdx);
				const PixelBufferAccess&	levelFace	= texture->getLevelFace(levelNdx, cubeFace);
				fillWithRandomColorTiles(levelFace, texFmtInfo.valueMin, texFmtInfo.valueMax, (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed() ^ (deUint32)cubeFaceI);

				log << TestLog::Image("InputTextureLevel" + de::toString(levelNdx) + "Face" + de::toString((int)cubeFace), de::toString(cubeFace), levelFace);
			}

			log << TestLog::EndImageSet
				<< TestLog::Message << "Note: texture level's size is " << texture->getLevelFace(levelNdx, tcu::CUBEFACE_NEGATIVE_X).getWidth() << TestLog::EndMessage;
		}

		swizzleTexture(m_swizzledTexture, *texture, m_baseParams.textureSwizzle);
	}

	return TextureBindingSp(new TextureBinding(texture.release(), sampler));
}

bool TextureGatherCubeInstance::verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const
{
	Vec3 texCoords[4];
	computeTexCoordVecs(computeQuadTexCoord(iterationNdx), texCoords);
	return TextureGatherInstance::verify(rendered, getOneLevelSubView(tcu::TextureCubeView(m_swizzledTexture), m_baseParams.baseLevel), texCoords, m_iterations[iterationNdx].gatherArgs);
}

// \note Cube case always uses just basic textureGather(); offset versions are not defined for cube maps.
class TextureGatherCubeCase : public TestCase
{
public:
									TextureGatherCubeCase				(tcu::TestContext&					testCtx,
																		 const string&						name,
																		 const string&						description,
																		 const tcu::TextureFormat			textureFormat,
																		 const tcu::Sampler::CompareMode	shadowCompareMode,
																		 const tcu::Sampler::WrapMode		wrapS,
																		 const tcu::Sampler::WrapMode		wrapT,
																		 const MaybeTextureSwizzle&			textureSwizzle,
																		 const tcu::Sampler::FilterMode		minFilter,
																		 const tcu::Sampler::FilterMode		magFilter,
																		 const LevelMode					levelMode,
																		 const int							baseLevel,
																		 const deUint32						flags,
																		 const int							textureSize,
																		 const ImageBackingMode				sparseCase);
	virtual							~TextureGatherCubeCase				(void);

	virtual void					initPrograms						(vk::SourceCollections& dst) const;
	virtual	TestInstance*			createInstance						(Context& context) const;

private:
	const GatherCaseBaseParams		m_baseParams;
	const int						m_textureSize;
};

TextureGatherCubeCase::TextureGatherCubeCase (tcu::TestContext&						testCtx,
											  const string&							name,
											  const string&							description,
											  const tcu::TextureFormat				textureFormat,
											  const tcu::Sampler::CompareMode		shadowCompareMode,
											  const tcu::Sampler::WrapMode			wrapS,
											  const tcu::Sampler::WrapMode			wrapT,
											  const MaybeTextureSwizzle&			textureSwizzle,
											  const tcu::Sampler::FilterMode		minFilter,
											  const tcu::Sampler::FilterMode		magFilter,
											  const LevelMode						levelMode,
											  const int								baseLevel,
											  const deUint32						flags,
											  const int								textureSize,
											  const ImageBackingMode				sparseCase)
	: TestCase			(testCtx, name, description)
	, m_baseParams		(TEXTURETYPE_CUBE, GATHERTYPE_BASIC, OFFSETSIZE_NONE, textureFormat, shadowCompareMode, wrapS, wrapT, textureSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, sparseCase)
	, m_textureSize		(textureSize)
{
}

TextureGatherCubeCase::~TextureGatherCubeCase (void)
{
}

void TextureGatherCubeCase::initPrograms (vk::SourceCollections& dst) const
{
	const vector<GatherCubeArgs>	iterations	= generateCubeCaseIterations(m_baseParams.gatherType,
																			 m_baseParams.levelMode,
																			 m_baseParams.textureFormat,
																			 m_baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(m_baseParams.offsetSize) : IVec2(0));

	genGatherPrograms(dst, m_baseParams, vector<GatherArgs>(iterations.begin(), iterations.end()));
}

TestInstance* TextureGatherCubeCase::createInstance (Context& context) const
{
	const vector<GatherCubeArgs>	iterations	= generateCubeCaseIterations(m_baseParams.gatherType,
																			 m_baseParams.levelMode,
																			 m_baseParams.textureFormat,
																			 getOffsetRange(m_baseParams.offsetSize, context.getDeviceProperties().limits));

	return new TextureGatherCubeInstance(context, m_baseParams, m_textureSize, iterations);
}

class TextureGatherTests : public tcu::TestCaseGroup
{
public:
								TextureGatherTests				(tcu::TestContext& context);
	virtual						~TextureGatherTests				(void);
	virtual void				init							(void);

private:
								TextureGatherTests				(const TextureGatherTests&);		// not allowed!
	TextureGatherTests&			operator=						(const TextureGatherTests&);		// not allowed!
};

TextureGatherTests::TextureGatherTests (tcu::TestContext& context)
	: TestCaseGroup(context, "texture_gather", "textureGather* tests")
{
}

TextureGatherTests::~TextureGatherTests (void)
{
}

static inline TestCase* makeTextureGatherCase (TextureType					textureType,
											   tcu::TestContext&			testCtx,
											   const string&				name,
											   const string&				description,
											   GatherType					gatherType,
											   OffsetSize					offsetSize,
											   tcu::TextureFormat			textureFormat,
											   tcu::Sampler::CompareMode	shadowCompareMode,
											   tcu::Sampler::WrapMode		wrapS,
											   tcu::Sampler::WrapMode		wrapT,
											   const MaybeTextureSwizzle&	texSwizzle,
											   tcu::Sampler::FilterMode		minFilter,
											   tcu::Sampler::FilterMode		magFilter,
											   LevelMode					levelMode,
											   int							baseLevel,
											   const IVec3&					textureSize,
											   deUint32						flags = 0,
											   const ImageBackingMode		sparseCase = ShaderRenderCaseInstance::IMAGE_BACKING_MODE_REGULAR)
{
	switch (textureType)
	{
		case TEXTURETYPE_2D:
			return new TextureGather2DCase(testCtx, name, description, gatherType, offsetSize, textureFormat, shadowCompareMode,
										   wrapS, wrapT, texSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, textureSize.swizzle(0, 1), sparseCase);

		case TEXTURETYPE_2D_ARRAY:
			return new TextureGather2DArrayCase(testCtx, name, description, gatherType, offsetSize, textureFormat, shadowCompareMode,
												wrapS, wrapT, texSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, textureSize, sparseCase);

		case TEXTURETYPE_CUBE:
			DE_ASSERT(gatherType == GATHERTYPE_BASIC);
			DE_ASSERT(offsetSize == OFFSETSIZE_NONE);
			return new TextureGatherCubeCase(testCtx, name, description, textureFormat, shadowCompareMode,
											 wrapS, wrapT, texSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, textureSize.x(), sparseCase);

		default:
			DE_ASSERT(false);
			return DE_NULL;
	}
}

static inline const char* compareModeName (tcu::Sampler::CompareMode mode)
{
	switch (mode)
	{
		case tcu::Sampler::COMPAREMODE_LESS:				return "less";
		case tcu::Sampler::COMPAREMODE_LESS_OR_EQUAL:		return "less_or_equal";
		case tcu::Sampler::COMPAREMODE_GREATER:				return "greater";
		case tcu::Sampler::COMPAREMODE_GREATER_OR_EQUAL:	return "greater_or_equal";
		case tcu::Sampler::COMPAREMODE_EQUAL:				return "equal";
		case tcu::Sampler::COMPAREMODE_NOT_EQUAL:			return "not_equal";
		case tcu::Sampler::COMPAREMODE_ALWAYS:				return "always";
		case tcu::Sampler::COMPAREMODE_NEVER:				return "never";
		default: DE_ASSERT(false); return DE_NULL;
	}
}

void TextureGatherTests::init (void)
{
	const struct
	{
		const char* name;
		TextureType type;
	} textureTypes[] =
	{
		{ "2d",			TEXTURETYPE_2D			},
		{ "2d_array",	TEXTURETYPE_2D_ARRAY	},
		{ "cube",		TEXTURETYPE_CUBE		}
	};

	const struct
	{
		const char*			name;
		tcu::TextureFormat	format;
	} formats[] =
	{
		{ "rgba8",		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_INT8)		},
		{ "rgba8ui",	tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT8)	},
		{ "rgba8i",		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SIGNED_INT8)	},
		{ "depth32f",	tcu::TextureFormat(tcu::TextureFormat::D,		tcu::TextureFormat::FLOAT)			}
	};

	const struct
	{
		const char*		name;
		IVec3			size;
	} textureSizes[] =
	{
		{ "size_pot",	IVec3(64, 64, 3) },
		{ "size_npot",	IVec3(17, 23, 3) }
	};

	const struct
	{
		const char*				name;
		tcu::Sampler::WrapMode	mode;
	} wrapModes[] =
	{
		{ "clamp_to_edge",		tcu::Sampler::CLAMP_TO_EDGE			},
		{ "repeat",				tcu::Sampler::REPEAT_GL				},
		{ "mirrored_repeat",	tcu::Sampler::MIRRORED_REPEAT_GL	}
	};

	for (int gatherTypeI = 0; gatherTypeI < GATHERTYPE_LAST; gatherTypeI++)
	{
		const GatherType		gatherType			= (GatherType)gatherTypeI;
		TestCaseGroup* const	gatherTypeGroup		= new TestCaseGroup(m_testCtx, gatherTypeName(gatherType), gatherTypeDescription(gatherType));
		addChild(gatherTypeGroup);

		for (int offsetSizeI = 0; offsetSizeI < OFFSETSIZE_LAST; offsetSizeI++)
		{
			const OffsetSize offsetSize = (OffsetSize)offsetSizeI;
			if ((gatherType == GATHERTYPE_BASIC) != (offsetSize == OFFSETSIZE_NONE))
				continue;

			if (gatherType == GATHERTYPE_OFFSETS && offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM) // \note offsets argument must be compile-time constant
				continue;

			TestCaseGroup* const offsetSizeGroup = offsetSize == OFFSETSIZE_NONE ?
													gatherTypeGroup :
													new TestCaseGroup(m_testCtx,
																	  offsetSize == OFFSETSIZE_MINIMUM_REQUIRED				? "min_required_offset"
																	  : offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM		? "implementation_offset"
																	  : DE_NULL,
																	  offsetSize == OFFSETSIZE_MINIMUM_REQUIRED				? "Use offsets within Vulkan minimum required range"
																	  : offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM		? "Use offsets within the implementation range"
																	  : DE_NULL);

			if (offsetSizeGroup != gatherTypeGroup)
				gatherTypeGroup->addChild(offsetSizeGroup);

			for (int textureTypeNdx = 0; textureTypeNdx < DE_LENGTH_OF_ARRAY(textureTypes); textureTypeNdx++)
			{
				const TextureType textureType = textureTypes[textureTypeNdx].type;

				if (textureType == TEXTURETYPE_CUBE && gatherType != GATHERTYPE_BASIC)
					continue;

				TestCaseGroup* const textureTypeGroup = new TestCaseGroup(m_testCtx, textureTypes[textureTypeNdx].name, "");
				offsetSizeGroup->addChild(textureTypeGroup);

				for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
				{
					const tcu::TextureFormat&	format			= formats[formatNdx].format;
					TestCaseGroup* const		formatGroup		= new TestCaseGroup(m_testCtx, formats[formatNdx].name, "");
					textureTypeGroup->addChild(formatGroup);

					for (int noCornersI = 0; noCornersI <= ((textureType == TEXTURETYPE_CUBE)?1:0); noCornersI++)
					{
						const bool				noCorners		= noCornersI!= 0;
						TestCaseGroup* const	cornersGroup	= noCorners
																? new TestCaseGroup(m_testCtx, "no_corners", "Test case variants that don't sample around cube map corners")
																: formatGroup;

						if (formatGroup != cornersGroup)
							formatGroup->addChild(cornersGroup);

						for (int textureSizeNdx = 0; textureSizeNdx < DE_LENGTH_OF_ARRAY(textureSizes); textureSizeNdx++)
						{
							const IVec3&			textureSize			= textureSizes[textureSizeNdx].size;
							TestCaseGroup* const	textureSizeGroup	= new TestCaseGroup(m_testCtx, textureSizes[textureSizeNdx].name, "");
							cornersGroup->addChild(textureSizeGroup);

							for (int compareModeI = 0; compareModeI < tcu::Sampler::COMPAREMODE_LAST; compareModeI++)
							{
								const tcu::Sampler::CompareMode compareMode = (tcu::Sampler::CompareMode)compareModeI;

								if ((compareMode != tcu::Sampler::COMPAREMODE_NONE) != isDepthFormat(format))
									continue;

								if (compareMode != tcu::Sampler::COMPAREMODE_NONE &&
									compareMode != tcu::Sampler::COMPAREMODE_LESS &&
									compareMode != tcu::Sampler::COMPAREMODE_GREATER)
									continue;

								TestCaseGroup* const compareModeGroup = compareMode == tcu::Sampler::COMPAREMODE_NONE ?
																			textureSizeGroup :
																			new TestCaseGroup(m_testCtx,
																							  (string() + "compare_" + compareModeName(compareMode)).c_str(),
																							  "");
								if (compareModeGroup != textureSizeGroup)
									textureSizeGroup->addChild(compareModeGroup);

								for (int wrapCaseNdx = 0; wrapCaseNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapCaseNdx++)
								{
									const int						wrapSNdx	= wrapCaseNdx;
									const int						wrapTNdx	= (wrapCaseNdx + 1) % DE_LENGTH_OF_ARRAY(wrapModes);
									const tcu::Sampler::WrapMode	wrapS		= wrapModes[wrapSNdx].mode;
									const tcu::Sampler::WrapMode	wrapT		= wrapModes[wrapTNdx].mode;

									const string caseName = string() + wrapModes[wrapSNdx].name + "_" + wrapModes[wrapTNdx].name;

									compareModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format, compareMode, wrapS, wrapT,
																					 MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, LevelMode::NORMAL, 0, textureSize,
																					 noCorners ? GATHERCASE_DONT_SAMPLE_CUBE_CORNERS : 0));
									compareModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format, compareMode, wrapS, wrapT,
																					 MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, LevelMode::NORMAL, 0, textureSize,
																					 noCorners ? GATHERCASE_DONT_SAMPLE_CUBE_CORNERS : 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
								}
							}
						}
					}

					if (offsetSize != OFFSETSIZE_MINIMUM_REQUIRED || gatherType == GATHERTYPE_OFFSETS) // Don't test all features for both offset size types, as they should be rather orthogonal.
					{
						if (!isDepthFormat(format))
						{
							TestCaseGroup* const swizzleGroup = new TestCaseGroup(m_testCtx, "texture_swizzle", "");
							formatGroup->addChild(swizzleGroup);

							DE_STATIC_ASSERT(TEXTURESWIZZLECOMPONENT_R == 0);
							for (int swizzleCaseNdx = 0; swizzleCaseNdx < TEXTURESWIZZLECOMPONENT_LAST; swizzleCaseNdx++)
							{
								MaybeTextureSwizzle	swizzle	= MaybeTextureSwizzle::createSomeTextureSwizzle();
								string				caseName;

								for (int i = 0; i < 4; i++)
								{
									swizzle.getSwizzle()[i] = (TextureSwizzleComponent)((swizzleCaseNdx + i) % (int)TEXTURESWIZZLECOMPONENT_LAST);
									caseName += (i > 0 ? "_" : "") + de::toLower(de::toString(swizzle.getSwizzle()[i]));
								}

								swizzleGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format,
																			 tcu::Sampler::COMPAREMODE_NONE, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
																			 swizzle, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, LevelMode::NORMAL, 0, IVec3(64, 64, 3)));
								swizzleGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format,
																			 tcu::Sampler::COMPAREMODE_NONE, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
																			 swizzle, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, LevelMode::NORMAL, 0, IVec3(64, 64, 3), 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
							}
						}

						{
							TestCaseGroup* const filterModeGroup = new TestCaseGroup(m_testCtx, "filter_mode", "Test that filter modes have no effect");
							formatGroup->addChild(filterModeGroup);

							const struct
							{
								const char*					name;
								tcu::Sampler::FilterMode	filter;
							} magFilters[] =
							{
								{ "linear",		tcu::Sampler::LINEAR	},
								{ "nearest",	tcu::Sampler::NEAREST	}
							};

							const struct
							{
								const char*					name;
								tcu::Sampler::FilterMode	filter;
							} minFilters[] =
							{
								// \note Don't test NEAREST here, as it's covered by other cases.
								{ "linear",						tcu::Sampler::LINEAR					},
								{ "nearest_mipmap_nearest",		tcu::Sampler::NEAREST_MIPMAP_NEAREST	},
								{ "nearest_mipmap_linear",		tcu::Sampler::NEAREST_MIPMAP_LINEAR		},
								{ "linear_mipmap_nearest",		tcu::Sampler::LINEAR_MIPMAP_NEAREST		},
								{ "linear_mipmap_linear",		tcu::Sampler::LINEAR_MIPMAP_LINEAR		},
							};

							for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilters); minFilterNdx++)
							for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilters); magFilterNdx++)
							{
								const tcu::Sampler::FilterMode		minFilter		= minFilters[minFilterNdx].filter;
								const tcu::Sampler::FilterMode		magFilter		= magFilters[magFilterNdx].filter;
								const tcu::Sampler::CompareMode		compareMode		= isDepthFormat(format) ? tcu::Sampler::COMPAREMODE_LESS : tcu::Sampler::COMPAREMODE_NONE;

								if ((isUnormFormatType(format.type) || isDepthFormat(format)) && magFilter == tcu::Sampler::NEAREST)
									continue; // Covered by other cases.
								if ((isUIntFormatType(format.type) || isSIntFormatType(format.type)) &&
									(magFilter != tcu::Sampler::NEAREST || minFilter != tcu::Sampler::NEAREST_MIPMAP_NEAREST))
									continue;

								const string caseName = string() + "min_" + minFilters[minFilterNdx].name + "_mag_" + magFilters[magFilterNdx].name;

								filterModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format, compareMode,
																				tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, MaybeTextureSwizzle::createNoneTextureSwizzle(),
																				minFilter, magFilter, LevelMode::NORMAL, 0, IVec3(64, 64, 3)));
								filterModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format, compareMode,
																				tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, MaybeTextureSwizzle::createNoneTextureSwizzle(),
																				minFilter, magFilter, LevelMode::NORMAL, 0, IVec3(64, 64, 3), 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
							}
						}

						{
							TestCaseGroup* const baseLevelGroup = new TestCaseGroup(m_testCtx, "base_level", "");
							formatGroup->addChild(baseLevelGroup);

							for (int baseLevel = 1; baseLevel <= 2; baseLevel++)
							{
								static const struct
								{
									const std::string	suffix;
									LevelMode			levelMode;
								} levelModes[] =
								{
									{ "",			LevelMode::NORMAL	},
									{ "_amd_bias",	LevelMode::AMD_BIAS	},
									{ "_amd_lod",	LevelMode::AMD_LOD	},
								};

								for (int modeIdx = 0; modeIdx < DE_LENGTH_OF_ARRAY(levelModes); ++modeIdx)
								{
									const auto&							mode			= levelModes[modeIdx].levelMode;

									// Not supported for these sampler types.
									if (isDepthFormat(format) && mode != LevelMode::NORMAL)
										continue;

									const string						caseName		= "level_" + de::toString(baseLevel) + levelModes[modeIdx].suffix;
									const tcu::Sampler::CompareMode		compareMode		= isDepthFormat(format) ? tcu::Sampler::COMPAREMODE_LESS : tcu::Sampler::COMPAREMODE_NONE;
									// The minFilter mode may need to be NEAREST_MIPMAP_NEAREST so the sampler creating code will not limit maxLod.
									const auto							minFilter		= ((mode == LevelMode::NORMAL) ? tcu::Sampler::NEAREST : tcu::Sampler::NEAREST_MIPMAP_NEAREST);
									baseLevelGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format,
																				compareMode, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
																				MaybeTextureSwizzle::createNoneTextureSwizzle(), minFilter, tcu::Sampler::NEAREST,
																				mode, baseLevel, IVec3(64, 64, 3)));
									baseLevelGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format,
																				compareMode, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
																				MaybeTextureSwizzle::createNoneTextureSwizzle(), minFilter, tcu::Sampler::NEAREST,
																				mode, baseLevel, IVec3(64, 64, 3), 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
								}
							}
						}
					}
				}
			}
		}
	}
}

} // anonymous

tcu::TestCaseGroup* createTextureGatherTests (tcu::TestContext& testCtx)
{
	return new TextureGatherTests(testCtx);
}

} // sr
} // vkt
