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

#include "glsUniformBlockCase.hpp"
#include "gluRenderContext.hpp"
#include "gluShaderProgram.hpp"
#include "gluPixelTransfer.hpp"
#include "gluContextInfo.hpp"
#include "gluRenderContext.hpp"
#include "gluDrawUtil.hpp"
#include "glwFunctions.hpp"
#include "glwEnums.hpp"
#include "tcuTestLog.hpp"
#include "tcuSurface.hpp"
#include "tcuRenderTarget.hpp"
#include "deRandom.hpp"
#include "deStringUtil.hpp"
#include "deMemory.h"
#include "deString.h"

#include <algorithm>
#include <map>

using tcu::TestLog;
using std::string;
using std::vector;
using std::map;

namespace deqp
{
namespace gls
{
namespace ub
{

static bool isSupportedGLSLVersion (glu::GLSLVersion version)
{
	return version >= (glslVersionIsES(version) ? glu::GLSL_VERSION_300_ES : glu::GLSL_VERSION_330);
}

struct PrecisionFlagsFmt
{
	deUint32 flags;
	PrecisionFlagsFmt (deUint32 flags_) : flags(flags_) {}
};

std::ostream& operator<< (std::ostream& str, const PrecisionFlagsFmt& fmt)
{
	// Precision.
	DE_ASSERT(dePop32(fmt.flags & (PRECISION_LOW|PRECISION_MEDIUM|PRECISION_HIGH)) <= 1);
	str << (fmt.flags & PRECISION_LOW		? "lowp"	:
			fmt.flags & PRECISION_MEDIUM	? "mediump"	:
			fmt.flags & PRECISION_HIGH		? "highp"	: "");
	return str;
}

struct LayoutFlagsFmt
{
	deUint32 flags;
	LayoutFlagsFmt (deUint32 flags_) : flags(flags_) {}
};

std::ostream& operator<< (std::ostream& str, const LayoutFlagsFmt& fmt)
{
	static const struct
	{
		deUint32	bit;
		const char*	token;
	} bitDesc[] =
	{
		{ LAYOUT_SHARED,		"shared"		},
		{ LAYOUT_PACKED,		"packed"		},
		{ LAYOUT_STD140,		"std140"		},
		{ LAYOUT_ROW_MAJOR,		"row_major"		},
		{ LAYOUT_COLUMN_MAJOR,	"column_major"	}
	};

	deUint32 remBits = fmt.flags;
	for (int descNdx = 0; descNdx < DE_LENGTH_OF_ARRAY(bitDesc); descNdx++)
	{
		if (remBits & bitDesc[descNdx].bit)
		{
			if (remBits != fmt.flags)
				str << ", ";
			str << bitDesc[descNdx].token;
			remBits &= ~bitDesc[descNdx].bit;
		}
	}
	DE_ASSERT(remBits == 0);
	return str;
}

// VarType implementation.

VarType::VarType (void)
	: m_type	(TYPE_LAST)
	, m_flags	(0)
{
}

VarType::VarType (const VarType& other)
	: m_type	(TYPE_LAST)
	, m_flags	(0)
{
	*this = other;
}

VarType::VarType (glu::DataType basicType, deUint32 flags)
	: m_type	(TYPE_BASIC)
	, m_flags	(flags)
{
	m_data.basicType = basicType;
}

VarType::VarType (const VarType& elementType, int arraySize)
	: m_type	(TYPE_ARRAY)
	, m_flags	(0)
{
	m_data.array.size			= arraySize;
	m_data.array.elementType	= new VarType(elementType);
}

VarType::VarType (const StructType* structPtr)
	: m_type	(TYPE_STRUCT)
	, m_flags	(0)
{
	m_data.structPtr = structPtr;
}

VarType::~VarType (void)
{
	if (m_type == TYPE_ARRAY)
		delete m_data.array.elementType;
}

VarType& VarType::operator= (const VarType& other)
{
	if (this == &other)
		return *this; // Self-assignment.

	if (m_type == TYPE_ARRAY)
		delete m_data.array.elementType;

	m_type	= other.m_type;
	m_flags	= other.m_flags;
	m_data	= Data();

	if (m_type == TYPE_ARRAY)
	{
		m_data.array.elementType	= new VarType(*other.m_data.array.elementType);
		m_data.array.size			= other.m_data.array.size;
	}
	else
		m_data = other.m_data;

	return *this;
}

// StructType implementation.

void StructType::addMember (const char* name, const VarType& type, deUint32 flags)
{
	m_members.push_back(StructMember(name, type, flags));
}

// Uniform implementation.

Uniform::Uniform (const char* name, const VarType& type, deUint32 flags)
	: m_name	(name)
	, m_type	(type)
	, m_flags	(flags)
{
}

// UniformBlock implementation.

UniformBlock::UniformBlock (const char* blockName)
	: m_blockName	(blockName)
	, m_arraySize	(0)
	, m_flags		(0)
{
}

struct BlockLayoutEntry
{
	BlockLayoutEntry (void)
		: size(0)
	{
	}

	std::string			name;
	int					size;
	std::vector<int>	activeUniformIndices;
};

std::ostream& operator<< (std::ostream& stream, const BlockLayoutEntry& entry)
{
	stream << entry.name << " { name = " << entry.name
		   << ", size = " << entry.size
		   << ", activeUniformIndices = [";

	for (vector<int>::const_iterator i = entry.activeUniformIndices.begin(); i != entry.activeUniformIndices.end(); i++)
	{
		if (i != entry.activeUniformIndices.begin())
			stream << ", ";
		stream << *i;
	}

	stream << "] }";
	return stream;
}

struct UniformLayoutEntry
{
	UniformLayoutEntry (void)
		: type			(glu::TYPE_LAST)
		, size			(0)
		, blockNdx		(-1)
		, offset		(-1)
		, arrayStride	(-1)
		, matrixStride	(-1)
		, isRowMajor	(false)
	{
	}

	std::string			name;
	glu::DataType		type;
	int					size;
	int					blockNdx;
	int					offset;
	int					arrayStride;
	int					matrixStride;
	bool				isRowMajor;
};

std::ostream& operator<< (std::ostream& stream, const UniformLayoutEntry& entry)
{
	stream << entry.name << " { type = " << glu::getDataTypeName(entry.type)
		   << ", size = " << entry.size
		   << ", blockNdx = " << entry.blockNdx
		   << ", offset = " << entry.offset
		   << ", arrayStride = " << entry.arrayStride
		   << ", matrixStride = " << entry.matrixStride
		   << ", isRowMajor = " << (entry.isRowMajor ? "true" : "false")
		   << " }";
	return stream;
}

class UniformLayout
{
public:
	std::vector<BlockLayoutEntry>		blocks;
	std::vector<UniformLayoutEntry>		uniforms;

	int									getUniformIndex			(const char* name) const;
	int									getBlockIndex			(const char* name) const;
};

// \todo [2012-01-24 pyry] Speed up lookups using hash.

int UniformLayout::getUniformIndex (const char* name) const
{
	for (int ndx = 0; ndx < (int)uniforms.size(); ndx++)
	{
		if (uniforms[ndx].name == name)
			return ndx;
	}
	return -1;
}

int UniformLayout::getBlockIndex (const char* name) const
{
	for (int ndx = 0; ndx < (int)blocks.size(); ndx++)
	{
		if (blocks[ndx].name == name)
			return ndx;
	}
	return -1;
}

// ShaderInterface implementation.

ShaderInterface::ShaderInterface (void)
{
}

ShaderInterface::~ShaderInterface (void)
{
	for (std::vector<StructType*>::iterator i = m_structs.begin(); i != m_structs.end(); i++)
		delete *i;

	for (std::vector<UniformBlock*>::iterator i = m_uniformBlocks.begin(); i != m_uniformBlocks.end(); i++)
		delete *i;
}

StructType& ShaderInterface::allocStruct (const char* name)
{
	m_structs.reserve(m_structs.size()+1);
	m_structs.push_back(new StructType(name));
	return *m_structs.back();
}

struct StructNameEquals
{
	std::string name;

	StructNameEquals (const char* name_) : name(name_) {}

	bool operator() (const StructType* type) const
	{
		return type->getTypeName() && name == type->getTypeName();
	}
};

const StructType* ShaderInterface::findStruct (const char* name) const
{
	std::vector<StructType*>::const_iterator pos = std::find_if(m_structs.begin(), m_structs.end(), StructNameEquals(name));
	return pos != m_structs.end() ? *pos : DE_NULL;
}

void ShaderInterface::getNamedStructs (std::vector<const StructType*>& structs) const
{
	for (std::vector<StructType*>::const_iterator i = m_structs.begin(); i != m_structs.end(); i++)
	{
		if ((*i)->getTypeName() != DE_NULL)
			structs.push_back(*i);
	}
}

UniformBlock& ShaderInterface::allocBlock (const char* name)
{
	m_uniformBlocks.reserve(m_uniformBlocks.size()+1);
	m_uniformBlocks.push_back(new UniformBlock(name));
	return *m_uniformBlocks.back();
}

namespace // Utilities
{

// Layout computation.

int getDataTypeByteSize (glu::DataType type)
{
	return glu::getDataTypeScalarSize(type)*sizeof(deUint32);
}

int getDataTypeByteAlignment (glu::DataType type)
{
	switch (type)
	{
		case glu::TYPE_FLOAT:
		case glu::TYPE_INT:
		case glu::TYPE_UINT:
		case glu::TYPE_BOOL:		return 1*sizeof(deUint32);

		case glu::TYPE_FLOAT_VEC2:
		case glu::TYPE_INT_VEC2:
		case glu::TYPE_UINT_VEC2:
		case glu::TYPE_BOOL_VEC2:	return 2*sizeof(deUint32);

		case glu::TYPE_FLOAT_VEC3:
		case glu::TYPE_INT_VEC3:
		case glu::TYPE_UINT_VEC3:
		case glu::TYPE_BOOL_VEC3:	// Fall-through to vec4

		case glu::TYPE_FLOAT_VEC4:
		case glu::TYPE_INT_VEC4:
		case glu::TYPE_UINT_VEC4:
		case glu::TYPE_BOOL_VEC4:	return 4*sizeof(deUint32);

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

int getDataTypeArrayStride (glu::DataType type)
{
	DE_ASSERT(!glu::isDataTypeMatrix(type));

	int baseStride		= getDataTypeByteSize(type);
	int vec4Alignment	= sizeof(deUint32)*4;

	DE_ASSERT(baseStride <= vec4Alignment);
	return de::max(baseStride, vec4Alignment); // Really? See rule 4.
}

static inline int deRoundUp32 (int a, int b)
{
	int d = a/b;
	return d*b == a ? a : (d+1)*b;
}

int computeStd140BaseAlignment (const VarType& type)
{
	const int vec4Alignment = sizeof(deUint32)*4;

	if (type.isBasicType())
	{
		glu::DataType basicType = type.getBasicType();

		if (glu::isDataTypeMatrix(basicType))
		{
			bool	isRowMajor	= !!(type.getFlags() & LAYOUT_ROW_MAJOR);
			int		vecSize		= isRowMajor ? glu::getDataTypeMatrixNumColumns(basicType)
											 : glu::getDataTypeMatrixNumRows(basicType);

			return getDataTypeArrayStride(glu::getDataTypeFloatVec(vecSize));
		}
		else
			return getDataTypeByteAlignment(basicType);
	}
	else if (type.isArrayType())
	{
		int elemAlignment = computeStd140BaseAlignment(type.getElementType());

		// Round up to alignment of vec4
		return deRoundUp32(elemAlignment, vec4Alignment);
	}
	else
	{
		DE_ASSERT(type.isStructType());

		int maxBaseAlignment = 0;

		for (StructType::ConstIterator memberIter = type.getStruct().begin(); memberIter != type.getStruct().end(); memberIter++)
			maxBaseAlignment = de::max(maxBaseAlignment, computeStd140BaseAlignment(memberIter->getType()));

		return deRoundUp32(maxBaseAlignment, vec4Alignment);
	}
}

inline deUint32 mergeLayoutFlags (deUint32 prevFlags, deUint32 newFlags)
{
	const deUint32	packingMask		= LAYOUT_PACKED|LAYOUT_SHARED|LAYOUT_STD140;
	const deUint32	matrixMask		= LAYOUT_ROW_MAJOR|LAYOUT_COLUMN_MAJOR;

	deUint32 mergedFlags = 0;

	mergedFlags |= ((newFlags & packingMask)	? newFlags : prevFlags) & packingMask;
	mergedFlags |= ((newFlags & matrixMask)		? newFlags : prevFlags) & matrixMask;

	return mergedFlags;
}

void computeStd140Layout (UniformLayout& layout, int& curOffset, int curBlockNdx, const std::string& curPrefix, const VarType& type, deUint32 layoutFlags)
{
	int baseAlignment = computeStd140BaseAlignment(type);

	curOffset = deAlign32(curOffset, baseAlignment);

	if (type.isBasicType())
	{
		glu::DataType		basicType	= type.getBasicType();
		UniformLayoutEntry	entry;

		entry.name			= curPrefix;
		entry.type			= basicType;
		entry.size			= 1;
		entry.arrayStride	= 0;
		entry.matrixStride	= 0;
		entry.blockNdx		= curBlockNdx;

		if (glu::isDataTypeMatrix(basicType))
		{
			// Array of vectors as specified in rules 5 & 7.
			bool	isRowMajor	= !!(layoutFlags & LAYOUT_ROW_MAJOR);
			int		vecSize		= isRowMajor ? glu::getDataTypeMatrixNumColumns(basicType)
											 : glu::getDataTypeMatrixNumRows(basicType);
			int		numVecs		= isRowMajor ? glu::getDataTypeMatrixNumRows(basicType)
											 : glu::getDataTypeMatrixNumColumns(basicType);
			int		stride		= getDataTypeArrayStride(glu::getDataTypeFloatVec(vecSize));

			entry.offset		= curOffset;
			entry.matrixStride	= stride;
			entry.isRowMajor	= isRowMajor;

			curOffset += numVecs*stride;
		}
		else
		{
			// Scalar or vector.
			entry.offset = curOffset;

			curOffset += getDataTypeByteSize(basicType);
		}

		layout.uniforms.push_back(entry);
	}
	else if (type.isArrayType())
	{
		const VarType&	elemType	= type.getElementType();

		if (elemType.isBasicType() && !glu::isDataTypeMatrix(elemType.getBasicType()))
		{
			// Array of scalars or vectors.
			glu::DataType		elemBasicType	= elemType.getBasicType();
			UniformLayoutEntry	entry;
			int					stride			= getDataTypeArrayStride(elemBasicType);

			entry.name			= curPrefix + "[0]"; // Array uniforms are always postfixed with [0]
			entry.type			= elemBasicType;
			entry.blockNdx		= curBlockNdx;
			entry.offset		= curOffset;
			entry.size			= type.getArraySize();
			entry.arrayStride	= stride;
			entry.matrixStride	= 0;

			curOffset += stride*type.getArraySize();

			layout.uniforms.push_back(entry);
		}
		else if (elemType.isBasicType() && glu::isDataTypeMatrix(elemType.getBasicType()))
		{
			// Array of matrices.
			glu::DataType		elemBasicType	= elemType.getBasicType();
			bool				isRowMajor		= !!(layoutFlags & LAYOUT_ROW_MAJOR);
			int					vecSize			= isRowMajor ? glu::getDataTypeMatrixNumColumns(elemBasicType)
															 : glu::getDataTypeMatrixNumRows(elemBasicType);
			int					numVecs			= isRowMajor ? glu::getDataTypeMatrixNumRows(elemBasicType)
															 : glu::getDataTypeMatrixNumColumns(elemBasicType);
			int					stride			= getDataTypeArrayStride(glu::getDataTypeFloatVec(vecSize));
			UniformLayoutEntry	entry;

			entry.name			= curPrefix + "[0]"; // Array uniforms are always postfixed with [0]
			entry.type			= elemBasicType;
			entry.blockNdx		= curBlockNdx;
			entry.offset		= curOffset;
			entry.size			= type.getArraySize();
			entry.arrayStride	= stride*numVecs;
			entry.matrixStride	= stride;
			entry.isRowMajor	= isRowMajor;

			curOffset += numVecs*type.getArraySize()*stride;

			layout.uniforms.push_back(entry);
		}
		else
		{
			DE_ASSERT(elemType.isStructType() || elemType.isArrayType());

			for (int elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++)
				computeStd140Layout(layout, curOffset, curBlockNdx, curPrefix + "[" + de::toString(elemNdx) + "]", type.getElementType(), layoutFlags);
		}
	}
	else
	{
		DE_ASSERT(type.isStructType());

		for (StructType::ConstIterator memberIter = type.getStruct().begin(); memberIter != type.getStruct().end(); memberIter++)
			computeStd140Layout(layout, curOffset, curBlockNdx, curPrefix + "." + memberIter->getName(), memberIter->getType(), layoutFlags);

		curOffset = deAlign32(curOffset, baseAlignment);
	}
}

void computeStd140Layout (UniformLayout& layout, const ShaderInterface& interface)
{
	// \todo [2012-01-23 pyry] Uniforms in default block.

	int numUniformBlocks = interface.getNumUniformBlocks();

	for (int blockNdx = 0; blockNdx < numUniformBlocks; blockNdx++)
	{
		const UniformBlock&	block			= interface.getUniformBlock(blockNdx);
		bool				hasInstanceName	= block.getInstanceName() != DE_NULL;
		std::string			blockPrefix		= hasInstanceName ? (std::string(block.getBlockName()) + ".") : std::string("");
		int					curOffset		= 0;
		int					activeBlockNdx	= (int)layout.blocks.size();
		int					firstUniformNdx	= (int)layout.uniforms.size();

		for (UniformBlock::ConstIterator uniformIter = block.begin(); uniformIter != block.end(); uniformIter++)
		{
			const Uniform& uniform = *uniformIter;
			computeStd140Layout(layout, curOffset, activeBlockNdx, blockPrefix + uniform.getName(), uniform.getType(), mergeLayoutFlags(block.getFlags(), uniform.getFlags()));
		}

		int	uniformIndicesEnd	= (int)layout.uniforms.size();
		int	blockSize			= curOffset;
		int	numInstances		= block.isArray() ? block.getArraySize() : 1;

		// Create block layout entries for each instance.
		for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
		{
			// Allocate entry for instance.
			layout.blocks.push_back(BlockLayoutEntry());
			BlockLayoutEntry& blockEntry = layout.blocks.back();

			blockEntry.name = block.getBlockName();
			blockEntry.size = blockSize;

			// Compute active uniform set for block.
			for (int uniformNdx = firstUniformNdx; uniformNdx < uniformIndicesEnd; uniformNdx++)
				blockEntry.activeUniformIndices.push_back(uniformNdx);

			if (block.isArray())
				blockEntry.name += "[" + de::toString(instanceNdx) + "]";
		}
	}
}

// Value generator.

void generateValue (const UniformLayoutEntry& entry, void* basePtr, de::Random& rnd)
{
	glu::DataType	scalarType		= glu::getDataTypeScalarType(entry.type);
	int				scalarSize		= glu::getDataTypeScalarSize(entry.type);
	bool			isMatrix		= glu::isDataTypeMatrix(entry.type);
	int				numVecs			= isMatrix ? (entry.isRowMajor ? glu::getDataTypeMatrixNumRows(entry.type) : glu::getDataTypeMatrixNumColumns(entry.type)) : 1;
	int				vecSize			= scalarSize / numVecs;
	bool			isArray			= entry.size > 1;
	const int		compSize		= sizeof(deUint32);

	DE_ASSERT(scalarSize%numVecs == 0);

	for (int elemNdx = 0; elemNdx < entry.size; elemNdx++)
	{
		deUint8* elemPtr = (deUint8*)basePtr + entry.offset + (isArray ? elemNdx*entry.arrayStride : 0);

		for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
		{
			deUint8* vecPtr = elemPtr + (isMatrix ? vecNdx*entry.matrixStride : 0);

			for (int compNdx = 0; compNdx < vecSize; compNdx++)
			{
				deUint8* compPtr = vecPtr + compSize*compNdx;

				switch (scalarType)
				{
					case glu::TYPE_FLOAT:	*((float*)compPtr)		= (float)rnd.getInt(-9, 9);						break;
					case glu::TYPE_INT:		*((int*)compPtr)		= rnd.getInt(-9, 9);							break;
					case glu::TYPE_UINT:	*((deUint32*)compPtr)	= (deUint32)rnd.getInt(0, 9);					break;
					// \note Random bit pattern is used for true values. Spec states that all non-zero values are
					//       interpreted as true but some implementations fail this.
					case glu::TYPE_BOOL:	*((deUint32*)compPtr)	= rnd.getBool() ? rnd.getUint32()|1u : 0u;		break;
					default:
						DE_ASSERT(false);
				}
			}
		}
	}
}

void generateValues (const UniformLayout& layout, const std::map<int, void*>& blockPointers, deUint32 seed)
{
	de::Random	rnd			(seed);
	int			numBlocks	= (int)layout.blocks.size();

	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
	{
		void*	basePtr		= blockPointers.find(blockNdx)->second;
		int		numEntries	= (int)layout.blocks[blockNdx].activeUniformIndices.size();

		for (int entryNdx = 0; entryNdx < numEntries; entryNdx++)
		{
			const UniformLayoutEntry& entry = layout.uniforms[layout.blocks[blockNdx].activeUniformIndices[entryNdx]];
			generateValue(entry, basePtr, rnd);
		}
	}
}

// Shader generator.

const char* getCompareFuncForType (glu::DataType type)
{
	switch (type)
	{
		case glu::TYPE_FLOAT:			return "mediump float compare_float    (highp float a, highp float b)  { return abs(a - b) < 0.05 ? 1.0 : 0.0; }\n";
		case glu::TYPE_FLOAT_VEC2:		return "mediump float compare_vec2     (highp vec2 a, highp vec2 b)    { return compare_float(a.x, b.x)*compare_float(a.y, b.y); }\n";
		case glu::TYPE_FLOAT_VEC3:		return "mediump float compare_vec3     (highp vec3 a, highp vec3 b)    { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z); }\n";
		case glu::TYPE_FLOAT_VEC4:		return "mediump float compare_vec4     (highp vec4 a, highp vec4 b)    { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z)*compare_float(a.w, b.w); }\n";
		case glu::TYPE_FLOAT_MAT2:		return "mediump float compare_mat2     (highp mat2 a, highp mat2 b)    { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1]); }\n";
		case glu::TYPE_FLOAT_MAT2X3:	return "mediump float compare_mat2x3   (highp mat2x3 a, highp mat2x3 b){ return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1]); }\n";
		case glu::TYPE_FLOAT_MAT2X4:	return "mediump float compare_mat2x4   (highp mat2x4 a, highp mat2x4 b){ return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1]); }\n";
		case glu::TYPE_FLOAT_MAT3X2:	return "mediump float compare_mat3x2   (highp mat3x2 a, highp mat3x2 b){ return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2]); }\n";
		case glu::TYPE_FLOAT_MAT3:		return "mediump float compare_mat3     (highp mat3 a, highp mat3 b)    { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2]); }\n";
		case glu::TYPE_FLOAT_MAT3X4:	return "mediump float compare_mat3x4   (highp mat3x4 a, highp mat3x4 b){ return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2]); }\n";
		case glu::TYPE_FLOAT_MAT4X2:	return "mediump float compare_mat4x2   (highp mat4x2 a, highp mat4x2 b){ return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2])*compare_vec2(a[3], b[3]); }\n";
		case glu::TYPE_FLOAT_MAT4X3:	return "mediump float compare_mat4x3   (highp mat4x3 a, highp mat4x3 b){ return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2])*compare_vec3(a[3], b[3]); }\n";
		case glu::TYPE_FLOAT_MAT4:		return "mediump float compare_mat4     (highp mat4 a, highp mat4 b)    { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2])*compare_vec4(a[3], b[3]); }\n";
		case glu::TYPE_INT:				return "mediump float compare_int      (highp int a, highp int b)      { return a == b ? 1.0 : 0.0; }\n";
		case glu::TYPE_INT_VEC2:		return "mediump float compare_ivec2    (highp ivec2 a, highp ivec2 b)  { return a == b ? 1.0 : 0.0; }\n";
		case glu::TYPE_INT_VEC3:		return "mediump float compare_ivec3    (highp ivec3 a, highp ivec3 b)  { return a == b ? 1.0 : 0.0; }\n";
		case glu::TYPE_INT_VEC4:		return "mediump float compare_ivec4    (highp ivec4 a, highp ivec4 b)  { return a == b ? 1.0 : 0.0; }\n";
		case glu::TYPE_UINT:			return "mediump float compare_uint     (highp uint a, highp uint b)    { return a == b ? 1.0 : 0.0; }\n";
		case glu::TYPE_UINT_VEC2:		return "mediump float compare_uvec2    (highp uvec2 a, highp uvec2 b)  { return a == b ? 1.0 : 0.0; }\n";
		case glu::TYPE_UINT_VEC3:		return "mediump float compare_uvec3    (highp uvec3 a, highp uvec3 b)  { return a == b ? 1.0 : 0.0; }\n";
		case glu::TYPE_UINT_VEC4:		return "mediump float compare_uvec4    (highp uvec4 a, highp uvec4 b)  { return a == b ? 1.0 : 0.0; }\n";
		case glu::TYPE_BOOL:			return "mediump float compare_bool     (bool a, bool b)                { return a == b ? 1.0 : 0.0; }\n";
		case glu::TYPE_BOOL_VEC2:		return "mediump float compare_bvec2    (bvec2 a, bvec2 b)              { return a == b ? 1.0 : 0.0; }\n";
		case glu::TYPE_BOOL_VEC3:		return "mediump float compare_bvec3    (bvec3 a, bvec3 b)              { return a == b ? 1.0 : 0.0; }\n";
		case glu::TYPE_BOOL_VEC4:		return "mediump float compare_bvec4    (bvec4 a, bvec4 b)              { return a == b ? 1.0 : 0.0; }\n";
		default:
			DE_ASSERT(false);
			return DE_NULL;
	}
}

void getCompareDependencies (std::set<glu::DataType>& compareFuncs, glu::DataType basicType)
{
	switch (basicType)
	{
		case glu::TYPE_FLOAT_VEC2:
		case glu::TYPE_FLOAT_VEC3:
		case glu::TYPE_FLOAT_VEC4:
			compareFuncs.insert(glu::TYPE_FLOAT);
			compareFuncs.insert(basicType);
			break;

		case glu::TYPE_FLOAT_MAT2:
		case glu::TYPE_FLOAT_MAT2X3:
		case glu::TYPE_FLOAT_MAT2X4:
		case glu::TYPE_FLOAT_MAT3X2:
		case glu::TYPE_FLOAT_MAT3:
		case glu::TYPE_FLOAT_MAT3X4:
		case glu::TYPE_FLOAT_MAT4X2:
		case glu::TYPE_FLOAT_MAT4X3:
		case glu::TYPE_FLOAT_MAT4:
			compareFuncs.insert(glu::TYPE_FLOAT);
			compareFuncs.insert(glu::getDataTypeFloatVec(glu::getDataTypeMatrixNumRows(basicType)));
			compareFuncs.insert(basicType);
			break;

		default:
			compareFuncs.insert(basicType);
			break;
	}
}

void collectUniqueBasicTypes (std::set<glu::DataType>& basicTypes, const VarType& type)
{
	if (type.isStructType())
	{
		for (StructType::ConstIterator iter = type.getStruct().begin(); iter != type.getStruct().end(); ++iter)
			collectUniqueBasicTypes(basicTypes, iter->getType());
	}
	else if (type.isArrayType())
		collectUniqueBasicTypes(basicTypes, type.getElementType());
	else
	{
		DE_ASSERT(type.isBasicType());
		basicTypes.insert(type.getBasicType());
	}
}

void collectUniqueBasicTypes (std::set<glu::DataType>& basicTypes, const UniformBlock& uniformBlock)
{
	for (UniformBlock::ConstIterator iter = uniformBlock.begin(); iter != uniformBlock.end(); ++iter)
		collectUniqueBasicTypes(basicTypes, iter->getType());
}

void collectUniqueBasicTypes (std::set<glu::DataType>& basicTypes, const ShaderInterface& interface)
{
	for (int ndx = 0; ndx < interface.getNumUniformBlocks(); ++ndx)
		collectUniqueBasicTypes(basicTypes, interface.getUniformBlock(ndx));
}

void generateCompareFuncs (std::ostream& str, const ShaderInterface& interface)
{
	std::set<glu::DataType> types;
	std::set<glu::DataType> compareFuncs;

	// Collect unique basic types
	collectUniqueBasicTypes(types, interface);

	// Set of compare functions required
	for (std::set<glu::DataType>::const_iterator iter = types.begin(); iter != types.end(); ++iter)
	{
		getCompareDependencies(compareFuncs, *iter);
	}

	for (int type = 0; type < glu::TYPE_LAST; ++type)
	{
		if (compareFuncs.find(glu::DataType(type)) != compareFuncs.end())
			str << getCompareFuncForType(glu::DataType(type));
	}
}

struct Indent
{
	int level;
	Indent (int level_) : level(level_) {}
};

std::ostream& operator<< (std::ostream& str, const Indent& indent)
{
	for (int i = 0; i < indent.level; i++)
		str << "\t";
	return str;
}

void		generateDeclaration			(std::ostringstream& src, const VarType& type, const char* name, int indentLevel, deUint32 unusedHints);
void		generateDeclaration			(std::ostringstream& src, const Uniform& uniform, int indentLevel);
void		generateDeclaration			(std::ostringstream& src, const StructType& structType, int indentLevel);

void		generateLocalDeclaration	(std::ostringstream& src, const StructType& structType, int indentLevel);
void		generateFullDeclaration		(std::ostringstream& src, const StructType& structType, int indentLevel);

void generateDeclaration (std::ostringstream& src, const StructType& structType, int indentLevel)
{
	DE_ASSERT(structType.getTypeName() != DE_NULL);
	generateFullDeclaration(src, structType, indentLevel);
	src << ";\n";
}

void generateFullDeclaration (std::ostringstream& src, const StructType& structType, int indentLevel)
{
	src << "struct";
	if (structType.getTypeName())
		src << " " << structType.getTypeName();
	src << "\n" << Indent(indentLevel) << "{\n";

	for (StructType::ConstIterator memberIter = structType.begin(); memberIter != structType.end(); memberIter++)
	{
		src << Indent(indentLevel+1);
		generateDeclaration(src, memberIter->getType(), memberIter->getName(), indentLevel+1, memberIter->getFlags() & UNUSED_BOTH);
	}

	src << Indent(indentLevel) << "}";
}

void generateLocalDeclaration (std::ostringstream& src, const StructType& structType, int indentLevel)
{
	if (structType.getTypeName() == DE_NULL)
		generateFullDeclaration(src, structType, indentLevel);
	else
		src << structType.getTypeName();
}

void generateDeclaration (std::ostringstream& src, const VarType& type, const char* name, int indentLevel, deUint32 unusedHints)
{
	deUint32 flags = type.getFlags();

	if ((flags & LAYOUT_MASK) != 0)
		src << "layout(" << LayoutFlagsFmt(flags & LAYOUT_MASK) << ") ";

	if ((flags & PRECISION_MASK) != 0)
		src << PrecisionFlagsFmt(flags & PRECISION_MASK) << " ";

	if (type.isBasicType())
		src << glu::getDataTypeName(type.getBasicType()) << " " << name;
	else if (type.isArrayType())
	{
		std::vector<int>	arraySizes;
		const VarType*		curType		= &type;
		while (curType->isArrayType())
		{
			arraySizes.push_back(curType->getArraySize());
			curType = &curType->getElementType();
		}

		if (curType->isBasicType())
		{
			if ((curType->getFlags() & PRECISION_MASK) != 0)
				src << PrecisionFlagsFmt(curType->getFlags() & PRECISION_MASK) << " ";
			src << glu::getDataTypeName(curType->getBasicType());
		}
		else
		{
			DE_ASSERT(curType->isStructType());
			generateLocalDeclaration(src, curType->getStruct(), indentLevel+1);
		}

		src << " " << name;

		for (std::vector<int>::const_iterator sizeIter = arraySizes.begin(); sizeIter != arraySizes.end(); sizeIter++)
			src << "[" << *sizeIter << "]";
	}
	else
	{
		generateLocalDeclaration(src, type.getStruct(), indentLevel+1);
		src << " " << name;
	}

	src << ";";

	// Print out unused hints.
	if (unusedHints != 0)
		src << " // unused in " << (unusedHints == UNUSED_BOTH		? "both shaders"	:
									unusedHints == UNUSED_VERTEX	? "vertex shader"	:
									unusedHints == UNUSED_FRAGMENT	? "fragment shader" : "???");

	src << "\n";
}

void generateDeclaration (std::ostringstream& src, const Uniform& uniform, int indentLevel)
{
	if ((uniform.getFlags() & LAYOUT_MASK) != 0)
		src << "layout(" << LayoutFlagsFmt(uniform.getFlags() & LAYOUT_MASK) << ") ";

	generateDeclaration(src, uniform.getType(), uniform.getName(), indentLevel, uniform.getFlags() & UNUSED_BOTH);
}

void generateDeclaration (std::ostringstream& src, const UniformBlock& block)
{
	if ((block.getFlags() & LAYOUT_MASK) != 0)
		src << "layout(" << LayoutFlagsFmt(block.getFlags() & LAYOUT_MASK) << ") ";

	src << "uniform " << block.getBlockName();
	src << "\n{\n";

	for (UniformBlock::ConstIterator uniformIter = block.begin(); uniformIter != block.end(); uniformIter++)
	{
		src << Indent(1);
		generateDeclaration(src, *uniformIter, 1 /* indent level */);
	}

	src << "}";

	if (block.getInstanceName() != DE_NULL)
	{
		src << " " << block.getInstanceName();
		if (block.isArray())
			src << "[" << block.getArraySize() << "]";
	}
	else
		DE_ASSERT(!block.isArray());

	src << ";\n";
}

void generateValueSrc (std::ostringstream& src, const UniformLayoutEntry& entry, const void* basePtr, int elementNdx)
{
	glu::DataType	scalarType		= glu::getDataTypeScalarType(entry.type);
	int				scalarSize		= glu::getDataTypeScalarSize(entry.type);
	bool			isArray			= entry.size > 1;
	const deUint8*	elemPtr			= (const deUint8*)basePtr + entry.offset + (isArray ? elementNdx*entry.arrayStride : 0);
	const int		compSize		= sizeof(deUint32);

	if (scalarSize > 1)
		src << glu::getDataTypeName(entry.type) << "(";

	if (glu::isDataTypeMatrix(entry.type))
	{
		int	numRows	= glu::getDataTypeMatrixNumRows(entry.type);
		int	numCols	= glu::getDataTypeMatrixNumColumns(entry.type);

		DE_ASSERT(scalarType == glu::TYPE_FLOAT);

		// Constructed in column-wise order.
		for (int colNdx = 0; colNdx < numCols; colNdx++)
		{
			for (int rowNdx = 0; rowNdx < numRows; rowNdx++)
			{
				const deUint8*	compPtr	= elemPtr + (entry.isRowMajor ? rowNdx*entry.matrixStride + colNdx*compSize
																	  : colNdx*entry.matrixStride + rowNdx*compSize);

				if (colNdx > 0 || rowNdx > 0)
					src << ", ";

				src << de::floatToString(*((const float*)compPtr), 1);
			}
		}
	}
	else
	{
		for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
		{
			const deUint8* compPtr = elemPtr + scalarNdx*compSize;

			if (scalarNdx > 0)
				src << ", ";

			switch (scalarType)
			{
				case glu::TYPE_FLOAT:	src << de::floatToString(*((const float*)compPtr), 1);			break;
				case glu::TYPE_INT:		src << *((const int*)compPtr);									break;
				case glu::TYPE_UINT:	src << *((const deUint32*)compPtr) << "u";						break;
				case glu::TYPE_BOOL:	src << (*((const deUint32*)compPtr) != 0u ? "true" : "false");	break;
				default:
					DE_ASSERT(false);
			}
		}
	}

	if (scalarSize > 1)
		src << ")";
}

void generateCompareSrc (std::ostringstream& src, const char* resultVar, const VarType& type, const char* srcName, const char* apiName, const UniformLayout& layout, const void* basePtr, deUint32 unusedMask)
{
	if (type.isBasicType() || (type.isArrayType() && type.getElementType().isBasicType()))
	{
		// Basic type or array of basic types.
		bool						isArray			= type.isArrayType();
		glu::DataType				elementType		= isArray ? type.getElementType().getBasicType() : type.getBasicType();
		const char*					typeName		= glu::getDataTypeName(elementType);
		std::string					fullApiName		= string(apiName) + (isArray ? "[0]" : ""); // Arrays are always postfixed with [0]
		int							uniformNdx		= layout.getUniformIndex(fullApiName.c_str());
		const UniformLayoutEntry&	entry			= layout.uniforms[uniformNdx];

		if (isArray)
		{
			for (int elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++)
			{
				src << "\tresult *= compare_" << typeName << "(" << srcName << "[" << elemNdx << "], ";
				generateValueSrc(src, entry, basePtr, elemNdx);
				src << ");\n";
			}
		}
		else
		{
			src << "\tresult *= compare_" << typeName << "(" << srcName << ", ";
			generateValueSrc(src, entry, basePtr, 0);
			src << ");\n";
		}
	}
	else if (type.isArrayType())
	{
		const VarType& elementType = type.getElementType();

		for (int elementNdx = 0; elementNdx < type.getArraySize(); elementNdx++)
		{
			std::string op = string("[") + de::toString(elementNdx) + "]";
			generateCompareSrc(src, resultVar, elementType, (string(srcName) + op).c_str(), (string(apiName) + op).c_str(), layout, basePtr, unusedMask);
		}
	}
	else
	{
		DE_ASSERT(type.isStructType());

		for (StructType::ConstIterator memberIter = type.getStruct().begin(); memberIter != type.getStruct().end(); memberIter++)
		{
			if (memberIter->getFlags() & unusedMask)
				continue; // Skip member.

			string op = string(".") + memberIter->getName();
			generateCompareSrc(src, resultVar, memberIter->getType(), (string(srcName) + op).c_str(), (string(apiName) + op).c_str(), layout, basePtr, unusedMask);
		}
	}
}

void generateCompareSrc (std::ostringstream& src, const char* resultVar, const ShaderInterface& interface, const UniformLayout& layout, const std::map<int, void*>& blockPointers, bool isVertex)
{
	deUint32 unusedMask = isVertex ? UNUSED_VERTEX : UNUSED_FRAGMENT;

	for (int blockNdx = 0; blockNdx < interface.getNumUniformBlocks(); blockNdx++)
	{
		const UniformBlock& block = interface.getUniformBlock(blockNdx);

		if ((block.getFlags() & (isVertex ? DECLARE_VERTEX : DECLARE_FRAGMENT)) == 0)
			continue; // Skip.

		bool			hasInstanceName	= block.getInstanceName() != DE_NULL;
		bool			isArray			= block.isArray();
		int				numInstances	= isArray ? block.getArraySize() : 1;
		std::string		apiPrefix		= hasInstanceName ? string(block.getBlockName()) + "." : string("");

		DE_ASSERT(!isArray || hasInstanceName);

		for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
		{
			std::string		instancePostfix		= isArray ? string("[") + de::toString(instanceNdx) + "]" : string("");
			std::string		blockInstanceName	= block.getBlockName() + instancePostfix;
			std::string		srcPrefix			= hasInstanceName ? string(block.getInstanceName()) + instancePostfix + "." : string("");
			int				activeBlockNdx		= layout.getBlockIndex(blockInstanceName.c_str());
			void*			basePtr				= blockPointers.find(activeBlockNdx)->second;

			for (UniformBlock::ConstIterator uniformIter = block.begin(); uniformIter != block.end(); uniformIter++)
			{
				const Uniform& uniform = *uniformIter;

				if (uniform.getFlags() & unusedMask)
					continue; // Don't read from that uniform.

				generateCompareSrc(src, resultVar, uniform.getType(), (srcPrefix + uniform.getName()).c_str(), (apiPrefix + uniform.getName()).c_str(), layout, basePtr, unusedMask);
			}
		}
	}
}

void generateVertexShader (std::ostringstream& src, glu::GLSLVersion glslVersion, const ShaderInterface& interface, const UniformLayout& layout, const std::map<int, void*>& blockPointers)
{
	DE_ASSERT(isSupportedGLSLVersion(glslVersion));

	src << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
	src << "in highp vec4 a_position;\n";
	src << "out mediump float v_vtxResult;\n";
	src << "\n";

	std::vector<const StructType*> namedStructs;
	interface.getNamedStructs(namedStructs);
	for (std::vector<const StructType*>::const_iterator structIter = namedStructs.begin(); structIter != namedStructs.end(); structIter++)
		generateDeclaration(src, **structIter, 0);

	for (int blockNdx = 0; blockNdx < interface.getNumUniformBlocks(); blockNdx++)
	{
		const UniformBlock& block = interface.getUniformBlock(blockNdx);
		if (block.getFlags() & DECLARE_VERTEX)
			generateDeclaration(src, block);
	}

	// Comparison utilities.
	src << "\n";
	generateCompareFuncs(src, interface);

	src << "\n"
		   "void main (void)\n"
		   "{\n"
		   "	gl_Position = a_position;\n"
		   "	mediump float result = 1.0;\n";

	// Value compare.
	generateCompareSrc(src, "result", interface, layout, blockPointers, true);

	src << "	v_vtxResult = result;\n"
		   "}\n";
}

void generateFragmentShader (std::ostringstream& src, glu::GLSLVersion glslVersion, const ShaderInterface& interface, const UniformLayout& layout, const std::map<int, void*>& blockPointers)
{
	DE_ASSERT(isSupportedGLSLVersion(glslVersion));

	src << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
	src << "in mediump float v_vtxResult;\n";
	src << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
	src << "\n";

	std::vector<const StructType*> namedStructs;
	interface.getNamedStructs(namedStructs);
	for (std::vector<const StructType*>::const_iterator structIter = namedStructs.begin(); structIter != namedStructs.end(); structIter++)
		generateDeclaration(src, **structIter, 0);

	for (int blockNdx = 0; blockNdx < interface.getNumUniformBlocks(); blockNdx++)
	{
		const UniformBlock& block = interface.getUniformBlock(blockNdx);
		if (block.getFlags() & DECLARE_FRAGMENT)
			generateDeclaration(src, block);
	}

	// Comparison utilities.
	src << "\n";
	generateCompareFuncs(src, interface);

	src << "\n"
		   "void main (void)\n"
		   "{\n"
		   "	mediump float result = 1.0;\n";

	// Value compare.
	generateCompareSrc(src, "result", interface, layout, blockPointers, false);

	src << "	dEQP_FragColor = vec4(1.0, v_vtxResult, result, 1.0);\n"
		   "}\n";
}

void getGLUniformLayout (const glw::Functions& gl, UniformLayout& layout, deUint32 program)
{
	int		numActiveUniforms	= 0;
	int		numActiveBlocks		= 0;

	gl.getProgramiv(program, GL_ACTIVE_UNIFORMS,		&numActiveUniforms);
	gl.getProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS,	&numActiveBlocks);

	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get number of uniforms and uniform blocks");

	// Block entries.
	layout.blocks.resize(numActiveBlocks);
	for (int blockNdx = 0; blockNdx < numActiveBlocks; blockNdx++)
	{
		BlockLayoutEntry&	entry				= layout.blocks[blockNdx];
		int					size;
		int					nameLen;
		int					numBlockUniforms;

		gl.getActiveUniformBlockiv(program, (deUint32)blockNdx, GL_UNIFORM_BLOCK_DATA_SIZE,			&size);
		gl.getActiveUniformBlockiv(program, (deUint32)blockNdx, GL_UNIFORM_BLOCK_NAME_LENGTH,		&nameLen);
		gl.getActiveUniformBlockiv(program, (deUint32)blockNdx, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,	&numBlockUniforms);

		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform block query failed");

		// \note Some implementations incorrectly return 0 as name length even though the length should include null terminator.
		std::vector<char> nameBuf(nameLen > 0 ? nameLen : 1);
		gl.getActiveUniformBlockName(program, (deUint32)blockNdx, (glw::GLsizei)nameBuf.size(), DE_NULL, &nameBuf[0]);

		entry.name	= std::string(&nameBuf[0]);
		entry.size	= size;
		entry.activeUniformIndices.resize(numBlockUniforms);

		if (numBlockUniforms > 0)
			gl.getActiveUniformBlockiv(program, (deUint32)blockNdx, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, &entry.activeUniformIndices[0]);

		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform block query failed");
	}

	if (numActiveUniforms > 0)
	{
		// Uniform entries.
		std::vector<deUint32> uniformIndices(numActiveUniforms);
		for (int i = 0; i < numActiveUniforms; i++)
			uniformIndices[i] = (deUint32)i;

		std::vector<int>		types			(numActiveUniforms);
		std::vector<int>		sizes			(numActiveUniforms);
		std::vector<int>		nameLengths		(numActiveUniforms);
		std::vector<int>		blockIndices	(numActiveUniforms);
		std::vector<int>		offsets			(numActiveUniforms);
		std::vector<int>		arrayStrides	(numActiveUniforms);
		std::vector<int>		matrixStrides	(numActiveUniforms);
		std::vector<int>		rowMajorFlags	(numActiveUniforms);

		// Execute queries.
		gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0], GL_UNIFORM_TYPE,			&types[0]);
		gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0], GL_UNIFORM_SIZE,			&sizes[0]);
		gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0], GL_UNIFORM_NAME_LENGTH,	&nameLengths[0]);
		gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0], GL_UNIFORM_BLOCK_INDEX,	&blockIndices[0]);
		gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0], GL_UNIFORM_OFFSET,			&offsets[0]);
		gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0], GL_UNIFORM_ARRAY_STRIDE,	&arrayStrides[0]);
		gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0], GL_UNIFORM_MATRIX_STRIDE,	&matrixStrides[0]);
		gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0], GL_UNIFORM_IS_ROW_MAJOR,	&rowMajorFlags[0]);

		GLU_EXPECT_NO_ERROR(gl.getError(), "Active uniform query failed");

		// Translate to LayoutEntries
		layout.uniforms.resize(numActiveUniforms);
		for (int uniformNdx = 0; uniformNdx < numActiveUniforms; uniformNdx++)
		{
			UniformLayoutEntry&	entry		= layout.uniforms[uniformNdx];
			std::vector<char>	nameBuf		(nameLengths[uniformNdx]);
			glw::GLsizei		nameLen		= 0;
			int					size		= 0;
			deUint32			type		= GL_NONE;

			gl.getActiveUniform(program, (deUint32)uniformNdx, (glw::GLsizei)nameBuf.size(), &nameLen, &size, &type, &nameBuf[0]);

			GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform name query failed");

			// \note glGetActiveUniform() returns length without \0 and glGetActiveUniformsiv() with \0
			if (nameLen+1	!= nameLengths[uniformNdx]	||
				size		!= sizes[uniformNdx]		||
				type		!= (deUint32)types[uniformNdx])
				TCU_FAIL("Values returned by glGetActiveUniform() don't match with values queried with glGetActiveUniformsiv().");

			entry.name			= std::string(&nameBuf[0]);
			entry.type			= glu::getDataTypeFromGLType(types[uniformNdx]);
			entry.size			= sizes[uniformNdx];
			entry.blockNdx		= blockIndices[uniformNdx];
			entry.offset		= offsets[uniformNdx];
			entry.arrayStride	= arrayStrides[uniformNdx];
			entry.matrixStride	= matrixStrides[uniformNdx];
			entry.isRowMajor	= rowMajorFlags[uniformNdx] != GL_FALSE;
		}
	}
}

void copyUniformData (const UniformLayoutEntry& dstEntry, void* dstBlockPtr, const UniformLayoutEntry& srcEntry, const void* srcBlockPtr)
{
	deUint8*					dstBasePtr	= (deUint8*)dstBlockPtr + dstEntry.offset;
	const deUint8*				srcBasePtr	= (const deUint8*)srcBlockPtr + srcEntry.offset;

	DE_ASSERT(dstEntry.size <= srcEntry.size);
	DE_ASSERT(dstEntry.type == srcEntry.type);

	int							scalarSize	= glu::getDataTypeScalarSize(dstEntry.type);
	bool						isMatrix	= glu::isDataTypeMatrix(dstEntry.type);
	const int					compSize	= sizeof(deUint32);

	for (int elementNdx = 0; elementNdx < dstEntry.size; elementNdx++)
	{
		deUint8*		dstElemPtr	= dstBasePtr + elementNdx*dstEntry.arrayStride;
		const deUint8*	srcElemPtr	= srcBasePtr + elementNdx*srcEntry.arrayStride;

		if (isMatrix)
		{
			int	numRows	= glu::getDataTypeMatrixNumRows(dstEntry.type);
			int	numCols	= glu::getDataTypeMatrixNumColumns(dstEntry.type);

			for (int colNdx = 0; colNdx < numCols; colNdx++)
			{
				for (int rowNdx = 0; rowNdx < numRows; rowNdx++)
				{
					deUint8*		dstCompPtr	= dstElemPtr + (dstEntry.isRowMajor ? rowNdx*dstEntry.matrixStride + colNdx*compSize
																					: colNdx*dstEntry.matrixStride + rowNdx*compSize);
					const deUint8*	srcCompPtr	= srcElemPtr + (srcEntry.isRowMajor ? rowNdx*srcEntry.matrixStride + colNdx*compSize
																					: colNdx*srcEntry.matrixStride + rowNdx*compSize);
					deMemcpy(dstCompPtr, srcCompPtr, compSize);
				}
			}
		}
		else
			deMemcpy(dstElemPtr, srcElemPtr, scalarSize*compSize);
	}
}

void copyUniformData (const UniformLayout& dstLayout, const std::map<int, void*>& dstBlockPointers, const UniformLayout& srcLayout, const std::map<int, void*>& srcBlockPointers)
{
	// \note Src layout is used as reference in case of activeUniforms happens to be incorrect in dstLayout blocks.
	int numBlocks = (int)srcLayout.blocks.size();

	for (int srcBlockNdx = 0; srcBlockNdx < numBlocks; srcBlockNdx++)
	{
		const BlockLayoutEntry&		srcBlock	= srcLayout.blocks[srcBlockNdx];
		const void*					srcBlockPtr	= srcBlockPointers.find(srcBlockNdx)->second;
		int							dstBlockNdx	= dstLayout.getBlockIndex(srcBlock.name.c_str());
		void*						dstBlockPtr	= dstBlockNdx >= 0 ? dstBlockPointers.find(dstBlockNdx)->second : DE_NULL;

		if (dstBlockNdx < 0)
			continue;

		for (vector<int>::const_iterator srcUniformNdxIter = srcBlock.activeUniformIndices.begin(); srcUniformNdxIter != srcBlock.activeUniformIndices.end(); srcUniformNdxIter++)
		{
			const UniformLayoutEntry&	srcEntry		= srcLayout.uniforms[*srcUniformNdxIter];
			int							dstUniformNdx	= dstLayout.getUniformIndex(srcEntry.name.c_str());

			if (dstUniformNdx < 0)
				continue;

			copyUniformData(dstLayout.uniforms[dstUniformNdx], dstBlockPtr, srcEntry, srcBlockPtr);
		}
	}
}

} // anonymous (utilities)

class UniformBufferManager
{
public:
								UniformBufferManager	(const glu::RenderContext& renderCtx);
								~UniformBufferManager	(void);

	deUint32					allocBuffer				(void);

private:
								UniformBufferManager	(const UniformBufferManager& other);
	UniformBufferManager&		operator=				(const UniformBufferManager& other);

	const glu::RenderContext&	m_renderCtx;
	std::vector<deUint32>		m_buffers;
};

UniformBufferManager::UniformBufferManager (const glu::RenderContext& renderCtx)
	: m_renderCtx(renderCtx)
{
}

UniformBufferManager::~UniformBufferManager (void)
{
	if (!m_buffers.empty())
		m_renderCtx.getFunctions().deleteBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]);
}

deUint32 UniformBufferManager::allocBuffer (void)
{
	deUint32 buf = 0;

	m_buffers.reserve(m_buffers.size()+1);
	m_renderCtx.getFunctions().genBuffers(1, &buf);
	GLU_EXPECT_NO_ERROR(m_renderCtx.getFunctions().getError(), "Failed to allocate uniform buffer");
	m_buffers.push_back(buf);

	return buf;
}

} // ub

using namespace ub;

// UniformBlockCase.

UniformBlockCase::UniformBlockCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, glu::GLSLVersion glslVersion, BufferMode bufferMode)
	: TestCase		(testCtx, name, description)
	, m_renderCtx	(renderCtx)
	, m_glslVersion	(glslVersion)
	, m_bufferMode	(bufferMode)
{
	TCU_CHECK_INTERNAL(isSupportedGLSLVersion(glslVersion));
}

UniformBlockCase::~UniformBlockCase (void)
{
}

UniformBlockCase::IterateResult UniformBlockCase::iterate (void)
{
	TestLog&				log				= m_testCtx.getLog();
	const glw::Functions&	gl				= m_renderCtx.getFunctions();
	UniformLayout			refLayout;		//!< std140 layout.
	vector<deUint8>			data;			//!< Data.
	map<int, void*>			blockPointers;	//!< Reference block pointers.

	// Initialize result to pass.
	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");

	// Compute reference layout.
	computeStd140Layout(refLayout, m_interface);

	// Assign storage for reference values.
	{
		int totalSize = 0;
		for (vector<BlockLayoutEntry>::const_iterator blockIter = refLayout.blocks.begin(); blockIter != refLayout.blocks.end(); blockIter++)
			totalSize += blockIter->size;
		data.resize(totalSize);

		// Pointers for each block.
		int curOffset = 0;
		for (int blockNdx = 0; blockNdx < (int)refLayout.blocks.size(); blockNdx++)
		{
			blockPointers[blockNdx] = &data[0] + curOffset;
			curOffset += refLayout.blocks[blockNdx].size;
		}
	}

	// Generate values.
	generateValues(refLayout, blockPointers, 1 /* seed */);

	// Generate shaders and build program.
	std::ostringstream vtxSrc;
	std::ostringstream fragSrc;

	generateVertexShader(vtxSrc, m_glslVersion, m_interface, refLayout, blockPointers);
	generateFragmentShader(fragSrc, m_glslVersion, m_interface, refLayout, blockPointers);

	glu::ShaderProgram program(m_renderCtx, glu::makeVtxFragSources(vtxSrc.str(), fragSrc.str()));
	log << program;

	if (!program.isOk())
	{
		// Compile failed.
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compile failed");
		return STOP;
	}

	// Query layout from GL.
	UniformLayout glLayout;
	getGLUniformLayout(gl, glLayout, program.getProgram());

	// Print layout to log.
	log << TestLog::Section("ActiveUniformBlocks", "Active Uniform Blocks");
	for (int blockNdx = 0; blockNdx < (int)glLayout.blocks.size(); blockNdx++)
		log << TestLog::Message << blockNdx << ": " << glLayout.blocks[blockNdx] << TestLog::EndMessage;
	log << TestLog::EndSection;

	log << TestLog::Section("ActiveUniforms", "Active Uniforms");
	for (int uniformNdx = 0; uniformNdx < (int)glLayout.uniforms.size(); uniformNdx++)
		log << TestLog::Message << uniformNdx << ": " << glLayout.uniforms[uniformNdx] << TestLog::EndMessage;
	log << TestLog::EndSection;

	// Check that we can even try rendering with given layout.
	if (!checkLayoutIndices(glLayout) || !checkLayoutBounds(glLayout) || !compareTypes(refLayout, glLayout))
	{
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid layout");
		return STOP; // It is not safe to use the given layout.
	}

	// Verify all std140 blocks.
	if (!compareStd140Blocks(refLayout, glLayout))
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid std140 layout");

	// Verify all shared blocks - all uniforms should be active, and certain properties match.
	if (!compareSharedBlocks(refLayout, glLayout))
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid shared layout");

	// Check consistency with index queries
	if (!checkIndexQueries(program.getProgram(), glLayout))
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Inconsintent block index query results");

	// Use program.
	gl.useProgram(program.getProgram());

	// Assign binding points to all active uniform blocks.
	for (int blockNdx = 0; blockNdx < (int)glLayout.blocks.size(); blockNdx++)
	{
		deUint32 binding = (deUint32)blockNdx; // \todo [2012-01-25 pyry] Randomize order?
		gl.uniformBlockBinding(program.getProgram(), (deUint32)blockNdx, binding);
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set uniform block bindings");

	// Allocate buffers, write data and bind to targets.
	UniformBufferManager bufferManager(m_renderCtx);
	if (m_bufferMode == BUFFERMODE_PER_BLOCK)
	{
		int							numBlocks			= (int)glLayout.blocks.size();
		vector<vector<deUint8> >	glData				(numBlocks);
		map<int, void*>				glBlockPointers;

		for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
		{
			glData[blockNdx].resize(glLayout.blocks[blockNdx].size);
			glBlockPointers[blockNdx] = &glData[blockNdx][0];
		}

		copyUniformData(glLayout, glBlockPointers, refLayout, blockPointers);

		for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
		{
			deUint32	buffer	= bufferManager.allocBuffer();
			deUint32	binding	= (deUint32)blockNdx;

			gl.bindBuffer(GL_UNIFORM_BUFFER, buffer);
			gl.bufferData(GL_UNIFORM_BUFFER, (glw::GLsizeiptr)glData[blockNdx].size(), &glData[blockNdx][0], GL_STATIC_DRAW);
			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload uniform buffer data");

			gl.bindBufferBase(GL_UNIFORM_BUFFER, binding, buffer);
			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(GL_UNIFORM_BUFFER) failed");
		}
	}
	else
	{
		DE_ASSERT(m_bufferMode == BUFFERMODE_SINGLE);

		int				totalSize			= 0;
		int				curOffset			= 0;
		int				numBlocks			= (int)glLayout.blocks.size();
		int				bindingAlignment	= 0;
		map<int, int>	glBlockOffsets;

		gl.getIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &bindingAlignment);

		// Compute total size and offsets.
		curOffset = 0;
		for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
		{
			if (bindingAlignment > 0)
				curOffset = deRoundUp32(curOffset, bindingAlignment);
			glBlockOffsets[blockNdx] = curOffset;
			curOffset += glLayout.blocks[blockNdx].size;
		}
		totalSize = curOffset;

		// Assign block pointers.
		vector<deUint8>	glData(totalSize);
		map<int, void*>	glBlockPointers;

		for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
			glBlockPointers[blockNdx] = &glData[glBlockOffsets[blockNdx]];

		// Copy to gl format.
		copyUniformData(glLayout, glBlockPointers, refLayout, blockPointers);

		// Allocate buffer and upload data.
		deUint32 buffer = bufferManager.allocBuffer();
		gl.bindBuffer(GL_UNIFORM_BUFFER, buffer);
		if (!glData.empty())
			gl.bufferData(GL_UNIFORM_BUFFER, (glw::GLsizeiptr)glData.size(), &glData[0], GL_STATIC_DRAW);

		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload uniform buffer data");

		// Bind ranges to binding points.
		for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
		{
			deUint32 binding = (deUint32)blockNdx;
			gl.bindBufferRange(GL_UNIFORM_BUFFER, binding, buffer, (glw::GLintptr)glBlockOffsets[blockNdx], (glw::GLsizeiptr)glLayout.blocks[blockNdx].size);
			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange(GL_UNIFORM_BUFFER) failed");
		}
	}

	bool renderOk = render(program.getProgram());
	if (!renderOk)
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image compare failed");

	return STOP;
}

bool UniformBlockCase::compareStd140Blocks (const UniformLayout& refLayout, const UniformLayout& cmpLayout) const
{
	TestLog&	log			= m_testCtx.getLog();
	bool		isOk		= true;
	int			numBlocks	= m_interface.getNumUniformBlocks();

	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
	{
		const UniformBlock&		block			= m_interface.getUniformBlock(blockNdx);
		bool					isArray			= block.isArray();
		std::string				instanceName	= string(block.getBlockName()) + (isArray ? "[0]" : "");
		int						refBlockNdx		= refLayout.getBlockIndex(instanceName.c_str());
		int						cmpBlockNdx		= cmpLayout.getBlockIndex(instanceName.c_str());
		bool					isUsed			= (block.getFlags() & (DECLARE_VERTEX|DECLARE_FRAGMENT)) != 0;

		if ((block.getFlags() & LAYOUT_STD140) == 0)
			continue; // Not std140 layout.

		DE_ASSERT(refBlockNdx >= 0);

		if (cmpBlockNdx < 0)
		{
			// Not found, should it?
			if (isUsed)
			{
				log << TestLog::Message << "Error: Uniform block '" << instanceName << "' not found" << TestLog::EndMessage;
				isOk = false;
			}

			continue; // Skip block.
		}

		const BlockLayoutEntry&		refBlockLayout	= refLayout.blocks[refBlockNdx];
		const BlockLayoutEntry&		cmpBlockLayout	= cmpLayout.blocks[cmpBlockNdx];

		// \todo [2012-01-24 pyry] Verify that activeUniformIndices is correct.
		// \todo [2012-01-24 pyry] Verify all instances.
		if (refBlockLayout.activeUniformIndices.size() != cmpBlockLayout.activeUniformIndices.size())
		{
			log << TestLog::Message << "Error: Number of active uniforms differ in block '" << instanceName
				<< "' (expected " << refBlockLayout.activeUniformIndices.size()
				<< ", got " << cmpBlockLayout.activeUniformIndices.size()
				<< ")" << TestLog::EndMessage;
			isOk = false;
		}

		for (vector<int>::const_iterator ndxIter = refBlockLayout.activeUniformIndices.begin(); ndxIter != refBlockLayout.activeUniformIndices.end(); ndxIter++)
		{
			const UniformLayoutEntry&	refEntry	= refLayout.uniforms[*ndxIter];
			int							cmpEntryNdx	= cmpLayout.getUniformIndex(refEntry.name.c_str());

			if (cmpEntryNdx < 0)
			{
				log << TestLog::Message << "Error: Uniform '" << refEntry.name << "' not found" << TestLog::EndMessage;
				isOk = false;
				continue;
			}

			const UniformLayoutEntry&	cmpEntry	= cmpLayout.uniforms[cmpEntryNdx];

			if (refEntry.type			!= cmpEntry.type			||
				refEntry.size			!= cmpEntry.size			||
				refEntry.offset			!= cmpEntry.offset			||
				refEntry.arrayStride	!= cmpEntry.arrayStride		||
				refEntry.matrixStride	!= cmpEntry.matrixStride	||
				refEntry.isRowMajor		!= cmpEntry.isRowMajor)
			{
				log << TestLog::Message << "Error: Layout mismatch in '" << refEntry.name << "':\n"
					<< "  expected: type = " << glu::getDataTypeName(refEntry.type) << ", size = " << refEntry.size << ", offset = " << refEntry.offset << ", array stride = "<< refEntry.arrayStride << ", matrix stride = " << refEntry.matrixStride << ", row major = " << (refEntry.isRowMajor ? "true" : "false") << "\n"
					<< "  got: type = " << glu::getDataTypeName(cmpEntry.type) << ", size = " << cmpEntry.size << ", offset = " << cmpEntry.offset << ", array stride = "<< cmpEntry.arrayStride << ", matrix stride = " << cmpEntry.matrixStride << ", row major = " << (cmpEntry.isRowMajor ? "true" : "false")
					<< TestLog::EndMessage;
				isOk = false;
			}
		}
	}

	return isOk;
}

bool UniformBlockCase::compareSharedBlocks (const UniformLayout& refLayout, const UniformLayout& cmpLayout) const
{
	TestLog&	log			= m_testCtx.getLog();
	bool		isOk		= true;
	int			numBlocks	= m_interface.getNumUniformBlocks();

	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
	{
		const UniformBlock&		block			= m_interface.getUniformBlock(blockNdx);
		bool					isArray			= block.isArray();
		std::string				instanceName	= string(block.getBlockName()) + (isArray ? "[0]" : "");
		int						refBlockNdx		= refLayout.getBlockIndex(instanceName.c_str());
		int						cmpBlockNdx		= cmpLayout.getBlockIndex(instanceName.c_str());
		bool					isUsed			= (block.getFlags() & (DECLARE_VERTEX|DECLARE_FRAGMENT)) != 0;

		if ((block.getFlags() & LAYOUT_SHARED) == 0)
			continue; // Not shared layout.

		DE_ASSERT(refBlockNdx >= 0);

		if (cmpBlockNdx < 0)
		{
			// Not found, should it?
			if (isUsed)
			{
				log << TestLog::Message << "Error: Uniform block '" << instanceName << "' not found" << TestLog::EndMessage;
				isOk = false;
			}

			continue; // Skip block.
		}

		const BlockLayoutEntry&		refBlockLayout	= refLayout.blocks[refBlockNdx];
		const BlockLayoutEntry&		cmpBlockLayout	= cmpLayout.blocks[cmpBlockNdx];

		if (refBlockLayout.activeUniformIndices.size() != cmpBlockLayout.activeUniformIndices.size())
		{
			log << TestLog::Message << "Error: Number of active uniforms differ in block '" << instanceName
				<< "' (expected " << refBlockLayout.activeUniformIndices.size()
				<< ", got " << cmpBlockLayout.activeUniformIndices.size()
				<< ")" << TestLog::EndMessage;
			isOk = false;
		}

		for (vector<int>::const_iterator ndxIter = refBlockLayout.activeUniformIndices.begin(); ndxIter != refBlockLayout.activeUniformIndices.end(); ndxIter++)
		{
			const UniformLayoutEntry&	refEntry	= refLayout.uniforms[*ndxIter];
			int							cmpEntryNdx	= cmpLayout.getUniformIndex(refEntry.name.c_str());

			if (cmpEntryNdx < 0)
			{
				log << TestLog::Message << "Error: Uniform '" << refEntry.name << "' not found" << TestLog::EndMessage;
				isOk = false;
				continue;
			}

			const UniformLayoutEntry&	cmpEntry	= cmpLayout.uniforms[cmpEntryNdx];

			if (refEntry.type		!= cmpEntry.type	||
				refEntry.size		!= cmpEntry.size	||
				refEntry.isRowMajor	!= cmpEntry.isRowMajor)
			{
				log << TestLog::Message << "Error: Layout mismatch in '" << refEntry.name << "':\n"
					<< "  expected: type = " << glu::getDataTypeName(refEntry.type) << ", size = " << refEntry.size << ", row major = " << (refEntry.isRowMajor ? "true" : "false") << "\n"
					<< "  got: type = " << glu::getDataTypeName(cmpEntry.type) << ", size = " << cmpEntry.size << ", row major = " << (cmpEntry.isRowMajor ? "true" : "false")
					<< TestLog::EndMessage;
				isOk = false;
			}
		}
	}

	return isOk;
}

bool UniformBlockCase::compareTypes (const UniformLayout& refLayout, const UniformLayout& cmpLayout) const
{
	TestLog&	log			= m_testCtx.getLog();
	bool		isOk		= true;
	int			numBlocks	= m_interface.getNumUniformBlocks();

	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
	{
		const UniformBlock&		block			= m_interface.getUniformBlock(blockNdx);
		bool					isArray			= block.isArray();
		int						numInstances	= isArray ? block.getArraySize() : 1;

		for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
		{
			std::ostringstream instanceName;

			instanceName << block.getBlockName();
			if (isArray)
				instanceName << "[" << instanceNdx << "]";

			int cmpBlockNdx = cmpLayout.getBlockIndex(instanceName.str().c_str());

			if (cmpBlockNdx < 0)
				continue;

			const BlockLayoutEntry& cmpBlockLayout = cmpLayout.blocks[cmpBlockNdx];

			for (vector<int>::const_iterator ndxIter = cmpBlockLayout.activeUniformIndices.begin(); ndxIter != cmpBlockLayout.activeUniformIndices.end(); ndxIter++)
			{
				const UniformLayoutEntry&	cmpEntry	= cmpLayout.uniforms[*ndxIter];
				int							refEntryNdx	= refLayout.getUniformIndex(cmpEntry.name.c_str());

				if (refEntryNdx < 0)
				{
					log << TestLog::Message << "Error: Uniform '" << cmpEntry.name << "' not found in reference layout" << TestLog::EndMessage;
					isOk = false;
					continue;
				}

				const UniformLayoutEntry&	refEntry	= refLayout.uniforms[refEntryNdx];

				// \todo [2012-11-26 pyry] Should we check other properties as well?
				if (refEntry.type != cmpEntry.type)
				{
					log << TestLog::Message << "Error: Uniform type mismatch in '" << refEntry.name << "':\n"
						<< "  expected: " << glu::getDataTypeName(refEntry.type) << "\n"
						<< "  got: " << glu::getDataTypeName(cmpEntry.type)
						<< TestLog::EndMessage;
					isOk = false;
				}
			}
		}
	}

	return isOk;
}

bool UniformBlockCase::checkLayoutIndices (const UniformLayout& layout) const
{
	TestLog&	log			= m_testCtx.getLog();
	int			numUniforms	= (int)layout.uniforms.size();
	int			numBlocks	= (int)layout.blocks.size();
	bool		isOk		= true;

	// Check uniform block indices.
	for (int uniformNdx = 0; uniformNdx < numUniforms; uniformNdx++)
	{
		const UniformLayoutEntry& uniform = layout.uniforms[uniformNdx];

		if (uniform.blockNdx < 0 || !deInBounds32(uniform.blockNdx, 0, numBlocks))
		{
			log << TestLog::Message << "Error: Invalid block index in uniform '" << uniform.name << "'" << TestLog::EndMessage;
			isOk = false;
		}
	}

	// Check active uniforms.
	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
	{
		const BlockLayoutEntry& block = layout.blocks[blockNdx];

		for (vector<int>::const_iterator uniformIter = block.activeUniformIndices.begin(); uniformIter != block.activeUniformIndices.end(); uniformIter++)
		{
			if (!deInBounds32(*uniformIter, 0, numUniforms))
			{
				log << TestLog::Message << "Error: Invalid active uniform index " << *uniformIter << " in block '" << block.name << "'" << TestLog::EndMessage;
				isOk = false;
			}
		}
	}

	return isOk;
}

bool UniformBlockCase::checkLayoutBounds (const UniformLayout& layout) const
{
	TestLog&	log			= m_testCtx.getLog();
	int			numUniforms	= (int)layout.uniforms.size();
	bool		isOk		= true;

	for (int uniformNdx = 0; uniformNdx < numUniforms; uniformNdx++)
	{
		const UniformLayoutEntry& uniform = layout.uniforms[uniformNdx];

		if (uniform.blockNdx < 0)
			continue;

		const BlockLayoutEntry&		block			= layout.blocks[uniform.blockNdx];
		bool						isMatrix		= glu::isDataTypeMatrix(uniform.type);
		int							numVecs			= isMatrix ? (uniform.isRowMajor ? glu::getDataTypeMatrixNumRows(uniform.type) : glu::getDataTypeMatrixNumColumns(uniform.type)) : 1;
		int							numComps		= isMatrix ? (uniform.isRowMajor ? glu::getDataTypeMatrixNumColumns(uniform.type) : glu::getDataTypeMatrixNumRows(uniform.type)) : glu::getDataTypeScalarSize(uniform.type);
		int							numElements		= uniform.size;
		const int					compSize		= sizeof(deUint32);
		int							vecSize			= numComps*compSize;

		int							minOffset		= 0;
		int							maxOffset		= 0;

		// For negative strides.
		minOffset	= de::min(minOffset, (numVecs-1)*uniform.matrixStride);
		minOffset	= de::min(minOffset, (numElements-1)*uniform.arrayStride);
		minOffset	= de::min(minOffset, (numElements-1)*uniform.arrayStride + (numVecs-1)*uniform.matrixStride);

		maxOffset	= de::max(maxOffset, vecSize);
		maxOffset	= de::max(maxOffset, (numVecs-1)*uniform.matrixStride + vecSize);
		maxOffset	= de::max(maxOffset, (numElements-1)*uniform.arrayStride + vecSize);
		maxOffset	= de::max(maxOffset, (numElements-1)*uniform.arrayStride + (numVecs-1)*uniform.matrixStride + vecSize);

		if (uniform.offset+minOffset < 0 || uniform.offset+maxOffset > block.size)
		{
			log << TestLog::Message << "Error: Uniform '" << uniform.name << "' out of block bounds" << TestLog::EndMessage;
			isOk = false;
		}
	}

	return isOk;
}

bool UniformBlockCase::checkIndexQueries (deUint32 program, const UniformLayout& layout) const
{
	tcu::TestLog&				log			= m_testCtx.getLog();
	const glw::Functions&		gl			= m_renderCtx.getFunctions();
	bool						allOk		= true;

	// \note Spec mandates that uniform blocks are assigned consecutive locations from 0
	//		 to ACTIVE_UNIFORM_BLOCKS. BlockLayoutEntries are stored in that order in UniformLayout.
	for (int blockNdx = 0; blockNdx < (int)layout.blocks.size(); blockNdx++)
	{
		const BlockLayoutEntry&		block		= layout.blocks[blockNdx];
		const int					queriedNdx	= gl.getUniformBlockIndex(program, block.name.c_str());

		if (queriedNdx != blockNdx)
		{
			log << TestLog::Message << "ERROR: glGetUniformBlockIndex(" << block.name << ") returned " << queriedNdx << ", expected " << blockNdx << "!" << TestLog::EndMessage;
			allOk = false;
		}

		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex()");
	}

	return allOk;
}

bool UniformBlockCase::render (deUint32 program) const
{
	tcu::TestLog&				log				= m_testCtx.getLog();
	const glw::Functions&		gl				= m_renderCtx.getFunctions();
	de::Random					rnd				(deStringHash(getName()));
	const tcu::RenderTarget&	renderTarget	= m_renderCtx.getRenderTarget();
	const int					viewportW		= de::min(renderTarget.getWidth(),	128);
	const int					viewportH		= de::min(renderTarget.getHeight(),	128);
	const int					viewportX		= rnd.getInt(0, renderTarget.getWidth()		- viewportW);
	const int					viewportY		= rnd.getInt(0, renderTarget.getHeight()	- viewportH);

	gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
	gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	// Draw
	{
		const float position[] =
		{
			-1.0f, -1.0f, 0.0f, 1.0f,
			-1.0f, +1.0f, 0.0f, 1.0f,
			+1.0f, -1.0f, 0.0f, 1.0f,
			+1.0f, +1.0f, 0.0f, 1.0f
		};
		const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };

		gl.viewport(viewportX, viewportY, viewportW, viewportH);

		glu::VertexArrayBinding posArray = glu::va::Float("a_position", 4, 4, 0, &position[0]);
		glu::draw(m_renderCtx, program, 1, &posArray,
				  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
	}

	// Verify that all pixels are white.
	{
		tcu::Surface	pixels			(viewportW, viewportH);
		int				numFailedPixels = 0;

		glu::readPixels(m_renderCtx, viewportX, viewportY, pixels.getAccess());
		GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels failed");

		for (int y = 0; y < pixels.getHeight(); y++)
		{
			for (int x = 0; x < pixels.getWidth(); x++)
			{
				if (pixels.getPixel(x, y) != tcu::RGBA::white)
					numFailedPixels += 1;
			}
		}

		if (numFailedPixels > 0)
		{
			log << TestLog::Image("Image", "Rendered image", pixels);
			log << TestLog::Message << "Image comparison failed, got " << numFailedPixels << " non-white pixels" << TestLog::EndMessage;
		}

		return numFailedPixels == 0;
	}
}

} // gls
} // deqp
