/*-------------------------------------------------------------------------
 * 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 "deInt32.h"
#include "deMemory.h"
#include "deRandom.hpp"
#include "deString.h"
#include "deStringUtil.hpp"

#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)*(int)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*(int)sizeof(deUint32);

		case glu::TYPE_FLOAT_VEC2:
		case glu::TYPE_INT_VEC2:
		case glu::TYPE_UINT_VEC2:
		case glu::TYPE_BOOL_VEC2:	return 2*(int)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*(int)sizeof(deUint32);

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

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

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

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

int computeStd140BaseAlignment (const VarType& type)
{
	const int vec4Alignment = (int)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
