/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2015 The Khronos Group Inc.
 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 * Copyright (c) 2016 The Android Open Source Project
 * Copyright (c) 2018 The Khronos Group Inc.
 *
 * 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 Vulkan Transform Feedback Fuzz Layout Tests
 *//*--------------------------------------------------------------------*/

#include "vktTransformFeedbackFuzzLayoutCase.hpp"

#include "vkPrograms.hpp"

#include "gluVarType.hpp"
#include "tcuTestLog.hpp"
#include "tcuSurface.hpp"
#include "deRandom.hpp"
#include "deStringUtil.hpp"

#include "tcuTextureUtil.hpp"
#include "deSharedPtr.hpp"
#include "deFloat16.h"

#include "vkMemUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkRef.hpp"
#include "vkRefUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"

#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <iomanip>

namespace vkt
{
namespace TransformFeedback
{

using namespace vk;

typedef std::map<int, int> BufferGeneralMapping;

typedef std::pair<int, int>				UsedRange;
typedef std::vector<UsedRange>			UsedRangeList;
typedef std::map<int, UsedRangeList>	BufferUsedRangesMap;

// 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, deUint32 flags)
	: m_type	(TYPE_STRUCT)
	, m_flags	(flags)
{
	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.

	VarType *oldElementType = m_type == TYPE_ARRAY ? m_data.array.elementType : DE_NULL;

	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;

	delete oldElementType;

	return *this;
}

// StructType implementation.
void StructType::addMember (const std::string& name, const VarType& type, deUint32 flags)
{
	m_members.push_back(StructMember(name, type, flags));
}

// InterfaceBlockMember implementation.
InterfaceBlockMember::InterfaceBlockMember (const std::string& name, const VarType& type, deUint32 flags)
	: m_name	(name)
	, m_type	(type)
	, m_flags	(flags)
{
}

// InterfaceBlock implementation.
InterfaceBlock::InterfaceBlock (const std::string& blockName)
	: m_blockName	(blockName)
	, m_xfbBuffer	(0)
	, m_arraySize	(0)
	, m_flags		(0)
{
}

std::ostream& operator<< (std::ostream& stream, const BlockLayoutEntry& entry)
{
	stream << entry.name << " { name = " << entry.name
		   << ", buffer = " << entry.xfbBuffer
		   << ", offset = " << entry.xfbOffset
		   << ", size = " << entry.xfbSize
		   << ", blockDeclarationNdx = " << entry.blockDeclarationNdx
		   << ", instanceNdx = " << entry.instanceNdx
		   << ", activeInterfaceIndices = [";

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

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

std::ostream& operator<< (std::ostream& stream, const InterfaceLayoutEntry& entry)
{
	stream << entry.name << " { type = " << glu::getDataTypeName(entry.type)
		   << ", arraySize = " << entry.arraySize
		   << ", blockNdx = " << entry.blockLayoutNdx
		   << ", offset = " << entry.offset
		   << ", arrayStride = " << entry.arrayStride
		   << ", matrixStride = " << entry.matrixStride
		   << " }";

	return stream;
}

std::ostream& operator<< (std::ostream& str, const InterfaceLayout& layout)
{
	const int	numBlocks	= (int)layout.blocks.size();

	str << "Blocks:" << std::endl;
	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
		str << layout.blocks[blockNdx] << std::endl;
	str << std::endl;

	str << "Interfaces:" << std::endl;
	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
	{
		int		numEntries	= (int)layout.blocks[blockNdx].activeInterfaceIndices.size();

		for (int entryNdx = 0; entryNdx < numEntries; entryNdx++)
		{
			const InterfaceLayoutEntry&	entry	= layout.interfaces[layout.blocks[blockNdx].activeInterfaceIndices[entryNdx]];

			str << blockNdx << ":" << entryNdx << " " << entry << std::endl;
		}
	}
	str << std::endl;

	return str;
}

int InterfaceLayout::getInterfaceLayoutIndex (int blockNdx, const std::string& name) const
{
	for (int ndx = 0; ndx < (int)interfaces.size(); ndx++)
	{
		if (blocks[interfaces[ndx].blockLayoutNdx].blockDeclarationNdx == blockNdx && interfaces[ndx].name == name)
			return ndx;
	}

	return -1;
}

int InterfaceLayout::getBlockLayoutIndex (int blockNdx, int instanceNdx) const
{
	for (int ndx = 0; ndx < (int)blocks.size(); ndx++)
	{
		if (blocks[ndx].blockDeclarationNdx == blockNdx && blocks[ndx].instanceNdx == instanceNdx)
			return ndx;
	}

	return -1;
}

// ShaderInterface implementation.

ShaderInterface::ShaderInterface (void)
{
}

ShaderInterface::~ShaderInterface (void)
{
}

StructType& ShaderInterface::allocStruct (const std::string& name)
{
	m_structs.push_back(StructTypeSP(new StructType(name)));
	return *m_structs.back();
}

struct StructNameEquals
{
	std::string name;

	StructNameEquals (const std::string& name_) : name(name_) {}

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

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

InterfaceBlock& ShaderInterface::allocBlock (const std::string& name)
{
	m_interfaceBlocks.push_back(InterfaceBlockSP(new InterfaceBlock(name)));

	return *m_interfaceBlocks.back();
}

namespace // Utilities
{

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

void dumpBytes (std::ostream& str, const std::string& msg, const void* dataBytes, size_t size, const void* dataMask = DE_NULL)
{
	const deUint8*		data	= (const deUint8*)dataBytes;
	const deUint8*		mask	= (const deUint8*)dataMask;
	std::ios::fmtflags	flags;

	str << msg;

	flags = str.flags ( std::ios::hex | std::ios::uppercase );
	{
		for (size_t i = 0; i < size; i++)
		{
			if (i%16 == 0) str << std::endl << std::setfill('0') << std::setw(8) << i << ":";
			else if (i%8 == 0) str << "  ";
			else if (i%4 == 0) str << " ";

			str << " " << std::setfill('0') << std::setw(2);

			if (mask == DE_NULL || mask[i] != 0)
				str << (deUint32)data[i];
			else
				str << "__";
		}
		str << std::endl << std::endl;
	}
	str.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;
	deUint32 buffer;
	deUint32 stride;
	deUint32 offset;

	LayoutFlagsFmt	(const deUint32	flags_,
					 const deUint32	buffer_,
					 const deUint32	stride_,
					 const deUint32	offset_)
		: flags		(flags_)
		, buffer	(buffer_)
		, stride	(stride_)
		, offset	(offset_)
	{
	}
};

std::ostream& operator<< (std::ostream& str, const LayoutFlagsFmt& fmt)
{
	static const struct
	{
		deUint32	bit;
		const char*	token;
	} bitDesc[] =
	{
		{ LAYOUT_XFBBUFFER,	"xfb_buffer"	},
		{ LAYOUT_XFBOFFSET,	"xfb_offset"	},
		{ LAYOUT_XFBSTRIDE,	"xfb_stride"	},
	};

	deUint32 remBits = fmt.flags;
	for (int descNdx = 0; descNdx < DE_LENGTH_OF_ARRAY(bitDesc); descNdx++)
	{
		if (remBits & bitDesc[descNdx].bit)
		{
			str << bitDesc[descNdx].token;

			if (bitDesc[descNdx].bit == LAYOUT_XFBBUFFER) str << " = " << fmt.buffer;
			if (bitDesc[descNdx].bit == LAYOUT_XFBOFFSET) str << " = " << fmt.offset;
			if (bitDesc[descNdx].bit == LAYOUT_XFBSTRIDE) str << " = " << fmt.stride;

			remBits &= ~bitDesc[descNdx].bit;

			if (remBits != 0)
				str << ", ";
		}
	}
	DE_ASSERT(remBits == 0);
	return str;
}

std::ostream& operator<< (std::ostream& str, const DeviceSizeVector& vec)
{
	str << " [";

	for (size_t vecNdx = 0; vecNdx < vec.size(); vecNdx++)
		str << (deUint64)vec[vecNdx] << (vecNdx + 1 < vec.size() ? ", " : "]");

	return str;
}

// Layout computation.

int getDataTypeByteSize (glu::DataType type)
{
	if (getDataTypeScalarType(type) == glu::TYPE_DOUBLE)
	{
		return glu::getDataTypeScalarSize(type)*(int)sizeof(deUint64);
	}
	else
	{
		return glu::getDataTypeScalarSize(type)*(int)sizeof(deUint32);
	}
}

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

	return getDataTypeByteSize(type);
}

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

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

	return deAlign32(baseStride, vec4Alignment);
}

int computeInterfaceBlockMemberAlignment (const VarType& type)
{
	if (type.isBasicType())
	{
		glu::DataType basicType = type.getBasicType();

		if (glu::isDataTypeMatrix(basicType) || isDataTypeVector(basicType))
			basicType = glu::getDataTypeScalarType(basicType);

		switch (basicType)
		{
			case glu::TYPE_FLOAT:
			case glu::TYPE_INT:
			case glu::TYPE_UINT:	return sizeof(deUint32);
			case glu::TYPE_DOUBLE:	return sizeof(deUint64);
			default:				TCU_THROW(InternalError, "Invalid type");
		}
	}
	else if (type.isArrayType())
	{
		return computeInterfaceBlockMemberAlignment(type.getElementType());
	}
	else if (type.isStructType())
	{
		int maxAlignment = 0;

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

		return maxAlignment;
	}
	else
		TCU_THROW(InternalError, "Invalid type");
}

void createMask (void* maskBasePtr, const InterfaceLayoutEntry& entry, const void* basePtr0, const void* basePtr)
{
	const glu::DataType	scalarType	= glu::getDataTypeScalarType(entry.type);
	const int			scalarSize	= glu::getDataTypeScalarSize(entry.type);
	const bool			isMatrix	= glu::isDataTypeMatrix(entry.type);
	const int			numVecs		= isMatrix ? glu::getDataTypeMatrixNumColumns(entry.type) : 1;
	const int			vecSize		= scalarSize / numVecs;
	const bool			isArray		= entry.arraySize > 1;
	const size_t		compSize	= getDataTypeByteSize(scalarType);

	DE_ASSERT(scalarSize%numVecs == 0);

	for (int elemNdx = 0; elemNdx < entry.arraySize; 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++)
			{
				const deUint8*	compPtr		= vecPtr + compSize*compNdx;
				const size_t	offset		= compPtr - (deUint8*)basePtr0;
				deUint8*		maskPtr		= (deUint8*)maskBasePtr + offset;

				switch (scalarType)
				{
					case glu::TYPE_DOUBLE:
					case glu::TYPE_FLOAT:
					case glu::TYPE_INT:
					case glu::TYPE_UINT:
					{
						for (size_t ndx = 0; ndx < compSize; ++ndx)
							++maskPtr[ndx];

						break;
					}
					default:
						DE_ASSERT(false);
				}
			}
		}
	}
}

std::vector<deUint8> createMask (const InterfaceLayout& layout, const std::map<int, void*>& blockPointers, const void* basePtr0, const size_t baseSize)
{
	std::vector<deUint8>	mask		(baseSize, 0);
	const 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].activeInterfaceIndices.size();

		for (int entryNdx = 0; entryNdx < numEntries; entryNdx++)
		{
			const InterfaceLayoutEntry&	entry	= layout.interfaces[layout.blocks[blockNdx].activeInterfaceIndices[entryNdx]];

			if (entry.validate)
				createMask (&mask[0], entry, basePtr0, basePtr);
		}
	}

	return mask;
}

int computeInterfaceBlockAlignment(const InterfaceBlock& interfaceBlock)
{
	int baseAlignment = 0;

	for (InterfaceBlock::ConstIterator memberIter = interfaceBlock.begin(); memberIter != interfaceBlock.end(); memberIter++)
	{
		const InterfaceBlockMember& member = *memberIter;

		baseAlignment = std::max(baseAlignment, computeInterfaceBlockMemberAlignment(member.getType()));
	}

	return baseAlignment;
}

static inline bool isOverlaped(const int a1, const int b1, const int a2, const int b2)
{
	DE_ASSERT(b1 > 0 && b2 > 0);

	const int b1s = b1 - 1;
	const int b2s = b2 - 1;

	return	deInRange32(a1,  a2, b2s) ||
			deInRange32(b1s, a2, b2s) ||
			deInRange32(a2,  a1, b1s) ||
			deInRange32(b2s, a1, b1s);
}

void computeXfbLayout (InterfaceLayout& layout, int& curOffset, int& curLocation, int curBlockNdx, const std::string& curPrefix, const VarType& type, deUint32 layoutFlags)
{
	const int	locationAlignSize	= 16;
	const bool	validate			= 0 == (layoutFlags & (FIELD_MISSING|FIELD_UNASSIGNED));
	int			baseAlignment		= computeInterfaceBlockMemberAlignment(type);

	DE_ASSERT(baseAlignment == sizeof(deUint32) || baseAlignment == sizeof(deUint64));

	curOffset = deAlign32(curOffset, baseAlignment);

	if (type.isBasicType())
	{
		const glu::DataType		basicType				= type.getBasicType();
		int						fieldSize				= 0;
		int						fieldSizeForLocation	= 0;
		InterfaceLayoutEntry	entry;

		entry.name				= curPrefix;
		entry.type				= basicType;
		entry.arraySize			= 1;
		entry.arrayStride		= 0;
		entry.matrixStride		= 0;
		entry.blockLayoutNdx	= curBlockNdx;
		entry.locationNdx		= 0;
		entry.validate			= validate;

		if (glu::isDataTypeMatrix(basicType))
		{
			// Array of vectors
			const int				vecSize				= glu::getDataTypeMatrixNumRows(basicType);
			const int				numVecs				= glu::getDataTypeMatrixNumColumns(basicType);
			const glu::DataType		elemType			= glu::getDataTypeScalarType(basicType);
			const int				stride				= getDataTypeArrayStride(glu::getDataTypeVector(elemType, vecSize));
			const int				strideForLocation	= getDataTypeArrayStrideForLocation(glu::getDataTypeVector(elemType, vecSize));

			entry.matrixStride		= stride;

			fieldSize				= numVecs * stride;
			fieldSizeForLocation	= numVecs * strideForLocation;
		}
		else
		{
			// Scalar or vector.
			fieldSize				= getDataTypeByteSize(basicType);
			fieldSizeForLocation	= deAlign32(fieldSize, locationAlignSize);
		}

		entry.offset		= curOffset;
		entry.locationNdx	= curLocation;

		curOffset += fieldSize;
		curLocation += deDivRoundUp32(fieldSizeForLocation, locationAlignSize);

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

		if (elemType.isBasicType() && !glu::isDataTypeMatrix(elemType.getBasicType()))
		{
			// Array of scalars or vectors.
			const glu::DataType		elemBasicType			= elemType.getBasicType();
			const int				stride					= getDataTypeArrayStride(elemBasicType);
			const int				fieldSize				= stride * type.getArraySize();
			const int				strideForLocation		= getDataTypeArrayStrideForLocation(elemBasicType);
			const int				fieldSizeForLocation	= strideForLocation * type.getArraySize();
			InterfaceLayoutEntry	entry;

			entry.name				= curPrefix + "[0]"; // Array interfaces are always postfixed with [0]
			entry.type				= elemBasicType;
			entry.blockLayoutNdx	= curBlockNdx;
			entry.offset			= curOffset;
			entry.arraySize			= type.getArraySize();
			entry.arrayStride		= stride;
			entry.matrixStride		= 0;
			entry.locationNdx		= curLocation;
			entry.validate			= validate;

			curOffset += fieldSize;
			curLocation += deDivRoundUp32(fieldSizeForLocation, locationAlignSize);

			layout.interfaces.push_back(entry);
		}
		else if (elemType.isBasicType() && glu::isDataTypeMatrix(elemType.getBasicType()))
		{
			// Array of matrices.
			const glu::DataType		elemBasicType			= elemType.getBasicType();
			const glu::DataType		scalarType				= glu::getDataTypeScalarType(elemBasicType);
			const int				vecSize					= glu::getDataTypeMatrixNumRows(elemBasicType);
			const int				numVecs					= glu::getDataTypeMatrixNumColumns(elemBasicType);
			const int				stride					= getDataTypeArrayStride(glu::getDataTypeVector(scalarType, vecSize));
			const int				fieldSize				= numVecs * type.getArraySize() * stride;
			const int				strideForLocation		= getDataTypeArrayStrideForLocation(glu::getDataTypeVector(scalarType, vecSize));
			const int				fieldSizeForLocation	= numVecs * type.getArraySize() * strideForLocation;
			InterfaceLayoutEntry	entry;

			entry.name				= curPrefix + "[0]"; // Array interfaces are always postfixed with [0]
			entry.type				= elemBasicType;
			entry.blockLayoutNdx	= curBlockNdx;
			entry.offset			= curOffset;
			entry.arraySize			= type.getArraySize();
			entry.arrayStride		= stride*numVecs;
			entry.matrixStride		= stride;
			entry.locationNdx		= curLocation;
			entry.validate			= validate;

			curOffset += fieldSize;
			curLocation += deDivRoundUp32(fieldSizeForLocation, locationAlignSize);

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

			for (int elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++)
				computeXfbLayout(layout, curOffset, curLocation, 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++)
			computeXfbLayout(layout, curOffset, curLocation, curBlockNdx, curPrefix + "." + memberIter->getName(), memberIter->getType(), (memberIter->getFlags() | layoutFlags) & FIELD_OPTIONS);

		curOffset = deAlign32(curOffset, baseAlignment);
	}
}

void computeXfbLayout (InterfaceLayout& layout, ShaderInterface& shaderInterface, BufferGeneralMapping& perBufferXfbOffsets, deUint32& locationsUsed)
{
	const int				numInterfaceBlocks	= shaderInterface.getNumInterfaceBlocks();
	int						curLocation			= 0;
	BufferGeneralMapping	bufferAlignments;
	BufferGeneralMapping	buffersList;
	BufferGeneralMapping	bufferStrideGroup;
	BufferUsedRangesMap		bufferUsedRanges;

	for (int blockNdx = 0; blockNdx < numInterfaceBlocks; blockNdx++)
	{
		const InterfaceBlock&	interfaceBlock	= shaderInterface.getInterfaceBlock(blockNdx);
		const int				xfbBuffer		= interfaceBlock.getXfbBuffer();

		buffersList[xfbBuffer] = 1;
		bufferStrideGroup[xfbBuffer] = xfbBuffer;
	}

	for (BufferGeneralMapping::const_iterator xfbBuffersIter = buffersList.begin(); xfbBuffersIter != buffersList.end(); xfbBuffersIter++)
	{
		const int	xfbBufferAnalyzed	= xfbBuffersIter->first;

		for (int blockNdx = 0; blockNdx < numInterfaceBlocks; blockNdx++)
		{
			InterfaceBlock&	interfaceBlock	= shaderInterface.getInterfaceBlockForModify(blockNdx);

			if (interfaceBlock.getXfbBuffer() == xfbBufferAnalyzed)
			{
				const bool			hasInstanceName		= interfaceBlock.hasInstanceName();
				const std::string	blockPrefix			= hasInstanceName ? (interfaceBlock.getBlockName() + ".") : "";
				const int			numInstances		= interfaceBlock.isArray() ? interfaceBlock.getArraySize() : 1;
				int					activeBlockNdx		= (int)layout.blocks.size();
				int					startInterfaceNdx	= (int)layout.interfaces.size();
				int					startLocationNdx	= (int)curLocation;
				int					interfaceAlignement	= computeInterfaceBlockAlignment(interfaceBlock);
				int					curOffset			= 0;
				int					blockSize			= 0;

				do
				{
					const int		xfbFirstInstanceBuffer			= interfaceBlock.getXfbBuffer();
					int&			xfbFirstInstanceBufferOffset	= perBufferXfbOffsets[xfbFirstInstanceBuffer];
					const int		savedLayoutInterfacesNdx		= (int)layout.interfaces.size();
					const int		savedCurOffset					= curOffset;
					const int		savedCurLocation				= curLocation;
					UsedRangeList&	usedRanges						= bufferUsedRanges[xfbFirstInstanceBuffer];
					bool			fitIntoBuffer					= true;

					// GLSL 4.60
					// Further, if applied to an aggregate containing a double, the offset must also be a multiple of 8,
					// and the space taken in the buffer will be a multiple of 8.
					xfbFirstInstanceBufferOffset	= deAlign32(xfbFirstInstanceBufferOffset, interfaceAlignement);

					for (InterfaceBlock::ConstIterator memberIter = interfaceBlock.begin(); memberIter != interfaceBlock.end(); memberIter++)
					{
						const InterfaceBlockMember& member	= *memberIter;

						computeXfbLayout(layout, curOffset, curLocation, activeBlockNdx, blockPrefix + member.getName(), member.getType(), member.getFlags() & FIELD_OPTIONS);
					}

					// GLSL 4.60
					// Further, if applied to an aggregate containing a double, the offset must also be a multiple of 8,
					// and the space taken in the buffer will be a multiple of 8.
					blockSize	= deAlign32(curOffset, interfaceAlignement);

					// Overlapping check
					for (UsedRangeList::const_iterator	usedRangeIt = usedRanges.begin();
														usedRangeIt != usedRanges.end();
														++usedRangeIt)
					{
						const int&	usedRangeStart	= usedRangeIt->first;
						const int&	usedRangeEnd	= usedRangeIt->second;
						const int	genRangeStart	= xfbFirstInstanceBufferOffset;
						const int	genRangeEnd		= xfbFirstInstanceBufferOffset + blockSize;

						// Validate if block has overlapping
						if (isOverlaped(genRangeStart, genRangeEnd, usedRangeStart, usedRangeEnd))
						{
							// Restart from obstacle interface end
							fitIntoBuffer					= false;

							DE_ASSERT(xfbFirstInstanceBufferOffset > usedRangeEnd);

							// Bump up interface start to the end of used range
							xfbFirstInstanceBufferOffset	= usedRangeEnd;

							// Undo allocation
							curOffset						= savedCurOffset;
							curLocation						= savedCurLocation;

							layout.interfaces.resize(savedLayoutInterfacesNdx);
						}
					}

					if (fitIntoBuffer)
						break;
				} while (true);

				const int	xfbFirstInstanceBuffer			= interfaceBlock.getXfbBuffer();
				const int	xfbFirstInstanceBufferOffset	= perBufferXfbOffsets[xfbFirstInstanceBuffer];
				const int	endInterfaceNdx					= (int)layout.interfaces.size();
				const int	blockSizeInLocations			= curLocation - startLocationNdx;

				curLocation -= blockSizeInLocations;

				if (numInstances > 1)
					interfaceBlock.setFlag(LAYOUT_XFBSTRIDE);

				// 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();
					const int			xfbBuffer		= xfbFirstInstanceBuffer + instanceNdx;
					int&				xfbBufferOffset	= perBufferXfbOffsets[xfbBuffer];

					DE_ASSERT(xfbBufferOffset <= xfbFirstInstanceBufferOffset);

					xfbBufferOffset					= xfbFirstInstanceBufferOffset;

					blockEntry.name					= interfaceBlock.getBlockName();
					blockEntry.xfbBuffer			= xfbBuffer;
					blockEntry.xfbOffset			= xfbBufferOffset;
					blockEntry.xfbSize				= blockSize;
					blockEntry.blockDeclarationNdx	= blockNdx;
					blockEntry.instanceNdx			= instanceNdx;
					blockEntry.locationNdx			= curLocation;
					blockEntry.locationSize			= blockSizeInLocations;

					xfbBufferOffset	+= blockSize;
					curLocation		+= blockSizeInLocations;

					// Compute active interface set for block.
					for (int interfaceNdx = startInterfaceNdx; interfaceNdx < endInterfaceNdx; interfaceNdx++)
						blockEntry.activeInterfaceIndices.push_back(interfaceNdx);

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

					bufferUsedRanges[xfbBuffer].push_back(UsedRange(blockEntry.xfbOffset, blockEntry.xfbOffset + blockEntry.xfbSize));

					// Store maximum per-buffer alignment
					bufferAlignments[xfbBuffer] = std::max(interfaceAlignement, bufferAlignments[xfbBuffer]);

					// Buffers bound through instanced arrays must have same stride (and alignment)
					bufferStrideGroup[xfbBuffer] = bufferStrideGroup[xfbFirstInstanceBuffer];
				}
			}
		}
	}

	// All XFB buffers within group must have same stride
	{
		BufferGeneralMapping groupStride;

		for (BufferGeneralMapping::const_iterator xfbBuffersIter = perBufferXfbOffsets.begin(); xfbBuffersIter != perBufferXfbOffsets.end(); xfbBuffersIter++)
		{
			const int	xfbBuffer	= xfbBuffersIter->first;
			const int	xfbStride	= perBufferXfbOffsets[xfbBuffer];
			const int	group		= bufferStrideGroup[xfbBuffer];

			groupStride[group] = std::max(groupStride[group], xfbStride);
		}

		for (BufferGeneralMapping::const_iterator xfbBuffersIter = perBufferXfbOffsets.begin(); xfbBuffersIter != perBufferXfbOffsets.end(); xfbBuffersIter++)
		{
			const int	xfbBuffer	= xfbBuffersIter->first;
			const int	group		= bufferStrideGroup[xfbBuffer];

			perBufferXfbOffsets[xfbBuffer] = groupStride[group];
		}
	}

	// All XFB buffers within group must have same stride alignment
	{
		BufferGeneralMapping groupAlignment;

		for (BufferGeneralMapping::const_iterator xfbBuffersIter = perBufferXfbOffsets.begin(); xfbBuffersIter != perBufferXfbOffsets.end(); xfbBuffersIter++)
		{
			const int	xfbBuffer	= xfbBuffersIter->first;
			const int	group		= bufferStrideGroup[xfbBuffer];
			const int	xfbAlign	= bufferAlignments[xfbBuffer];

			groupAlignment[group] = std::max(groupAlignment[group], xfbAlign);
		}

		for (BufferGeneralMapping::const_iterator xfbBuffersIter = perBufferXfbOffsets.begin(); xfbBuffersIter != perBufferXfbOffsets.end(); xfbBuffersIter++)
		{
			const int	xfbBuffer	= xfbBuffersIter->first;
			const int	group		= bufferStrideGroup[xfbBuffer];

			bufferAlignments[xfbBuffer] = groupAlignment[group];
		}
	}

	// GLSL 4.60
	// If the buffer is capturing any outputs with double-precision components, the stride must be a multiple of 8, ...
	for (BufferGeneralMapping::const_iterator xfbBuffersIter = perBufferXfbOffsets.begin(); xfbBuffersIter != perBufferXfbOffsets.end(); xfbBuffersIter++)
	{
		const int	xfbBuffer	= xfbBuffersIter->first;
		const int	xfbAlign	= bufferAlignments[xfbBuffer];
		int&		xfbOffset	= perBufferXfbOffsets[xfbBuffer];

		xfbOffset	= deAlign32(xfbOffset, xfbAlign);
	}

	// Keep stride in interface blocks
	for (int blockNdx = 0; blockNdx < (int)layout.blocks.size(); blockNdx++)
		layout.blocks[blockNdx].xfbStride	= perBufferXfbOffsets[layout.blocks[blockNdx].xfbBuffer];

	locationsUsed = static_cast<deUint32>(curLocation);
}

// Value generator.

void generateValue (const InterfaceLayoutEntry& entry, void* basePtr, de::Random& rnd)
{
	const glu::DataType	scalarType	= glu::getDataTypeScalarType(entry.type);
	const int			scalarSize	= glu::getDataTypeScalarSize(entry.type);
	const bool			isMatrix	= glu::isDataTypeMatrix(entry.type);
	const int			numVecs		= isMatrix ? glu::getDataTypeMatrixNumColumns(entry.type) : 1;
	const int			vecSize		= scalarSize / numVecs;
	const bool			isArray		= entry.arraySize > 1;
	const size_t		compSize	= getDataTypeByteSize(scalarType);

	DE_ASSERT(scalarSize%numVecs == 0);

	for (int elemNdx = 0; elemNdx < entry.arraySize; 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;
				const int	sign	= rnd.getBool() ? +1 : -1;
				const int	value	= rnd.getInt(1, 127);

				switch (scalarType)
				{
					case glu::TYPE_DOUBLE:	*((double*)compPtr)		= (double)  (sign * value);	break;
					case glu::TYPE_FLOAT:	*((float*)compPtr)		= (float)   (sign * value);	break;
					case glu::TYPE_INT:		*((deInt32*)compPtr)	= (deInt32) (sign * value);	break;
					case glu::TYPE_UINT:	*((deUint32*)compPtr)	= (deUint32)(       value);	break;
					default:
						DE_ASSERT(false);
				}
			}
		}
	}
}

void generateValues (const InterfaceLayout& 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].activeInterfaceIndices.size();

		for (int entryNdx = 0; entryNdx < numEntries; entryNdx++)
		{
			const InterfaceLayoutEntry& entry = layout.interfaces[layout.blocks[blockNdx].activeInterfaceIndices[entryNdx]];

			if (entry.validate)
				generateValue(entry, basePtr, rnd);
		}
	}
}

// Shader generator.

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 std::string& name, int indentLevel, deUint32 unusedHints, deUint32 flagsMask, deUint32 buffer, deUint32 stride, deUint32 offset);
void	generateDeclaration			(std::ostringstream& src, const InterfaceBlockMember& member, int indentLevel, deUint32 buffer, deUint32 stride, deUint32 offset);
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.hasTypeName());
	generateFullDeclaration(src, structType, indentLevel);
	src << ";\n";
}

void generateFullDeclaration (std::ostringstream& src, const StructType& structType, int indentLevel)
{
	src << "struct";
	if (structType.hasTypeName())
		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() & FIELD_OPTIONS, ~LAYOUT_MASK, 0u, 0u, 0u);
	}

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

void generateLocalDeclaration (std::ostringstream& src, const StructType& structType, int /* indentLevel */)
{
	src << structType.getTypeName();
}

void generateLayoutAndPrecisionDeclaration (std::ostringstream& src, deUint32 flags, deUint32 buffer, deUint32 stride, deUint32 offset)
{
	if ((flags & LAYOUT_MASK) != 0)
		src << "layout(" << LayoutFlagsFmt(flags & LAYOUT_MASK, buffer, stride, offset) << ") ";

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

void generateDeclaration (std::ostringstream& src, const VarType& type, const std::string& name, int indentLevel, deUint32 fieldHints, deUint32 flagsMask, deUint32 buffer, deUint32 stride, deUint32 offset)
{
	if (fieldHints & FIELD_MISSING)
		src << "// ";

	generateLayoutAndPrecisionDeclaration(src, type.getFlags() & flagsMask, buffer, stride, offset);

	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();
		}

		generateLayoutAndPrecisionDeclaration(src, curType->getFlags() & flagsMask, buffer, stride, offset);

		if (curType->isBasicType())
			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 (fieldHints & FIELD_MISSING)
		src << " // missing field";
	else if (fieldHints & FIELD_UNASSIGNED)
		src << " // unassigned";

	src << "\n";
}

void generateDeclaration (std::ostringstream& src, const InterfaceBlockMember& member, int indentLevel, deUint32 buffer, deUint32 stride, deUint32 offset)
{
	if ((member.getFlags() & LAYOUT_MASK) != 0)
		src << "layout(" << LayoutFlagsFmt(member.getFlags() & LAYOUT_MASK, buffer, stride, offset) << ") ";

	generateDeclaration(src, member.getType(), member.getName(), indentLevel, member.getFlags() & FIELD_OPTIONS, ~0u, buffer, stride, offset);
}

deUint32 getBlockMemberOffset (int blockNdx, const InterfaceBlock& block, const InterfaceBlockMember& member, const InterfaceLayout& layout)
{
	std::ostringstream	name;
	const VarType*		curType = &member.getType();

	if (block.getInstanceName().length() != 0)
		name << block.getBlockName() << ".";	// \note InterfaceLayoutEntry uses block name rather than instance name

	name << member.getName();

	while (!curType->isBasicType())
	{
		if (curType->isArrayType())
		{
			name << "[0]";
			curType = &curType->getElementType();
		}

		if (curType->isStructType())
		{
			const StructType::ConstIterator firstMember = curType->getStruct().begin();

			name << "." << firstMember->getName();
			curType = &firstMember->getType();
		}
	}

	const int interfaceLayoutNdx = layout.getInterfaceLayoutIndex(blockNdx, name.str());
	DE_ASSERT(interfaceLayoutNdx >= 0);

	return layout.interfaces[interfaceLayoutNdx].offset;
}

template<typename T>
void semiShuffle (std::vector<T>& v)
{
	const std::vector<T>	src	= v;
	int						i	= -1;
	int						n	= static_cast<int>(src.size());

	v.clear();

	while (n)
	{
		i += n;
		v.push_back(src[i]);
		n = (n > 0 ? 1 - n : -1 - n);
	}
}

template<typename T>
//! \note Stores pointers to original elements
class Traverser
{
public:
	template<typename Iter>
	Traverser (const Iter beg, const Iter end, const bool shuffled)
	{
		for (Iter it = beg; it != end; ++it)
			m_elements.push_back(&(*it));

		if (shuffled)
			semiShuffle(m_elements);

		m_next = m_elements.begin();
	}

	T* next (void)
	{
		if (m_next != m_elements.end())
			return *m_next++;
		else
			return DE_NULL;
	}

private:
	typename std::vector<T*>					m_elements;
	typename std::vector<T*>::const_iterator	m_next;
};

void generateDeclaration (std::ostringstream& src, int blockNdx, const InterfaceBlock& block, const InterfaceLayout& layout, bool shuffleUniformMembers)
{
	const int indentOne		= 1;
	const int ndx			= layout.getBlockLayoutIndex(blockNdx, 0);
	const int locationNdx	= layout.blocks[ndx].locationNdx;
	const int xfbOffset		= layout.blocks[ndx].xfbOffset;
	const int xfbBuffer		= layout.blocks[ndx].xfbBuffer;
	const int xfbStride		= layout.blocks[ndx].xfbStride;

	src << "layout(";
	src << "location = " << locationNdx;
	if ((block.getFlags() & LAYOUT_MASK) != 0)
		src << ", " << LayoutFlagsFmt(block.getFlags() & LAYOUT_MASK, xfbBuffer, xfbStride, xfbOffset);
	src << ") out " << block.getBlockName();

	src << " //"
		<< " sizeInBytes=" << layout.blocks[ndx].xfbSize
		<< " sizeInLocations=" << layout.blocks[ndx].locationSize;

	src << "\n{\n";

	Traverser<const InterfaceBlockMember> interfaces(block.begin(), block.end(), shuffleUniformMembers);

	while (const InterfaceBlockMember* pUniform = interfaces.next())
	{
		src << Indent(indentOne);
		generateDeclaration(src, *pUniform, indentOne, xfbBuffer, xfbStride, xfbOffset + getBlockMemberOffset(blockNdx, block, *pUniform, layout));
	}

	src << "}";

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

	src << ";\n";
}

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

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

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

		DE_ASSERT(scalarType == glu::TYPE_FLOAT || scalarType == glu::TYPE_DOUBLE);

		// Constructed in column-wise order.
		for (int colNdx = 0; colNdx < numCols; colNdx++)
		{
			for (int rowNdx = 0; rowNdx < numRows; rowNdx++)
			{
				const deUint8*	compPtr	= elemPtr + (colNdx * entry.matrixStride + rowNdx * compSize);
				const float		compVal	= (scalarType == glu::TYPE_FLOAT) ? *((const float*)compPtr)
										: (scalarType == glu::TYPE_DOUBLE) ? (float)*((const double*)compPtr)
										: 0.0f;

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

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

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

			switch (scalarType)
			{
				case glu::TYPE_DOUBLE:	src << de::floatToString((float)(*((const double*)compPtr)), 1);	break;
				case glu::TYPE_FLOAT:	src << de::floatToString(*((const float*)compPtr), 1) << "f";		break;
				case glu::TYPE_INT:		src << *((const int*)compPtr);										break;
				case glu::TYPE_UINT:	src << *((const deUint32*)compPtr) << "u";							break;
				default:				DE_ASSERT(false && "Invalid type");									break;
			}
		}
	}

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

	return static_cast<int>(elemPtr - static_cast<const deUint8*>(basePtr));
}

void writeMatrixTypeSrc (int							columnCount,
						 int							rowCount,
						 std::string					type,
						 std::ostringstream&			src,
						 const std::string&				srcName,
						 const void*					basePtr,
						 const InterfaceLayoutEntry&	entry,
						 bool							vector)
{
	if (vector)	// generateTestSrcMatrixPerVec
	{
		for (int colNdx = 0; colNdx < columnCount; colNdx++)
		{
			src << "\t" << srcName << "[" << colNdx << "] = ";

			if (glu::isDataTypeMatrix(entry.type))
			{
				const glu::DataType	scalarType	= glu::getDataTypeScalarType(entry.type);
				const int			scalarSize	= glu::getDataTypeScalarSize(entry.type);
				const deUint8*		compPtr		= (const deUint8*)basePtr + entry.offset;

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

				for (int rowNdx = 0; rowNdx < rowCount; rowNdx++)
				{
					const float		compVal	= (scalarType == glu::TYPE_FLOAT) ? *((const float*)compPtr)
											: (scalarType == glu::TYPE_DOUBLE) ? (float)*((const double*)compPtr)
											: 0.0f;

					src << de::floatToString(compVal, 1);

					if (rowNdx < rowCount-1)
						src << ", ";
				}

				src << ");\n";
			}
			else
			{
				generateValueSrc(src, entry, basePtr, 0);
				src << "[" << colNdx << "];\n";
			}
		}
	}
	else		// generateTestSrcMatrixPerElement
	{
		const glu::DataType	scalarType	= glu::getDataTypeScalarType(entry.type);

		for (int colNdx = 0; colNdx < columnCount; colNdx++)
		{
			for (int rowNdx = 0; rowNdx < rowCount; rowNdx++)
			{
				src << "\t" << srcName << "[" << colNdx << "][" << rowNdx << "] = ";
				if (glu::isDataTypeMatrix(entry.type))
				{
					const deUint8*	elemPtr		= (const deUint8*)basePtr + entry.offset;
					const size_t	compSize	= getDataTypeByteSize(scalarType);
					const deUint8*	compPtr		= elemPtr + (colNdx * entry.matrixStride + rowNdx * compSize);
					const float		compVal		= (scalarType == glu::TYPE_FLOAT) ? *((const float*)compPtr)
												: (scalarType == glu::TYPE_DOUBLE) ? (float)*((const double*)compPtr)
												: 0.0f;

					src << de::floatToString(compVal, 1) << ";\n";
				}
				else
				{
					generateValueSrc(src, entry, basePtr, 0);
					src << "[" << colNdx << "][" << rowNdx << "];\n";
				}
			}
		}
	}
}

void generateTestSrcMatrixPerVec (std::ostringstream&			src,
								  glu::DataType					elementType,
								  const std::string&			srcName,
								  const void*					basePtr,
								  const InterfaceLayoutEntry&	entry)
{
	switch (elementType)
	{
		case glu::TYPE_FLOAT_MAT2:		writeMatrixTypeSrc(2, 2, "vec2", src, srcName, basePtr, entry, true);	break;
		case glu::TYPE_FLOAT_MAT2X3:	writeMatrixTypeSrc(2, 3, "vec3", src, srcName, basePtr, entry, true);	break;
		case glu::TYPE_FLOAT_MAT2X4:	writeMatrixTypeSrc(2, 4, "vec4", src, srcName, basePtr, entry, true);	break;
		case glu::TYPE_FLOAT_MAT3X4:	writeMatrixTypeSrc(3, 4, "vec4", src, srcName, basePtr, entry, true);	break;
		case glu::TYPE_FLOAT_MAT4:		writeMatrixTypeSrc(4, 4, "vec4", src, srcName, basePtr, entry, true);	break;
		case glu::TYPE_FLOAT_MAT4X2:	writeMatrixTypeSrc(4, 2, "vec2", src, srcName, basePtr, entry, true);	break;
		case glu::TYPE_FLOAT_MAT4X3:	writeMatrixTypeSrc(4, 3, "vec3", src, srcName, basePtr, entry, true);	break;
		default:						DE_ASSERT(false && "Invalid type");										break;
	}
}

void generateTestSrcMatrixPerElement (std::ostringstream&			src,
									  glu::DataType					elementType,
									  const std::string&			srcName,
									  const void*					basePtr,
									  const InterfaceLayoutEntry&	entry)
{
	std::string type = "float";
	switch (elementType)
	{
		case glu::TYPE_FLOAT_MAT2:		writeMatrixTypeSrc(2, 2, type, src, srcName, basePtr, entry, false);	break;
		case glu::TYPE_FLOAT_MAT2X3:	writeMatrixTypeSrc(2, 3, type, src, srcName, basePtr, entry, false);	break;
		case glu::TYPE_FLOAT_MAT2X4:	writeMatrixTypeSrc(2, 4, type, src, srcName, basePtr, entry, false);	break;
		case glu::TYPE_FLOAT_MAT3X4:	writeMatrixTypeSrc(3, 4, type, src, srcName, basePtr, entry, false);	break;
		case glu::TYPE_FLOAT_MAT4:		writeMatrixTypeSrc(4, 4, type, src, srcName, basePtr, entry, false);	break;
		case glu::TYPE_FLOAT_MAT4X2:	writeMatrixTypeSrc(4, 2, type, src, srcName, basePtr, entry, false);	break;
		case glu::TYPE_FLOAT_MAT4X3:	writeMatrixTypeSrc(4, 3, type, src, srcName, basePtr, entry, false);	break;
		default:						DE_ASSERT(false && "Invalid type");										break;
	}
}

void generateSingleAssignment (std::ostringstream&			src,
							   glu::DataType				elementType,
							   const std::string&			srcName,
							   const void*					basePtr,
							   const InterfaceLayoutEntry&	entry,
							   MatrixLoadFlags				matrixLoadFlag)
{
	if (matrixLoadFlag == LOAD_FULL_MATRIX)
	{
		src << "\t" << srcName << " = ";
		generateValueSrc(src, entry, basePtr, 0);
		src << ";\n";
	}
	else
	{
		if (glu::isDataTypeMatrix(elementType))
		{
			generateTestSrcMatrixPerVec		(src, elementType, srcName, basePtr, entry);
			generateTestSrcMatrixPerElement	(src, elementType, srcName, basePtr, entry);
		}
	}
}

void generateAssignment (std::ostringstream&	src,
						 const InterfaceLayout&	layout,
						 const VarType&			type,
						 const std::string&		srcName,
						 const std::string&		apiName,
						 int					blockNdx,
						 const void*			basePtr,
						 MatrixLoadFlags		matrixLoadFlag)
{
	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();
		std::string					fullApiName			= std::string(apiName) + (isArray ? "[0]" : ""); // Arrays are always postfixed with [0]
		int							interfaceLayoutNdx	= layout.getInterfaceLayoutIndex(blockNdx, fullApiName);
		const InterfaceLayoutEntry&	entry				= layout.interfaces[interfaceLayoutNdx];

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

		for (int elementNdx = 0; elementNdx < type.getArraySize(); elementNdx++)
		{
			const std::string op				= std::string("[") + de::toString(elementNdx) + "]";
			const std::string elementSrcName	= std::string(srcName) + op;
			const std::string elementApiName	= std::string(apiName) + op;

			generateAssignment(src, layout, elementType, elementSrcName, elementApiName, blockNdx, basePtr, LOAD_FULL_MATRIX);
		}
	}
	else
	{
		DE_ASSERT(type.isStructType());

		for (StructType::ConstIterator memberIter = type.getStruct().begin(); memberIter != type.getStruct().end(); memberIter++)
		{
			const StructMember&	member			= *memberIter;
			const std::string	op				= std::string(".") + member.getName();
			const std::string	memberSrcName	= std::string(srcName) + op;
			const std::string	memberApiName	= std::string(apiName) + op;

			if (0 == (member.getFlags() & (FIELD_UNASSIGNED | FIELD_MISSING)))
				generateAssignment(src, layout, memberIter->getType(), memberSrcName, memberApiName, blockNdx, basePtr, LOAD_FULL_MATRIX);
		}
	}
}

void generateAssignment (std::ostringstream&			src,
						 const InterfaceLayout&			layout,
						 const ShaderInterface&			shaderInterface,
						 const std::map<int, void*>&	blockPointers,
						 MatrixLoadFlags				matrixLoadFlag)
{
	for (int blockNdx = 0; blockNdx < shaderInterface.getNumInterfaceBlocks(); blockNdx++)
	{
		const InterfaceBlock& block = shaderInterface.getInterfaceBlock(blockNdx);

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

		DE_ASSERT(!isArray || hasInstanceName);

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

			for (InterfaceBlock::ConstIterator interfaceMemberIter = block.begin(); interfaceMemberIter != block.end(); interfaceMemberIter++)
			{
				const InterfaceBlockMember& interfaceMember = *interfaceMemberIter;

				if ((interfaceMember.getFlags() & (FIELD_MISSING | FIELD_UNASSIGNED)) == 0)
				{
					std::string srcName = srcPrefix + interfaceMember.getName();
					std::string apiName = apiPrefix + interfaceMember.getName();

					generateAssignment(src, layout, interfaceMember.getType(), srcName, apiName, blockNdx, basePtr, matrixLoadFlag);
				}
			}
		}
	}
}

std::string generatePassthroughShader ()
{
	std::ostringstream	src;

	src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n";

	src << "\n"
		   "void main (void)\n"
		   "{\n"
		   "}\n";

	return src.str();
}

std::string generateTestShader (const ShaderInterface& shaderInterface, const InterfaceLayout& layout, const std::map<int, void*>& blockPointers, MatrixLoadFlags matrixLoadFlag, TestStageFlags testStageFlags, bool shuffleUniformMembers)
{
	std::ostringstream				src;
	std::vector<const StructType*>	namedStructs;

	src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n\n";

	if (testStageFlags == TEST_STAGE_GEOMETRY)
	{
		src << "layout(points) in;\n"
			<< "layout(points, max_vertices = 1) out;\n\n";
	}

	shaderInterface.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 < shaderInterface.getNumInterfaceBlocks(); blockNdx++)
	{
		const InterfaceBlock& block = shaderInterface.getInterfaceBlock(blockNdx);

		generateDeclaration(src, blockNdx, block, layout, shuffleUniformMembers);
	}

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

	generateAssignment(src, layout, shaderInterface, blockPointers, matrixLoadFlag);

	if (testStageFlags == TEST_STAGE_GEOMETRY)
	{
		src << "\n"
			<< "\tEmitVertex();\n"
			<< "\tEndPrimitive();\n";
	}

	src << "}\n";

	return src.str();
}

VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize			bufferSize,
										 const VkBufferUsageFlags	usage)
{
	const VkBufferCreateInfo bufferCreateInfo =
	{
		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	//  VkStructureType		sType;
		DE_NULL,								//  const void*			pNext;
		(VkBufferCreateFlags)0,					//  VkBufferCreateFlags	flags;
		bufferSize,								//  VkDeviceSize		size;
		usage,									//  VkBufferUsageFlags	usage;
		VK_SHARING_MODE_EXCLUSIVE,				//  VkSharingMode		sharingMode;
		0u,										//  deUint32			queueFamilyIndexCount;
		DE_NULL,								//  const deUint32*		pQueueFamilyIndices;
	};

	return bufferCreateInfo;
}

Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
									   const VkDevice				device,
									   const VkPipelineLayout		pipelineLayout,
									   const VkRenderPass			renderPass,
									   const VkShaderModule			vertexModule,
									   const VkShaderModule			geometryModule,
									   const VkExtent2D				renderSize)
{
	const std::vector<VkViewport>				viewports						(1, makeViewport(renderSize));
	const std::vector<VkRect2D>					scissors						(1, makeRect2D(renderSize));
	const VkPipelineVertexInputStateCreateInfo	vertexInputStateCreateInfo	=
	{
		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType								sType
		DE_NULL,													// const void*									pNext
		(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags		flags
		0u,															// deUint32										vertexBindingDescriptionCount
		DE_NULL,													// const VkVertexInputBindingDescription*		pVertexBindingDescriptions
		0u,															// deUint32										vertexAttributeDescriptionCount
		DE_NULL,													// const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions
	};

	return makeGraphicsPipeline(vk,									// const DeviceInterface&						vk
								device,								// const VkDevice								device
								pipelineLayout,						// const VkPipelineLayout						pipelineLayout
								vertexModule,						// const VkShaderModule							vertexShaderModule
								DE_NULL,							// const VkShaderModule							tessellationControlModule
								DE_NULL,							// const VkShaderModule							tessellationEvalModule
								geometryModule,						// const VkShaderModule							geometryShaderModule
								DE_NULL,							// const VkShaderModule							m_maxGeometryBlocksShaderModule
								renderPass,							// const VkRenderPass							renderPass
								viewports,							// const std::vector<VkViewport>&				viewports
								scissors,							// const std::vector<VkRect2D>&					scissors
								VK_PRIMITIVE_TOPOLOGY_POINT_LIST,	// const VkPrimitiveTopology					topology
								0u,									// const deUint32								subpass
								0u,									// const deUint32								patchControlPoints
								&vertexInputStateCreateInfo);		// const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
}

// InterfaceBlockCaseInstance

class InterfaceBlockCaseInstance : public vkt::TestInstance
{
public:
									InterfaceBlockCaseInstance	(Context&							context,
																 const InterfaceLayout&				layout,
																 const std::map<int, void*>&		blockPointers,
																 const std::vector<deUint8>&		data,
																 const std::vector<VkDeviceSize>&	tfBufBindingOffsets,
																 const std::vector<VkDeviceSize>&	tfBufBindingSizes,
																 const deUint32						locationsRequired,
																 const TestStageFlags				testStageFlags);

	virtual							~InterfaceBlockCaseInstance	(void);
	virtual tcu::TestStatus			iterate						(void);

private:
	Move<VkShaderModule>			getGeometryShaderModule		(const DeviceInterface&	vk,
																 const VkDevice			device);

	bool							usesFloat64					(void);
	std::string						validateValue				(const InterfaceLayoutEntry& entry, const void* basePtr0, const void* basePtr, const void* receivedBasePtr);
	std::string						validateValues				(const void* recievedDataPtr);

	typedef de::SharedPtr<vk::Unique<vk::VkBuffer> >	VkBufferSp;
	typedef de::SharedPtr<vk::Allocation>				AllocationSp;

	const InterfaceLayout&			m_layout;
	const std::vector<deUint8>&		m_data;
	const DeviceSizeVector&			m_tfBufBindingOffsets;
	const DeviceSizeVector&			m_tfBufBindingSizes;
	const std::map<int, void*>&		m_blockPointers;
	const deUint32					m_locationsRequired;
	const TestStageFlags			m_testStageFlags;
	const VkExtent2D				m_imageExtent2D;
};

InterfaceBlockCaseInstance::InterfaceBlockCaseInstance (Context&							ctx,
														const InterfaceLayout&				layout,
														const std::map<int, void*>&			blockPointers,
														const std::vector<deUint8>&			data,
														const std::vector<VkDeviceSize>&	tfBufBindingOffsets,
														const std::vector<VkDeviceSize>&	tfBufBindingSizes,
														const deUint32						locationsRequired,
														const TestStageFlags				testStageFlags)
	: vkt::TestInstance		(ctx)
	, m_layout				(layout)
	, m_data				(data)
	, m_tfBufBindingOffsets	(tfBufBindingOffsets)
	, m_tfBufBindingSizes	(tfBufBindingSizes)
	, m_blockPointers		(blockPointers)
	, m_locationsRequired	(locationsRequired)
	, m_testStageFlags		(testStageFlags)
	, m_imageExtent2D		(makeExtent2D(256u, 256u))
{
	const deUint32											componentsPerLocation		= 4u;
	const deUint32											componentsRequired			= m_locationsRequired * componentsPerLocation;
	const InstanceInterface&								vki							= m_context.getInstanceInterface();
	const VkPhysicalDevice									physDevice					= m_context.getPhysicalDevice();
	const VkPhysicalDeviceTransformFeedbackFeaturesEXT&		transformFeedbackFeatures	= m_context.getTransformFeedbackFeatures();
	const VkPhysicalDeviceLimits							limits						= getPhysicalDeviceProperties(vki, physDevice).limits;
	VkPhysicalDeviceTransformFeedbackPropertiesEXT			transformFeedbackProperties;
	VkPhysicalDeviceProperties2								deviceProperties2;

	if (transformFeedbackFeatures.transformFeedback == DE_FALSE)
		TCU_THROW(NotSupportedError, "transformFeedback feature is not supported");

	deMemset(&deviceProperties2, 0, sizeof(deviceProperties2));
	deMemset(&transformFeedbackProperties, 0x00, sizeof(transformFeedbackProperties));

	deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
	deviceProperties2.pNext = &transformFeedbackProperties;

	transformFeedbackProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT;
	transformFeedbackProperties.pNext = DE_NULL;

	vki.getPhysicalDeviceProperties2(physDevice, &deviceProperties2);

	if (transformFeedbackProperties.maxTransformFeedbackBuffers < tfBufBindingSizes.size())
		TCU_THROW(NotSupportedError, "maxTransformFeedbackBuffers=" + de::toString(transformFeedbackProperties.maxTransformFeedbackBuffers) + " is less than required (" + de::toString(tfBufBindingSizes.size()) + ")");

	if (transformFeedbackProperties.maxTransformFeedbackBufferDataSize < m_data.size())
		TCU_THROW(NotSupportedError, "maxTransformFeedbackBufferDataSize=" + de::toString(transformFeedbackProperties.maxTransformFeedbackBufferDataSize) + " is less than required (" + de::toString(m_data.size()) + ")");

	if (m_testStageFlags == TEST_STAGE_VERTEX)
	{
		if (limits.maxVertexOutputComponents < componentsRequired)
			TCU_THROW(NotSupportedError, "maxVertexOutputComponents=" + de::toString(limits.maxVertexOutputComponents) + " is less than required (" + de::toString(componentsRequired) + ")");
	}

	if (m_testStageFlags == TEST_STAGE_GEOMETRY)
	{
		if (limits.maxGeometryOutputComponents < componentsRequired)
			TCU_THROW(NotSupportedError, "maxGeometryOutputComponents=" + de::toString(limits.maxGeometryOutputComponents) + " is less than required (" + de::toString(componentsRequired) + ")");
	}

	if (usesFloat64())
		m_context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_FLOAT64);
}

InterfaceBlockCaseInstance::~InterfaceBlockCaseInstance (void)
{
}

bool InterfaceBlockCaseInstance::usesFloat64 (void)
{
	for (size_t layoutNdx = 0; layoutNdx< m_layout.interfaces.size(); ++layoutNdx)
		if (isDataTypeDoubleType(m_layout.interfaces[layoutNdx].type))
			return true;

	return false;
}

Move<VkShaderModule> InterfaceBlockCaseInstance::getGeometryShaderModule (const DeviceInterface&	vk,
																		  const VkDevice			device)
{
	if (m_testStageFlags == TEST_STAGE_GEOMETRY)
		return createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);

	return Move<VkShaderModule>();
}

tcu::TestStatus InterfaceBlockCaseInstance::iterate (void)
{
	const DeviceInterface&			vk					= m_context.getDeviceInterface();
	const VkDevice					device				= m_context.getDevice();
	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
	const VkQueue					queue				= m_context.getUniversalQueue();
	Allocator&						allocator			= m_context.getDefaultAllocator();

	const Move<VkShaderModule>		vertModule			(createShaderModule		(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
	const Move<VkShaderModule>		geomModule			(getGeometryShaderModule(vk, device));
	const Move<VkRenderPass>		renderPass			(makeRenderPass			(vk, device, VK_FORMAT_UNDEFINED));
	const Move<VkFramebuffer>		framebuffer			(makeFramebuffer		(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
	const Move<VkPipelineLayout>	pipelineLayout		(makePipelineLayout		(vk, device));
	const Move<VkPipeline>			pipeline			(makeGraphicsPipeline	(vk, device, *pipelineLayout, *renderPass, *vertModule, *geomModule, m_imageExtent2D));
	const Move<VkCommandPool>		cmdPool				(createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
	const Move<VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer	(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));

	const VkBufferCreateInfo		tfBufCreateInfo		= makeBufferCreateInfo(m_data.size(), VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
	const Move<VkBuffer>			tfBuf				= createBuffer(vk, device, &tfBufCreateInfo);
	const de::MovePtr<Allocation>	tfBufAllocation		= allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
	const deUint32					tfBufBindingCount	= static_cast<deUint32>(m_tfBufBindingOffsets.size());
	const std::vector<VkBuffer>		tfBufBindings		(tfBufBindingCount, *tfBuf);

	DE_ASSERT(tfBufBindings.size() == tfBufBindingCount);

	VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));

	deMemset(tfBufAllocation->getHostPtr(), 0, m_data.size());
	flushMappedMemoryRange(vk, device, tfBufAllocation->getMemory(), tfBufAllocation->getOffset(), VK_WHOLE_SIZE);

	beginCommandBuffer(vk, *cmdBuffer);
	{
		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
		{
			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);

			vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, tfBufBindingCount, &tfBufBindings[0], &m_tfBufBindingOffsets[0], &m_tfBufBindingSizes[0]);

			vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
			{
				vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
			}
			vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
		}
		endRenderPass(vk, *cmdBuffer);
	}
	endCommandBuffer(vk, *cmdBuffer);
	submitCommandsAndWait(vk, device, queue, *cmdBuffer);

	invalidateMappedMemoryRange(vk, device, tfBufAllocation->getMemory(), tfBufAllocation->getOffset(), VK_WHOLE_SIZE);

	std::string result = validateValues(tfBufAllocation->getHostPtr());

	if (!result.empty())
		return tcu::TestStatus::fail(result);

	return tcu::TestStatus::pass("Pass");
}

std::string InterfaceBlockCaseInstance::validateValue (const InterfaceLayoutEntry& entry, const void* basePtr0, const void* basePtr, const void* receivedBasePtr)
{
	const glu::DataType	scalarType	= glu::getDataTypeScalarType(entry.type);
	const int			scalarSize	= glu::getDataTypeScalarSize(entry.type);
	const bool			isMatrix	= glu::isDataTypeMatrix(entry.type);
	const int			numVecs		= isMatrix ? glu::getDataTypeMatrixNumColumns(entry.type) : 1;
	const int			vecSize		= scalarSize / numVecs;
	const bool			isArray		= entry.arraySize > 1;
	const size_t		compSize	= getDataTypeByteSize(scalarType);
	std::string			result;

	DE_ASSERT(scalarSize%numVecs == 0);

	for (int elemNdx = 0; elemNdx < entry.arraySize; 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++)
			{
				const deUint8*	compPtr		= vecPtr + compSize*compNdx;
				const size_t	offset		= compPtr - (deUint8*)basePtr0;
				const deUint8*	receivedPtr	= (deUint8*)receivedBasePtr + offset;

				switch (scalarType)
				{
					case glu::TYPE_DOUBLE:
					{
						const double expected	= *((double*)compPtr);
						const double received	= *((double*)receivedPtr);

						if (deAbs(received - expected) > 0.05)
							result = "Mismatch at offset " + de::toString(offset) + " expected " + de::toString(expected) + " received " + de::toString(received);

						break;
					}
					case glu::TYPE_FLOAT:
					{
						const float expected	= *((float*)compPtr);
						const float received	= *((float*)receivedPtr);

						if (deAbs(received - expected) > 0.05)
							result = "Mismatch at offset " + de::toString(offset) + " expected " + de::toString(expected) + " received " + de::toString(received);

						break;
					}
					case glu::TYPE_INT:
					{
						const deInt32 expected	= *((deInt32*)compPtr);
						const deInt32 received	= *((deInt32*)receivedPtr);

						if (received != expected)
							result = "Mismatch at offset " + de::toString(offset) + " expected " + de::toString(expected) + " received " + de::toString(received);

						break;
					}
					case glu::TYPE_UINT:
					{
						const deUint32 expected	= *((deUint32*)compPtr);
						const deUint32 received	= *((deUint32*)receivedPtr);

						if (received != expected)
							result = "Mismatch at offset " + de::toString(offset) + " expected " + de::toString(expected) + " received " + de::toString(received);

						break;
					}
					default:
						DE_ASSERT(false);
				}

				if (!result.empty())
				{
					result += " (elemNdx=" + de::toString(elemNdx) + " vecNdx=" + de::toString(vecNdx) + " compNdx=" + de::toString(compNdx) + ")";

					return result;
				}
			}
		}
	}

	return result;
}

std::string InterfaceBlockCaseInstance::validateValues (const void* recievedDataPtr)
{
	const int	numBlocks	= (int)m_layout.blocks.size();

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

		for (int entryNdx = 0; entryNdx < numEntries; entryNdx++)
		{
			const InterfaceLayoutEntry&	entry	= m_layout.interfaces[m_layout.blocks[blockNdx].activeInterfaceIndices[entryNdx]];
			const std::string			result	= entry.validate ? validateValue(entry, &m_data[0], basePtr, recievedDataPtr) : "";

			if (!result.empty())
			{
				tcu::TestLog&			log		= m_context.getTestContext().getLog();
				std::vector<deUint8>	mask	= createMask(m_layout, m_blockPointers, &m_data[0], m_data.size());
				std::ostringstream		str;

				str << "Error at entry '" << entry.name << "' block '" << m_layout.blocks[blockNdx].name << "'" << std::endl;
				str << result << std::endl;

				str << m_layout;

				str << "Xfb buffer offsets: " << m_tfBufBindingOffsets << std::endl;
				str << "Xfb buffer sizes: " << m_tfBufBindingSizes << std::endl << std::endl;

				dumpBytes(str, "Expected:", &m_data[0], m_data.size(), &mask[0]);
				dumpBytes(str, "Retrieved:", recievedDataPtr, m_data.size(), &mask[0]);

				dumpBytes(str, "Expected (unfiltered):", &m_data[0], m_data.size());
				dumpBytes(str, "Retrieved (unfiltered):", recievedDataPtr, m_data.size());

				log << tcu::TestLog::Message << str.str() << tcu::TestLog::EndMessage;

				return result;
			}
		}
	}

	return std::string();
}

} // anonymous (utilities)

// InterfaceBlockCase.

InterfaceBlockCase::InterfaceBlockCase (tcu::TestContext&	testCtx,
										const std::string&	name,
										const std::string&	description,
										MatrixLoadFlags		matrixLoadFlag,
										TestStageFlags		testStageFlags,
										bool				shuffleInterfaceMembers)
	: TestCase					(testCtx, name, description)
	, m_matrixLoadFlag			(matrixLoadFlag)
	, m_testStageFlags			(testStageFlags)
	, m_shuffleInterfaceMembers	(shuffleInterfaceMembers)
	, m_locationsRequired		(0)
{
}

InterfaceBlockCase::~InterfaceBlockCase (void)
{
}

void InterfaceBlockCase::initPrograms (vk::SourceCollections& programCollection) const
{
	DE_ASSERT(!m_vertShaderSource.empty());

	programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);

	if (!m_geomShaderSource.empty())
		programCollection.glslSources.add("geom") << glu::GeometrySource(m_geomShaderSource);
}

TestInstance* InterfaceBlockCase::createInstance (Context& context) const
{
	return new InterfaceBlockCaseInstance(context, m_interfaceLayout, m_blockPointers, m_data, m_tfBufBindingOffsets, m_tfBufBindingSizes, m_locationsRequired, m_testStageFlags);
}

void InterfaceBlockCase::delayedInit (void)
{
	BufferGeneralMapping	xfbBufferSize;
	std::string				notSupportedComment;

	// Compute reference layout.
	computeXfbLayout(m_interfaceLayout, m_interface, xfbBufferSize, m_locationsRequired);

	// Assign storage for reference values.
	// m_data contains all xfb buffers starting with all interfaces of first xfb_buffer, then all interfaces of next xfb_buffer
	{
		BufferGeneralMapping	xfbBufferOffsets;
		int						totalSize			= 0;
		int						maxXfb				= 0;

		for (BufferGeneralMapping::const_iterator xfbBuffersIter = xfbBufferSize.begin(); xfbBuffersIter != xfbBufferSize.end(); xfbBuffersIter++)
		{
			xfbBufferOffsets[xfbBuffersIter->first] = totalSize;
			totalSize += xfbBuffersIter->second;
			maxXfb = std::max(maxXfb, xfbBuffersIter->first);
		}
		m_data.resize(totalSize);

		DE_ASSERT(de::inBounds(maxXfb, 0, 256)); // Not correlated with spec: just make sure vectors won't be huge

		m_tfBufBindingSizes.resize(maxXfb + 1);
		for (BufferGeneralMapping::const_iterator xfbBuffersIter = xfbBufferSize.begin(); xfbBuffersIter != xfbBufferSize.end(); xfbBuffersIter++)
			m_tfBufBindingSizes[xfbBuffersIter->first] = xfbBuffersIter->second;

		m_tfBufBindingOffsets.resize(maxXfb + 1);
		for (BufferGeneralMapping::const_iterator xfbBuffersIter = xfbBufferOffsets.begin(); xfbBuffersIter != xfbBufferOffsets.end(); xfbBuffersIter++)
			m_tfBufBindingOffsets[xfbBuffersIter->first] = xfbBuffersIter->second;

		// Pointers for each block.
		for (int blockNdx = 0; blockNdx < (int)m_interfaceLayout.blocks.size(); blockNdx++)
		{
			const int dataXfbBufferStartOffset	= xfbBufferOffsets[m_interfaceLayout.blocks[blockNdx].xfbBuffer];
			const int offset					= dataXfbBufferStartOffset + m_interfaceLayout.blocks[blockNdx].xfbOffset;

			m_blockPointers[blockNdx] = &m_data[0] + offset;
		}
	}

	// Generate values.
	generateValues(m_interfaceLayout, m_blockPointers, 1 /* seed */);

	// Overlap validation
	{
		std::vector<deUint8>	mask	= createMask(m_interfaceLayout, m_blockPointers, &m_data[0], m_data.size());

		for (size_t maskNdx = 0; maskNdx < mask.size(); ++maskNdx)
			DE_ASSERT(mask[maskNdx] <= 1);
	}

	if (m_testStageFlags == TEST_STAGE_VERTEX)
	{
		m_vertShaderSource = generateTestShader(m_interface, m_interfaceLayout, m_blockPointers, m_matrixLoadFlag, m_testStageFlags, m_shuffleInterfaceMembers);
		m_geomShaderSource = "";
	}
	else if (m_testStageFlags == TEST_STAGE_GEOMETRY)
	{
		m_vertShaderSource = generatePassthroughShader();
		m_geomShaderSource = generateTestShader(m_interface, m_interfaceLayout, m_blockPointers, m_matrixLoadFlag, m_testStageFlags, m_shuffleInterfaceMembers);
	}
	else
	{
		DE_ASSERT(false && "Unknown test stage specified");
	}
}

} // TransformFeedback
} // vkt
