/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 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 Program interface utilities
 *//*--------------------------------------------------------------------*/

#include "es31fProgramInterfaceDefinitionUtil.hpp"
#include "es31fProgramInterfaceDefinition.hpp"
#include "gluVarType.hpp"
#include "gluVarTypeUtil.hpp"
#include "gluShaderUtil.hpp"
#include "deString.h"
#include "deStringUtil.hpp"
#include "glwEnums.hpp"

#include <set>
#include <map>
#include <sstream>
#include <vector>
#include <algorithm>

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace ProgramInterfaceDefinition
{

VariableSearchFilter::VariableSearchFilter (void)
	: m_shaderTypeBits	(0xFFFFFFFFul)
	, m_storageBits		(0xFFFFFFFFul)
{
}

VariableSearchFilter VariableSearchFilter::createShaderTypeFilter (glu::ShaderType type)
{
	DE_ASSERT(type < glu::SHADERTYPE_LAST);

	VariableSearchFilter filter;
	filter.m_shaderTypeBits = (1u << type);
	return filter;
}

VariableSearchFilter VariableSearchFilter::createStorageFilter (glu::Storage storage)
{
	DE_ASSERT(storage < glu::STORAGE_LAST);

	VariableSearchFilter filter;
	filter.m_storageBits = (1u << storage);
	return filter;
}

VariableSearchFilter VariableSearchFilter::createShaderTypeStorageFilter (glu::ShaderType type, glu::Storage storage)
{
	return logicalAnd(createShaderTypeFilter(type), createStorageFilter(storage));
}

VariableSearchFilter VariableSearchFilter::logicalOr (const VariableSearchFilter& a, const VariableSearchFilter& b)
{
	VariableSearchFilter filter;
	filter.m_shaderTypeBits	= a.m_shaderTypeBits | b.m_shaderTypeBits;
	filter.m_storageBits	= a.m_storageBits | b.m_storageBits;
	return filter;
}

VariableSearchFilter VariableSearchFilter::logicalAnd (const VariableSearchFilter& a, const VariableSearchFilter& b)
{
	VariableSearchFilter filter;
	filter.m_shaderTypeBits	= a.m_shaderTypeBits & b.m_shaderTypeBits;
	filter.m_storageBits	= a.m_storageBits & b.m_storageBits;
	return filter;
}

bool VariableSearchFilter::matchesFilter (const ProgramInterfaceDefinition::Shader* shader) const
{
	DE_ASSERT(shader->getType() < glu::SHADERTYPE_LAST);
	return (m_shaderTypeBits & (1u << shader->getType())) != 0;
}

bool VariableSearchFilter::matchesFilter (const glu::VariableDeclaration& variable) const
{
	DE_ASSERT(variable.storage < glu::STORAGE_LAST);
	return (m_storageBits & (1u << variable.storage)) != 0;
}

bool VariableSearchFilter::matchesFilter (const glu::InterfaceBlock& block) const
{
	DE_ASSERT(block.storage < glu::STORAGE_LAST);
	return (m_storageBits & (1u << block.storage)) != 0;
}

} // ProgramInterfaceDefinition

static bool incrementMultiDimensionIndex (std::vector<int>& index, const std::vector<int>& dimensions)
{
	int incrementDimensionNdx = (int)(index.size() - 1);

	while (incrementDimensionNdx >= 0)
	{
		if (++index[incrementDimensionNdx] == dimensions[incrementDimensionNdx])
			index[incrementDimensionNdx--] = 0;
		else
			break;
	}

	return (incrementDimensionNdx != -1);
}

bool programContainsIOBlocks (const ProgramInterfaceDefinition::Program* program)
{
	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
	{
		if (shaderContainsIOBlocks(program->getShaders()[shaderNdx]))
			return true;
	}

	return false;
}

bool shaderContainsIOBlocks (const ProgramInterfaceDefinition::Shader* shader)
{
	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
	{
		const glu::Storage storage = shader->getDefaultBlock().interfaceBlocks[ndx].storage;
		if (storage == glu::STORAGE_IN			||
			storage == glu::STORAGE_OUT			||
			storage == glu::STORAGE_PATCH_IN	||
			storage == glu::STORAGE_PATCH_OUT)
		{
			return true;
		}
	}
	return false;
}

glu::ShaderType getProgramTransformFeedbackStage (const ProgramInterfaceDefinition::Program* program)
{
	if (program->hasStage(glu::SHADERTYPE_GEOMETRY))
		return glu::SHADERTYPE_GEOMETRY;

	if (program->hasStage(glu::SHADERTYPE_TESSELLATION_EVALUATION))
		return glu::SHADERTYPE_TESSELLATION_EVALUATION;

	if (program->hasStage(glu::SHADERTYPE_VERTEX))
		return glu::SHADERTYPE_VERTEX;

	DE_ASSERT(false);
	return glu::SHADERTYPE_LAST;
}

void generateVariableTypeResourceNames (std::vector<std::string>& resources, const std::string& name, const glu::VarType& type, deUint32 resourceNameGenerationFlags)
{
	DE_ASSERT((resourceNameGenerationFlags & (~RESOURCE_NAME_GENERATION_FLAG_MASK)) == 0);

	// remove top-level flag from children
	const deUint32 childFlags = resourceNameGenerationFlags & ~((deUint32)RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE);

	if (type.isBasicType())
		resources.push_back(name);
	else if (type.isStructType())
	{
		const glu::StructType* structType = type.getStructPtr();
		for (int ndx = 0; ndx < structType->getNumMembers(); ++ndx)
			generateVariableTypeResourceNames(resources, name + "." + structType->getMember(ndx).getName(), structType->getMember(ndx).getType(), childFlags);
	}
	else if (type.isArrayType())
	{
		// Bottom-level arrays of basic types of a transform feedback variable will produce only the first
		// element but without the trailing "[0]"
		if (type.getElementType().isBasicType() &&
			(resourceNameGenerationFlags & RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE) != 0)
		{
			resources.push_back(name);
		}
		// Bottom-level arrays of basic types and SSBO top-level arrays of any type procude only first element
		else if (type.getElementType().isBasicType() ||
				 (resourceNameGenerationFlags & RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE) != 0)
		{
			generateVariableTypeResourceNames(resources, name + "[0]", type.getElementType(), childFlags);
		}
		// Other arrays of aggregate types are expanded
		else
		{
			for (int ndx = 0; ndx < type.getArraySize(); ++ndx)
				generateVariableTypeResourceNames(resources, name + "[" + de::toString(ndx) + "]", type.getElementType(), childFlags);
		}
	}
	else
		DE_ASSERT(false);
}

// Program source generation

namespace
{

using ProgramInterfaceDefinition::VariablePathComponent;
using ProgramInterfaceDefinition::VariableSearchFilter;

static std::string getShaderExtensionDeclarations (const ProgramInterfaceDefinition::Shader* shader)
{
	if (shader->getVersion() > glu::GLSL_VERSION_440)
		return "";

	std::vector<std::string>	extensions;
	std::ostringstream			buf;

	if (shader->getType() == glu::SHADERTYPE_GEOMETRY)
	{
		extensions.push_back("GL_EXT_geometry_shader");
	}
	else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_CONTROL ||
			 shader->getType() == glu::SHADERTYPE_TESSELLATION_EVALUATION)
	{
		extensions.push_back("GL_EXT_tessellation_shader");
	}

	if (shaderContainsIOBlocks(shader))
		extensions.push_back("GL_EXT_shader_io_blocks");

	for (int ndx = 0; ndx < (int)extensions.size(); ++ndx)
		buf << "#extension " << extensions[ndx] << " : require\n";
	return buf.str();
}

static std::string getShaderTypeDeclarations (const ProgramInterfaceDefinition::Program* program, const ProgramInterfaceDefinition::Shader* shader)
{
	glu::ShaderType type = shader->getType();
	auto isCoreGL = (shader->getVersion() > glu::GLSL_VERSION_440);

	switch (type)
	{
		case glu::SHADERTYPE_VERTEX:
			if (isCoreGL)
				return "out gl_PerVertex { vec4 gl_Position; };\n";
			return "";

		case glu::SHADERTYPE_FRAGMENT:
			return "";

		case glu::SHADERTYPE_GEOMETRY:
		{
			std::ostringstream buf;
			buf <<	"layout(points) in;\n"
					"layout(points, max_vertices=" << program->getGeometryNumOutputVertices() << ") out;\n";
			if (isCoreGL)
			{
				buf << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
					   "out gl_PerVertex { vec4 gl_Position; };\n";
			}
			return buf.str();
		}

		case glu::SHADERTYPE_TESSELLATION_CONTROL:
		{
			std::ostringstream buf;
			buf << "layout(vertices=" << program->getTessellationNumOutputPatchVertices() << ") out;\n";
			if (isCoreGL)
			{
				buf << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
					   "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n";
			}
			return buf.str();
		}

		case glu::SHADERTYPE_TESSELLATION_EVALUATION:
		{
			std::ostringstream buf;
			if (isCoreGL)
			{
				buf << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
					   "out gl_PerVertex { vec4 gl_Position; };\n";
			}
			buf << "layout(triangles, point_mode) in;\n";
			return buf.str();
		}

		case glu::SHADERTYPE_COMPUTE:
			return "layout(local_size_x=1) in;\n";

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

class StructNameEqualPredicate
{
public:
				StructNameEqualPredicate	(const char* name) : m_name(name) { }
	bool		operator()					(const glu::StructType* type) { return type->hasTypeName() && (deStringEqual(m_name, type->getTypeName()) == DE_TRUE); }
private:
	const char*	m_name;
};

static void collectNamedStructureDefinitions (std::vector<const glu::StructType*>& dst, const glu::VarType& type)
{
	if (type.isBasicType())
		return;
	else if (type.isArrayType())
		return collectNamedStructureDefinitions(dst, type.getElementType());
	else if (type.isStructType())
	{
		if (type.getStructPtr()->hasTypeName())
		{
			// must be unique (may share the the same struct)
			std::vector<const glu::StructType*>::iterator where = std::find_if(dst.begin(), dst.end(), StructNameEqualPredicate(type.getStructPtr()->getTypeName()));
			if (where != dst.end())
			{
				DE_ASSERT(**where == *type.getStructPtr());

				// identical type has been added already, types of members must be added too
				return;
			}
		}

		// Add types of members first
		for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
			collectNamedStructureDefinitions(dst, type.getStructPtr()->getMember(ndx).getType());

		dst.push_back(type.getStructPtr());
	}
	else
		DE_ASSERT(false);
}

static void writeStructureDefinitions (std::ostringstream& buf, const ProgramInterfaceDefinition::DefaultBlock& defaultBlock)
{
	std::vector<const glu::StructType*> namedStructs;

	// Collect all structs in post order

	for (int ndx = 0; ndx < (int)defaultBlock.variables.size(); ++ndx)
		collectNamedStructureDefinitions(namedStructs, defaultBlock.variables[ndx].varType);

	for (int blockNdx = 0; blockNdx < (int)defaultBlock.interfaceBlocks.size(); ++blockNdx)
		for (int ndx = 0; ndx < (int)defaultBlock.interfaceBlocks[blockNdx].variables.size(); ++ndx)
			collectNamedStructureDefinitions(namedStructs, defaultBlock.interfaceBlocks[blockNdx].variables[ndx].varType);

	// Write

	for (int structNdx = 0; structNdx < (int)namedStructs.size(); ++structNdx)
	{
		buf <<	"struct " << namedStructs[structNdx]->getTypeName() << "\n"
				"{\n";

		for (int memberNdx = 0; memberNdx < namedStructs[structNdx]->getNumMembers(); ++memberNdx)
			buf << glu::indent(1) << glu::declare(namedStructs[structNdx]->getMember(memberNdx).getType(), namedStructs[structNdx]->getMember(memberNdx).getName(), 1) << ";\n";

		buf <<	"};\n";
	}

	if (!namedStructs.empty())
		buf << "\n";
}

static void writeInterfaceBlock (std::ostringstream& buf, const glu::InterfaceBlock& interfaceBlock)
{
	buf << interfaceBlock.layout;

	if (interfaceBlock.layout != glu::Layout())
		buf << " ";

	buf	<< glu::getStorageName(interfaceBlock.storage) << " " << interfaceBlock.interfaceName << "\n"
		<< "{\n";

	for (int ndx = 0; ndx < (int)interfaceBlock.variables.size(); ++ndx)
		buf << glu::indent(1) << interfaceBlock.variables[ndx] << ";\n";

	buf << "}";

	if (!interfaceBlock.instanceName.empty())
		buf << " " << interfaceBlock.instanceName;

	for (int dimensionNdx = 0; dimensionNdx < (int)interfaceBlock.dimensions.size(); ++dimensionNdx)
		buf << "[" << interfaceBlock.dimensions[dimensionNdx] << "]";

	buf << ";\n\n";
}

static bool isReadableInterface (const glu::InterfaceBlock& interface)
{
	return	interface.storage == glu::STORAGE_UNIFORM	||
			interface.storage == glu::STORAGE_IN		||
			interface.storage == glu::STORAGE_PATCH_IN	||
			(interface.storage == glu::STORAGE_BUFFER && (interface.memoryAccessQualifierFlags & glu::MEMORYACCESSQUALIFIER_WRITEONLY_BIT) == 0);
}

static bool isWritableInterface (const glu::InterfaceBlock& interface)
{
	return	interface.storage == glu::STORAGE_OUT		||
			interface.storage == glu::STORAGE_PATCH_OUT	||
			(interface.storage == glu::STORAGE_BUFFER && (interface.memoryAccessQualifierFlags & glu::MEMORYACCESSQUALIFIER_READONLY_BIT) == 0);
}


static void writeVariableReadAccumulateExpression (std::ostringstream&							buf,
												   const std::string&							accumulatorName,
												   const std::string&							name,
												   glu::ShaderType								shaderType,
												   glu::Storage									storage,
												   const ProgramInterfaceDefinition::Program*	program,
												   const glu::VarType&							varType)
{
	if (varType.isBasicType())
	{
		buf << "\t" << accumulatorName << " += ";

		if (glu::isDataTypeScalar(varType.getBasicType()))
			buf << "vec4(float(" << name << "))";
		else if (glu::isDataTypeVector(varType.getBasicType()))
			buf << "vec4(" << name << ".xyxy)";
		else if (glu::isDataTypeMatrix(varType.getBasicType()))
			buf << "vec4(float(" << name << "[0][0]))";
		else if (glu::isDataTypeSamplerMultisample(varType.getBasicType()))
			buf << "vec4(float(textureSize(" << name << ").x))";
		else if (glu::isDataTypeSampler(varType.getBasicType()))
			buf << "vec4(float(textureSize(" << name << ", 0).x))";
		else if (glu::isDataTypeImage(varType.getBasicType()))
			buf << "vec4(float(imageSize(" << name << ").x))";
		else if (varType.getBasicType() == glu::TYPE_UINT_ATOMIC_COUNTER)
			buf << "vec4(float(atomicCounterIncrement(" << name << ")))";
		else
			DE_ASSERT(false);

		buf << ";\n";
	}
	else if (varType.isStructType())
	{
		for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
			writeVariableReadAccumulateExpression(buf,
												  accumulatorName,
												  name + "." + varType.getStructPtr()->getMember(ndx).getName(),
												  shaderType,
												  storage,
												  program,
												  varType.getStructPtr()->getMember(ndx).getType());
	}
	else if (varType.isArrayType())
	{
		if (varType.getArraySize() != glu::VarType::UNSIZED_ARRAY)
		{
			for (int ndx = 0; ndx < varType.getArraySize(); ++ndx)
				writeVariableReadAccumulateExpression(buf,
													  accumulatorName,
													  name + "[" + de::toString(ndx) + "]",
													  shaderType,
													  storage,
													  program,
													  varType.getElementType());
		}
		else if (storage == glu::STORAGE_BUFFER)
		{
			// run-time sized array, read arbitrary
			writeVariableReadAccumulateExpression(buf,
												  accumulatorName,
												  name + "[8]",
												  shaderType,
												  storage,
												  program,
												  varType.getElementType());
		}
		else
		{
			DE_ASSERT(storage == glu::STORAGE_IN);

			if (shaderType == glu::SHADERTYPE_GEOMETRY)
			{
				// implicit sized geometry input array, size = primitive size. Just reading first is enough
				writeVariableReadAccumulateExpression(buf,
													  accumulatorName,
													  name + "[0]",
													  shaderType,
													  storage,
													  program,
													  varType.getElementType());
			}
			else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
			{
				// implicit sized tessellation input array, size = input patch max size. Just reading current is enough
				writeVariableReadAccumulateExpression(buf,
													  accumulatorName,
													  name + "[gl_InvocationID]",
													  shaderType,
													  storage,
													  program,
													  varType.getElementType());
			}
			else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
			{
				// implicit sized tessellation input array, size = output patch max size. Read all to prevent optimizations
				DE_ASSERT(program->getTessellationNumOutputPatchVertices() > 0);
				for (int ndx = 0; ndx < (int)program->getTessellationNumOutputPatchVertices(); ++ndx)
				{
					writeVariableReadAccumulateExpression(buf,
														  accumulatorName,
														  name + "[" + de::toString(ndx) + "]",
														  shaderType,
														  storage,
														  program,
														  varType.getElementType());
				}
			}
			else
				DE_ASSERT(false);
		}
	}
	else
		DE_ASSERT(false);
}

static void writeInterfaceReadAccumulateExpression (std::ostringstream&							buf,
													const std::string&							accumulatorName,
													const glu::InterfaceBlock&					block,
													glu::ShaderType								shaderType,
													const ProgramInterfaceDefinition::Program*	program)
{
	if (block.dimensions.empty())
	{
		const std::string prefix = (block.instanceName.empty()) ? ("") : (block.instanceName + ".");

		for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
		{
			writeVariableReadAccumulateExpression(buf,
												  accumulatorName,
												  prefix + block.variables[ndx].name,
												  shaderType,
												  block.storage,
												  program,
												  block.variables[ndx].varType);
		}
	}
	else
	{
		std::vector<int> index(block.dimensions.size(), 0);

		for (;;)
		{
			// access element
			{
				std::ostringstream name;
				name << block.instanceName;

				for (int dimensionNdx = 0; dimensionNdx < (int)block.dimensions.size(); ++dimensionNdx)
					name << "[" << index[dimensionNdx] << "]";

				for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
				{
					writeVariableReadAccumulateExpression(buf,
														  accumulatorName,
														  name.str() + "." + block.variables[ndx].name,
														  shaderType,
														  block.storage,
														  program,
														  block.variables[ndx].varType);
				}
			}

			// increment index
			if (!incrementMultiDimensionIndex(index, block.dimensions))
				break;
		}
	}
}

static void writeVariableWriteExpression (std::ostringstream&							buf,
										  const std::string&							sourceVec4Name,
										  const std::string&							name,
										  glu::ShaderType								shaderType,
										  glu::Storage									storage,
										  const ProgramInterfaceDefinition::Program*	program,
										  const glu::VarType&							varType)
{
	if (varType.isBasicType())
	{
		buf << "\t" << name << " = ";

		if (glu::isDataTypeScalar(varType.getBasicType()))
			buf << glu::getDataTypeName(varType.getBasicType()) << "(" << sourceVec4Name << ".y)";
		else if (glu::isDataTypeVector(varType.getBasicType()) || glu::isDataTypeMatrix(varType.getBasicType()))
			buf << glu::getDataTypeName(varType.getBasicType()) << "(" << glu::getDataTypeName(glu::getDataTypeScalarType(varType.getBasicType())) << "(" << sourceVec4Name << ".y))";
		else
			DE_ASSERT(false);

		buf << ";\n";
	}
	else if (varType.isStructType())
	{
		for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
			writeVariableWriteExpression(buf,
										 sourceVec4Name,
										 name + "." + varType.getStructPtr()->getMember(ndx).getName(),
										 shaderType,
										 storage,
										 program,
										 varType.getStructPtr()->getMember(ndx).getType());
	}
	else if (varType.isArrayType())
	{
		if (varType.getArraySize() != glu::VarType::UNSIZED_ARRAY)
		{
			for (int ndx = 0; ndx < varType.getArraySize(); ++ndx)
				writeVariableWriteExpression(buf,
											 sourceVec4Name,
											 name + "[" + de::toString(ndx) + "]",
											 shaderType,
											 storage,
											 program,
											 varType.getElementType());
		}
		else if (storage == glu::STORAGE_BUFFER)
		{
			// run-time sized array, write arbitrary
			writeVariableWriteExpression(buf,
										 sourceVec4Name,
										 name + "[9]",
										 shaderType,
										 storage,
										 program,
										 varType.getElementType());
		}
		else
		{
			DE_ASSERT(storage == glu::STORAGE_OUT);

			if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
			{
				// implicit sized tessellation onput array, size = output patch max size. Can only write to gl_InvocationID
				writeVariableWriteExpression(buf,
											 sourceVec4Name,
											 name + "[gl_InvocationID]",
											 shaderType,
											 storage,
											 program,
											 varType.getElementType());
			}
			else
				DE_ASSERT(false);
		}
	}
	else
		DE_ASSERT(false);
}

static void writeInterfaceWriteExpression (std::ostringstream&							buf,
										   const std::string&							sourceVec4Name,
										   const glu::InterfaceBlock&					block,
										   glu::ShaderType								shaderType,
										   const ProgramInterfaceDefinition::Program*	program)
{
	if (block.dimensions.empty())
	{
		const std::string prefix = (block.instanceName.empty()) ? ("") : (block.instanceName + ".");

		for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
		{
			writeVariableWriteExpression(buf,
										 sourceVec4Name,
										 prefix + block.variables[ndx].name,
										 shaderType,
										 block.storage,
										 program,
										 block.variables[ndx].varType);
		}
	}
	else
	{
		std::vector<int> index(block.dimensions.size(), 0);

		for (;;)
		{
			// access element
			{
				std::ostringstream name;
				name << block.instanceName;

				for (int dimensionNdx = 0; dimensionNdx < (int)block.dimensions.size(); ++dimensionNdx)
					name << "[" << index[dimensionNdx] << "]";

				for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
				{
					writeVariableWriteExpression(buf,
												 sourceVec4Name,
												 name.str() + "." + block.variables[ndx].name,
												 shaderType,
												 block.storage,
												 program,
												 block.variables[ndx].varType);
				}
			}

			// increment index
			if (!incrementMultiDimensionIndex(index, block.dimensions))
				break;
		}
	}
}

static bool traverseVariablePath (std::vector<VariablePathComponent>& typePath, const char* subPath, const glu::VarType& type)
{
	glu::VarTokenizer tokenizer(subPath);

	typePath.push_back(VariablePathComponent(&type));

	if (tokenizer.getToken() == glu::VarTokenizer::TOKEN_END)
		return true;

	if (type.isStructType() && tokenizer.getToken() == glu::VarTokenizer::TOKEN_PERIOD)
	{
		tokenizer.advance();

		// malformed path
		if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_IDENTIFIER)
			return false;

		for (int memberNdx = 0; memberNdx < type.getStructPtr()->getNumMembers(); ++memberNdx)
			if (type.getStructPtr()->getMember(memberNdx).getName() == tokenizer.getIdentifier())
				return traverseVariablePath(typePath, subPath + tokenizer.getCurrentTokenEndLocation(), type.getStructPtr()->getMember(memberNdx).getType());

		// malformed path, no such member
		return false;
	}
	else if (type.isArrayType() && tokenizer.getToken() == glu::VarTokenizer::TOKEN_LEFT_BRACKET)
	{
		tokenizer.advance();

		// malformed path
		if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_NUMBER)
			return false;

		tokenizer.advance();
		if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_RIGHT_BRACKET)
			return false;

		return traverseVariablePath(typePath, subPath + tokenizer.getCurrentTokenEndLocation(), type.getElementType());
	}

	return false;
}

static bool traverseVariablePath (std::vector<VariablePathComponent>& typePath, const std::string& path, const glu::VariableDeclaration& var)
{
	if (glu::parseVariableName(path.c_str()) != var.name)
		return false;

	typePath.push_back(VariablePathComponent(&var));
	return traverseVariablePath(typePath, path.c_str() + var.name.length(), var.varType);
}

static bool traverseShaderVariablePath (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Shader* shader, const std::string& path, const VariableSearchFilter& filter)
{
	// Default block variable?
	for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx)
		if (filter.matchesFilter(shader->getDefaultBlock().variables[varNdx]))
			if (traverseVariablePath(typePath, path, shader->getDefaultBlock().variables[varNdx]))
				return true;

	// is variable an interface block variable?
	{
		const std::string blockName = glu::parseVariableName(path.c_str());

		for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
		{
			if (!filter.matchesFilter(shader->getDefaultBlock().interfaceBlocks[interfaceNdx]))
				continue;

			if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].interfaceName == blockName)
			{
				// resource is a member of a named interface block
				// \note there is no array index specifier even if the interface is declared as an array of instances
				const std::string blockMemberPath = path.substr(blockName.size() + 1);
				const std::string blockMemeberName = glu::parseVariableName(blockMemberPath.c_str());

				for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables.size(); ++varNdx)
				{
					if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx].name == blockMemeberName)
					{
						typePath.push_back(VariablePathComponent(&shader->getDefaultBlock().interfaceBlocks[interfaceNdx]));
						return traverseVariablePath(typePath, blockMemberPath, shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx]);
					}
				}

				// terminate search
				return false;
			}
			else if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].instanceName.empty())
			{
				const std::string blockMemeberName = glu::parseVariableName(path.c_str());

				// unnamed block contains such variable?
				for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables.size(); ++varNdx)
				{
					if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx].name == blockMemeberName)
					{
						typePath.push_back(VariablePathComponent(&shader->getDefaultBlock().interfaceBlocks[interfaceNdx]));
						return traverseVariablePath(typePath, path, shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx]);
					}
				}

				// continue search
			}
		}
	}

	return false;
}

static bool traverseProgramVariablePath (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Program* program, const std::string& path, const VariableSearchFilter& filter)
{
	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
	{
		const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];

		if (filter.matchesFilter(shader))
		{
			// \note modifying output variable even when returning false
			typePath.clear();
			if (traverseShaderVariablePath(typePath, shader, path, filter))
				return true;
		}
	}

	return false;
}

static bool containsSubType (const glu::VarType& complexType, glu::DataType basicType)
{
	if (complexType.isBasicType())
	{
		return complexType.getBasicType() == basicType;
	}
	else if (complexType.isArrayType())
	{
		return containsSubType(complexType.getElementType(), basicType);
	}
	else if (complexType.isStructType())
	{
		for (int ndx = 0; ndx < complexType.getStructPtr()->getNumMembers(); ++ndx)
			if (containsSubType(complexType.getStructPtr()->getMember(ndx).getType(), basicType))
				return true;
		return false;
	}
	else
	{
		DE_ASSERT(false);
		return false;
	}
}

static int getNumShaderBlocks (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
{
	int retVal = 0;

	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
	{
		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
		{
			int numInstances = 1;

			for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx)
				numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx];

			retVal += numInstances;
		}
	}

	return retVal;
}

static int getNumAtomicCounterBuffers (const ProgramInterfaceDefinition::Shader* shader)
{
	std::set<int> buffers;

	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
	{
		if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER))
		{
			DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1);
			buffers.insert(shader->getDefaultBlock().variables[ndx].layout.binding);
		}
	}

	return (int)buffers.size();
}

template <typename DataTypeMap>
static int accumulateComplexType (const glu::VarType& complexType, const DataTypeMap& dTypeMap)
{
	if (complexType.isBasicType())
		return dTypeMap(complexType.getBasicType());
	else if (complexType.isArrayType())
	{
		const int arraySize = (complexType.getArraySize() == glu::VarType::UNSIZED_ARRAY) ? (1) : (complexType.getArraySize());
		return arraySize * accumulateComplexType(complexType.getElementType(), dTypeMap);
	}
	else if (complexType.isStructType())
	{
		int sum = 0;
		for (int ndx = 0; ndx < complexType.getStructPtr()->getNumMembers(); ++ndx)
			sum += accumulateComplexType(complexType.getStructPtr()->getMember(ndx).getType(), dTypeMap);
		return sum;
	}
	else
	{
		DE_ASSERT(false);
		return false;
	}
}

template <typename InterfaceBlockFilter, typename VarDeclFilter, typename DataTypeMap>
static int accumulateShader (const ProgramInterfaceDefinition::Shader* shader,
							 const InterfaceBlockFilter& ibFilter,
							 const VarDeclFilter& vdFilter,
							 const DataTypeMap& dMap)
{
	int retVal = 0;

	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
	{
		if (ibFilter(shader->getDefaultBlock().interfaceBlocks[ndx]))
		{
			int numInstances = 1;

			for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx)
				numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx];

			for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].variables.size(); ++varNdx)
				retVal += numInstances * accumulateComplexType(shader->getDefaultBlock().interfaceBlocks[ndx].variables[varNdx].varType, dMap);
		}
	}

	for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx)
		if (vdFilter(shader->getDefaultBlock().variables[varNdx]))
			retVal += accumulateComplexType(shader->getDefaultBlock().variables[varNdx].varType, dMap);

	return retVal;
}

static bool dummyTrueConstantTypeFilter (glu::DataType d)
{
	DE_UNREF(d);
	return true;
}

class InstanceCounter
{
public:
	InstanceCounter (bool (*predicate)(glu::DataType))
		: m_predicate(predicate)
	{
	}

	int operator() (glu::DataType t) const
	{
		return (m_predicate(t)) ? (1) : (0);
	}

private:
	bool (*const m_predicate)(glu::DataType);
};

class InterfaceBlockStorageFilter
{
public:
	InterfaceBlockStorageFilter (glu::Storage storage)
		: m_storage(storage)
	{
	}

	bool operator() (const glu::InterfaceBlock& b) const
	{
		return m_storage == b.storage;
	}

private:
	const glu::Storage m_storage;
};

class VariableDeclarationStorageFilter
{
public:
	VariableDeclarationStorageFilter (glu::Storage storage)
		: m_storage(storage)
	{
	}

	bool operator() (const glu::VariableDeclaration& d) const
	{
		return m_storage == d.storage;
	}

private:
	const glu::Storage m_storage;
};

static int getNumTypeInstances (const glu::VarType& complexType, bool (*predicate)(glu::DataType))
{
	return accumulateComplexType(complexType, InstanceCounter(predicate));
}

static int getNumTypeInstances (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage, bool (*predicate)(glu::DataType))
{
	return accumulateShader(shader, InterfaceBlockStorageFilter(storage), VariableDeclarationStorageFilter(storage), InstanceCounter(predicate));
}

static int getNumTypeInstances (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
{
	return getNumTypeInstances(shader, storage, dummyTrueConstantTypeFilter);
}

static int accumulateShaderStorage (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage, int (*typeMap)(glu::DataType))
{
	return accumulateShader(shader, InterfaceBlockStorageFilter(storage), VariableDeclarationStorageFilter(storage), typeMap);
}

static int getNumDataTypeComponents (glu::DataType type)
{
	if (glu::isDataTypeScalarOrVector(type) || glu::isDataTypeMatrix(type))
		return glu::getDataTypeScalarSize(type);
	else
		return 0;
}

static int getNumDataTypeVectors (glu::DataType type)
{
	if (glu::isDataTypeScalar(type))
		return 1;
	else if (glu::isDataTypeVector(type))
		return 1;
	else if (glu::isDataTypeMatrix(type))
		return glu::getDataTypeMatrixNumColumns(type);
	else
		return 0;
}

static int getNumComponents (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
{
	return accumulateShaderStorage(shader, storage, getNumDataTypeComponents);
}

static int getNumVectors (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
{
	return accumulateShaderStorage(shader, storage, getNumDataTypeVectors);
}

static int getNumDefaultBlockComponents (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
{
	int retVal = 0;

	for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx)
		if (shader->getDefaultBlock().variables[varNdx].storage == storage)
			retVal += accumulateComplexType(shader->getDefaultBlock().variables[varNdx].varType, getNumDataTypeComponents);

	return retVal;
}

static int getMaxBufferBinding (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
{
	int maxBinding = -1;

	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
	{
		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
		{
			const int	binding			= (shader->getDefaultBlock().interfaceBlocks[ndx].layout.binding == -1) ? (0) : (shader->getDefaultBlock().interfaceBlocks[ndx].layout.binding);
			int			numInstances	= 1;

			for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx)
				numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx];

			maxBinding = de::max(maxBinding, binding + numInstances - 1);
		}
	}

	return (int)maxBinding;
}

static int getBufferTypeSize (glu::DataType type, glu::MatrixOrder order)
{
	// assume vec4 alignments, should produce values greater than or equal to the actual resource usage
	int numVectors = 0;

	if (glu::isDataTypeScalarOrVector(type))
		numVectors = 1;
	else if (glu::isDataTypeMatrix(type) && order == glu::MATRIXORDER_ROW_MAJOR)
		numVectors = glu::getDataTypeMatrixNumRows(type);
	else if (glu::isDataTypeMatrix(type) && order != glu::MATRIXORDER_ROW_MAJOR)
		numVectors = glu::getDataTypeMatrixNumColumns(type);
	else
		DE_ASSERT(false);

	return 4 * numVectors;
}

static int getBufferVariableSize (const glu::VarType& type, glu::MatrixOrder order)
{
	if (type.isBasicType())
		return getBufferTypeSize(type.getBasicType(), order);
	else if (type.isArrayType())
	{
		const int arraySize = (type.getArraySize() == glu::VarType::UNSIZED_ARRAY) ? (1) : (type.getArraySize());
		return arraySize * getBufferVariableSize(type.getElementType(), order);
	}
	else if (type.isStructType())
	{
		int sum = 0;
		for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
			sum += getBufferVariableSize(type.getStructPtr()->getMember(ndx).getType(), order);
		return sum;
	}
	else
	{
		DE_ASSERT(false);
		return false;
	}
}

static int getBufferSize (const glu::InterfaceBlock& block, glu::MatrixOrder blockOrder)
{
	int size = 0;

	for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
		size += getBufferVariableSize(block.variables[ndx].varType, (block.variables[ndx].layout.matrixOrder == glu::MATRIXORDER_LAST) ? (blockOrder) : (block.variables[ndx].layout.matrixOrder));

	return size;
}

static int getBufferMaxSize (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
{
	int maxSize = 0;

	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
			maxSize = de::max(maxSize, getBufferSize(shader->getDefaultBlock().interfaceBlocks[ndx], shader->getDefaultBlock().interfaceBlocks[ndx].layout.matrixOrder));

	return (int)maxSize;
}

static int getAtomicCounterMaxBinding (const ProgramInterfaceDefinition::Shader* shader)
{
	int maxBinding = -1;

	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
	{
		if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER))
		{
			DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1);
			maxBinding = de::max(maxBinding, shader->getDefaultBlock().variables[ndx].layout.binding);
		}
	}

	return (int)maxBinding;
}

static int getUniformMaxBinding (const ProgramInterfaceDefinition::Shader* shader, bool (*predicate)(glu::DataType))
{
	int maxBinding = -1;

	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
	{
		const int binding		= (shader->getDefaultBlock().variables[ndx].layout.binding == -1) ? (0) : (shader->getDefaultBlock().variables[ndx].layout.binding);
		const int numInstances	= getNumTypeInstances(shader->getDefaultBlock().variables[ndx].varType, predicate);

		maxBinding = de::max(maxBinding, binding + numInstances - 1);
	}

	return maxBinding;
}

static int getAtomicCounterMaxBufferSize (const ProgramInterfaceDefinition::Shader* shader)
{
	std::map<int, int>	bufferSizes;
	int					maxSize			= 0;

	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
	{
		if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER))
		{
			const int bufferBinding	= shader->getDefaultBlock().variables[ndx].layout.binding;
			const int offset		= (shader->getDefaultBlock().variables[ndx].layout.offset == -1) ? (0) : (shader->getDefaultBlock().variables[ndx].layout.offset);
			const int size			= offset + 4 * getNumTypeInstances(shader->getDefaultBlock().variables[ndx].varType, glu::isDataTypeAtomicCounter);

			DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1);

			if (bufferSizes.find(bufferBinding) == bufferSizes.end())
				bufferSizes[bufferBinding] = size;
			else
				bufferSizes[bufferBinding] = de::max<int>(bufferSizes[bufferBinding], size);
		}
	}

	for (std::map<int, int>::iterator it = bufferSizes.begin(); it != bufferSizes.end(); ++it)
		maxSize = de::max<int>(maxSize, it->second);

	return maxSize;
}

static int getNumFeedbackVaryingComponents (const ProgramInterfaceDefinition::Program* program, const std::string& name)
{
	std::vector<VariablePathComponent> path;

	if (name == "gl_Position")
		return 4;

	DE_ASSERT(deStringBeginsWith(name.c_str(), "gl_") == DE_FALSE);

	if (!traverseProgramVariablePath(path, program, name, VariableSearchFilter::createShaderTypeStorageFilter(getProgramTransformFeedbackStage(program), glu::STORAGE_OUT)))
		DE_ASSERT(false); // Program failed validate, invalid operation

	return accumulateComplexType(*path.back().getVariableType(), getNumDataTypeComponents);
}

static int getNumXFBComponents (const ProgramInterfaceDefinition::Program* program)
{
	int numComponents = 0;

	for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx)
		numComponents += getNumFeedbackVaryingComponents(program, program->getTransformFeedbackVaryings()[ndx]);

	return numComponents;
}

static int getNumMaxXFBOutputComponents (const ProgramInterfaceDefinition::Program* program)
{
	int numComponents = 0;

	for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx)
		numComponents = de::max(numComponents, getNumFeedbackVaryingComponents(program, program->getTransformFeedbackVaryings()[ndx]));

	return numComponents;
}

static int getFragmentOutputMaxLocation (const ProgramInterfaceDefinition::Shader* shader)
{
	DE_ASSERT(shader->getType() == glu::SHADERTYPE_FRAGMENT);

	int maxOutputLocation = -1;

	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
	{
		if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_OUT)
		{
			// missing location qualifier means location == 0
			const int outputLocation		= (shader->getDefaultBlock().variables[ndx].layout.location == -1)
												? (0)
												: (shader->getDefaultBlock().variables[ndx].layout.location);

			// only basic types or arrays of basic types possible
			DE_ASSERT(!shader->getDefaultBlock().variables[ndx].varType.isStructType());

			const int locationSlotsTaken	= (shader->getDefaultBlock().variables[ndx].varType.isArrayType())
												? (shader->getDefaultBlock().variables[ndx].varType.getArraySize())
												: (1);

			maxOutputLocation = de::max(maxOutputLocation, outputLocation + locationSlotsTaken - 1);
		}
	}

	return maxOutputLocation;
}

} // anonymous

std::vector<std::string> getProgramInterfaceBlockMemberResourceList (const glu::InterfaceBlock& interfaceBlock)
{
	const std::string			namePrefix					= (!interfaceBlock.instanceName.empty()) ? (interfaceBlock.interfaceName + ".") : ("");
	const bool					isTopLevelBufferVariable	= (interfaceBlock.storage == glu::STORAGE_BUFFER);
	std::vector<std::string>	resources;

	// \note this is defined in the GLSL spec, not in the GL spec
	for (int variableNdx = 0; variableNdx < (int)interfaceBlock.variables.size(); ++variableNdx)
		generateVariableTypeResourceNames(resources,
										  namePrefix + interfaceBlock.variables[variableNdx].name,
										  interfaceBlock.variables[variableNdx].varType,
										  (isTopLevelBufferVariable) ?
											(RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE) :
											(RESOURCE_NAME_GENERATION_FLAG_DEFAULT));

	return resources;
}

std::vector<std::string> getProgramInterfaceResourceList (const ProgramInterfaceDefinition::Program* program, ProgramInterface interface)
{
	// The same {uniform (block), buffer (variable)} can exist in multiple shaders, remove duplicates but keep order
	const bool					removeDuplicated	= (interface == PROGRAMINTERFACE_UNIFORM)			||
													  (interface == PROGRAMINTERFACE_UNIFORM_BLOCK)		||
													  (interface == PROGRAMINTERFACE_BUFFER_VARIABLE)	||
													  (interface == PROGRAMINTERFACE_SHADER_STORAGE_BLOCK);
	std::vector<std::string>	resources;

	switch (interface)
	{
		case PROGRAMINTERFACE_UNIFORM:
		case PROGRAMINTERFACE_BUFFER_VARIABLE:
		{
			const glu::Storage storage = (interface == PROGRAMINTERFACE_UNIFORM) ? (glu::STORAGE_UNIFORM) : (glu::STORAGE_BUFFER);

			for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
			{
				const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];

				for (int variableNdx = 0; variableNdx < (int)shader->getDefaultBlock().variables.size(); ++variableNdx)
					if (shader->getDefaultBlock().variables[variableNdx].storage == storage)
						generateVariableTypeResourceNames(resources,
														  shader->getDefaultBlock().variables[variableNdx].name,
														  shader->getDefaultBlock().variables[variableNdx].varType,
														  RESOURCE_NAME_GENERATION_FLAG_DEFAULT);

				for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
				{
					const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
					if (interfaceBlock.storage == storage)
					{
						const std::vector<std::string> blockResources = getProgramInterfaceBlockMemberResourceList(interfaceBlock);
						resources.insert(resources.end(), blockResources.begin(), blockResources.end());
					}
				}
			}
			break;
		}

		case PROGRAMINTERFACE_UNIFORM_BLOCK:
		case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK:
		{
			const glu::Storage storage = (interface == PROGRAMINTERFACE_UNIFORM_BLOCK) ? (glu::STORAGE_UNIFORM) : (glu::STORAGE_BUFFER);

			for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
			{
				const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];
				for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
				{
					const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
					if (interfaceBlock.storage == storage)
					{
						std::vector<int> index(interfaceBlock.dimensions.size(), 0);

						for (;;)
						{
							// add resource string for each element
							{
								std::ostringstream name;
								name << interfaceBlock.interfaceName;

								for (int dimensionNdx = 0; dimensionNdx < (int)interfaceBlock.dimensions.size(); ++dimensionNdx)
									name << "[" << index[dimensionNdx] << "]";

								resources.push_back(name.str());
							}

							// increment index
							if (!incrementMultiDimensionIndex(index, interfaceBlock.dimensions))
								break;
						}
					}
				}
			}
			break;
		}

		case PROGRAMINTERFACE_PROGRAM_INPUT:
		case PROGRAMINTERFACE_PROGRAM_OUTPUT:
		{
			const glu::Storage		queryStorage		= (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (glu::STORAGE_IN) : (glu::STORAGE_OUT);
			const glu::Storage		queryPatchStorage	= (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (glu::STORAGE_PATCH_IN) : (glu::STORAGE_PATCH_OUT);
			const glu::ShaderType	shaderType			= (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (program->getFirstStage()) : (program->getLastStage());

			for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
			{
				const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];

				if (shader->getType() != shaderType)
					continue;

				for (int variableNdx = 0; variableNdx < (int)shader->getDefaultBlock().variables.size(); ++variableNdx)
				{
					const glu::Storage variableStorage = shader->getDefaultBlock().variables[variableNdx].storage;
					if (variableStorage == queryStorage || variableStorage == queryPatchStorage)
						generateVariableTypeResourceNames(resources,
														  shader->getDefaultBlock().variables[variableNdx].name,
														  shader->getDefaultBlock().variables[variableNdx].varType,
														  RESOURCE_NAME_GENERATION_FLAG_DEFAULT);
				}

				for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
				{
					const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
					if (interfaceBlock.storage == queryStorage || interfaceBlock.storage == queryPatchStorage)
					{
						const std::vector<std::string> blockResources = getProgramInterfaceBlockMemberResourceList(interfaceBlock);
						resources.insert(resources.end(), blockResources.begin(), blockResources.end());
					}
				}
			}

			// built-ins
			if (interface == PROGRAMINTERFACE_PROGRAM_INPUT)
			{
				if (shaderType == glu::SHADERTYPE_VERTEX && resources.empty())
					resources.push_back("gl_VertexID"); // only read from when there are no other inputs
				else if (shaderType == glu::SHADERTYPE_FRAGMENT && resources.empty())
					resources.push_back("gl_FragCoord"); // only read from when there are no other inputs
				else if (shaderType == glu::SHADERTYPE_GEOMETRY)
					resources.push_back("gl_PerVertex.gl_Position");
				else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
				{
					resources.push_back("gl_InvocationID");
					resources.push_back("gl_PerVertex.gl_Position");
				}
				else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
					resources.push_back("gl_PerVertex.gl_Position");
				else if (shaderType == glu::SHADERTYPE_COMPUTE && resources.empty())
					resources.push_back("gl_NumWorkGroups"); // only read from when there are no other inputs
			}
			else if (interface == PROGRAMINTERFACE_PROGRAM_OUTPUT)
			{
				if (shaderType == glu::SHADERTYPE_VERTEX)
					resources.push_back("gl_Position");
				else if (shaderType == glu::SHADERTYPE_FRAGMENT && resources.empty())
					resources.push_back("gl_FragDepth"); // only written to when there are no other outputs
				else if (shaderType == glu::SHADERTYPE_GEOMETRY)
					resources.push_back("gl_Position");
				else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
				{
					resources.push_back("gl_PerVertex.gl_Position");
					resources.push_back("gl_TessLevelOuter[0]");
					resources.push_back("gl_TessLevelInner[0]");
				}
				else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
					resources.push_back("gl_Position");
			}

			break;
		}

		case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING:
		{
			const glu::ShaderType xfbStage = getProgramTransformFeedbackStage(program);

			for (int varyingNdx = 0; varyingNdx < (int)program->getTransformFeedbackVaryings().size(); ++varyingNdx)
			{
				const std::string& varyingName = program->getTransformFeedbackVaryings()[varyingNdx];

				if (deStringBeginsWith(varyingName.c_str(), "gl_"))
					resources.push_back(varyingName); // builtin
				else
				{
					std::vector<VariablePathComponent> path;

					if (!traverseProgramVariablePath(path, program, varyingName, VariableSearchFilter::createShaderTypeStorageFilter(xfbStage, glu::STORAGE_OUT)))
						DE_ASSERT(false); // Program failed validate, invalid operation

					generateVariableTypeResourceNames(resources,
													  varyingName,
													  *path.back().getVariableType(),
													  RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE);
				}
			}

			break;
		}

		default:
			DE_ASSERT(false);
	}

	if (removeDuplicated)
	{
		std::set<std::string>		addedVariables;
		std::vector<std::string>	uniqueResouces;

		for (int ndx = 0; ndx < (int)resources.size(); ++ndx)
		{
			if (addedVariables.find(resources[ndx]) == addedVariables.end())
			{
				addedVariables.insert(resources[ndx]);
				uniqueResouces.push_back(resources[ndx]);
			}
		}

		uniqueResouces.swap(resources);
	}

	return resources;
}

/**
 * Name of the dummy uniform added by generateProgramInterfaceProgramSources
 *
 * A uniform named "dummyZero" is added by
 * generateProgramInterfaceProgramSources.  It is used in expressions to
 * prevent various program resources from being eliminated by the GLSL
 * compiler's optimizer.
 *
 * \sa deqp::gles31::Functional::ProgramInterfaceDefinition::generateProgramInterfaceProgramSources
 */
const char* getDummyZeroUniformName()
{
	return "dummyZero";
}

glu::ProgramSources generateProgramInterfaceProgramSources (const ProgramInterfaceDefinition::Program* program)
{
	glu::ProgramSources sources;

	DE_ASSERT(program->isValid());

	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
	{
		const ProgramInterfaceDefinition::Shader*	shader						= program->getShaders()[shaderNdx];
		bool										containsUserDefinedOutputs	= false;
		bool										containsUserDefinedInputs	= false;
		std::ostringstream							sourceBuf;
		std::ostringstream							usageBuf;

		sourceBuf	<< glu::getGLSLVersionDeclaration(shader->getVersion()) << "\n"
					<< getShaderExtensionDeclarations(shader)
					<< getShaderTypeDeclarations(program, shader)
					<< "\n";

		// Struct definitions

		writeStructureDefinitions(sourceBuf, shader->getDefaultBlock());

		// variables in the default scope

		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
			sourceBuf << shader->getDefaultBlock().variables[ndx] << ";\n";

		if (!shader->getDefaultBlock().variables.empty())
			sourceBuf << "\n";

		// Interface blocks

		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
			writeInterfaceBlock(sourceBuf, shader->getDefaultBlock().interfaceBlocks[ndx]);

		// Use inputs and outputs so that they won't be removed by the optimizer

		usageBuf <<	"highp uniform vec4 " << getDummyZeroUniformName() << "; // Default value is vec4(0.0).\n"
					"highp vec4 readInputs()\n"
					"{\n"
					"	highp vec4 retValue = " << getDummyZeroUniformName() << ";\n";

		// User-defined inputs

		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
		{
			if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_IN			||
				shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_PATCH_IN	||
				shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_UNIFORM)
			{
				writeVariableReadAccumulateExpression(usageBuf,
													  "retValue",
													  shader->getDefaultBlock().variables[ndx].name,
													  shader->getType(),
													  shader->getDefaultBlock().variables[ndx].storage,
													  program,
													  shader->getDefaultBlock().variables[ndx].varType);
				containsUserDefinedInputs = true;
			}
		}

		for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
		{
			const glu::InterfaceBlock& interface = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
			if (isReadableInterface(interface))
			{
				writeInterfaceReadAccumulateExpression(usageBuf,
													   "retValue",
													   interface,
													   shader->getType(),
													   program);
				containsUserDefinedInputs = true;
			}
		}

		// Built-in-inputs

		switch (shader->getType())
		{
			case glu::SHADERTYPE_VERTEX:
				// make readInputs to never be compile time constant
				if (!containsUserDefinedInputs)
					usageBuf << "	retValue += vec4(float(gl_VertexID));\n";
				break;

			case glu::SHADERTYPE_FRAGMENT:
				// make readInputs to never be compile time constant
				if (!containsUserDefinedInputs)
					usageBuf << "	retValue += gl_FragCoord;\n";
				break;
			case glu::SHADERTYPE_GEOMETRY:
				// always use previous stage's output values so that previous stage won't be optimized out
				usageBuf << "	retValue += gl_in[0].gl_Position;\n";
				break;
			case glu::SHADERTYPE_TESSELLATION_CONTROL:
				// always use previous stage's output values so that previous stage won't be optimized out
				usageBuf << "	retValue += gl_in[0].gl_Position;\n";
				break;
			case glu::SHADERTYPE_TESSELLATION_EVALUATION:
				// always use previous stage's output values so that previous stage won't be optimized out
				usageBuf << "	retValue += gl_in[0].gl_Position;\n";
				break;

			case glu::SHADERTYPE_COMPUTE:
				// make readInputs to never be compile time constant
				if (!containsUserDefinedInputs)
					usageBuf << "	retValue += vec4(float(gl_NumWorkGroups.x));\n";
				break;
			default:
				DE_ASSERT(false);
		}

		usageBuf <<	"	return retValue;\n"
					"}\n\n";

		usageBuf <<	"void writeOutputs(in highp vec4 dummyValue)\n"
					"{\n";

		// User-defined outputs

		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
		{
			if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_OUT ||
				shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_PATCH_OUT)
			{
				writeVariableWriteExpression(usageBuf,
											 "dummyValue",
											 shader->getDefaultBlock().variables[ndx].name,
											 shader->getType(),
											 shader->getDefaultBlock().variables[ndx].storage,
											 program,
											 shader->getDefaultBlock().variables[ndx].varType);
				containsUserDefinedOutputs = true;
			}
		}

		for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
		{
			const glu::InterfaceBlock& interface = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
			if (isWritableInterface(interface))
			{
				writeInterfaceWriteExpression(usageBuf, "dummyValue", interface, shader->getType(), program);
				containsUserDefinedOutputs = true;
			}
		}

		// Builtin-outputs that must be written to

		if (shader->getType() == glu::SHADERTYPE_VERTEX)
			usageBuf << "	gl_Position = dummyValue;\n";
		else if (shader->getType() == glu::SHADERTYPE_GEOMETRY)
			usageBuf << "	gl_Position = dummyValue;\n"
						 "	EmitVertex();\n";
		else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_CONTROL)
			usageBuf << "	gl_out[gl_InvocationID].gl_Position = dummyValue;\n"
						"	gl_TessLevelOuter[0] = 2.8;\n"
						"	gl_TessLevelOuter[1] = 2.8;\n"
						"	gl_TessLevelOuter[2] = 2.8;\n"
						"	gl_TessLevelOuter[3] = 2.8;\n"
						"	gl_TessLevelInner[0] = 2.8;\n"
						"	gl_TessLevelInner[1] = 2.8;\n";
		else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_EVALUATION)
			usageBuf << "	gl_Position = dummyValue;\n";

		// Output to sink input data to

		if (!containsUserDefinedOutputs)
		{
			if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
				usageBuf << "	gl_FragDepth = dot(dummyValue.xy, dummyValue.xw);\n";
			else if (shader->getType() == glu::SHADERTYPE_COMPUTE)
				usageBuf << "	dummyOutputBlock.dummyValue = dummyValue;\n";
		}

		usageBuf <<	"}\n\n"
					"void main()\n"
					"{\n"
					"	writeOutputs(readInputs());\n"
					"}\n";

		// Interface for dummy output

		if (shader->getType() == glu::SHADERTYPE_COMPUTE && !containsUserDefinedOutputs)
		{
			sourceBuf	<< "writeonly buffer DummyOutputInterface\n"
						<< "{\n"
						<< "	highp vec4 dummyValue;\n"
						<< "} dummyOutputBlock;\n\n";
		}

		sources << glu::ShaderSource(shader->getType(), sourceBuf.str() + usageBuf.str());
	}

	if (program->isSeparable())
		sources << glu::ProgramSeparable(true);

	for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx)
		sources << glu::TransformFeedbackVarying(program->getTransformFeedbackVaryings()[ndx]);

	if (program->getTransformFeedbackMode())
		sources << glu::TransformFeedbackMode(program->getTransformFeedbackMode());

	return sources;
}

bool findProgramVariablePathByPathName (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Program* program, const std::string& pathName, const VariableSearchFilter& filter)
{
	std::vector<VariablePathComponent> modifiedPath;

	if (!traverseProgramVariablePath(modifiedPath, program, pathName, filter))
		return false;

	// modify param only on success
	typePath.swap(modifiedPath);
	return true;
}

ProgramInterfaceDefinition::ShaderResourceUsage getShaderResourceUsage (const ProgramInterfaceDefinition::Program* program, const ProgramInterfaceDefinition::Shader* shader)
{
	ProgramInterfaceDefinition::ShaderResourceUsage retVal;

	retVal.numInputs						= getNumTypeInstances(shader, glu::STORAGE_IN);
	retVal.numInputVectors					= getNumVectors(shader, glu::STORAGE_IN);
	retVal.numInputComponents				= getNumComponents(shader, glu::STORAGE_IN);

	retVal.numOutputs						= getNumTypeInstances(shader, glu::STORAGE_OUT);
	retVal.numOutputVectors					= getNumVectors(shader, glu::STORAGE_OUT);
	retVal.numOutputComponents				= getNumComponents(shader, glu::STORAGE_OUT);

	retVal.numPatchInputComponents			= getNumComponents(shader, glu::STORAGE_PATCH_IN);
	retVal.numPatchOutputComponents			= getNumComponents(shader, glu::STORAGE_PATCH_OUT);

	retVal.numDefaultBlockUniformComponents	= getNumDefaultBlockComponents(shader, glu::STORAGE_UNIFORM);
	retVal.numCombinedUniformComponents		= getNumComponents(shader, glu::STORAGE_UNIFORM);
	retVal.numUniformVectors				= getNumVectors(shader, glu::STORAGE_UNIFORM);

	retVal.numSamplers						= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeSampler);
	retVal.numImages						= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage);

	retVal.numAtomicCounterBuffers			= getNumAtomicCounterBuffers(shader);
	retVal.numAtomicCounters				= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeAtomicCounter);

	retVal.numUniformBlocks					= getNumShaderBlocks(shader, glu::STORAGE_UNIFORM);
	retVal.numShaderStorageBlocks			= getNumShaderBlocks(shader, glu::STORAGE_BUFFER);

	// add builtins
	switch (shader->getType())
	{
		case glu::SHADERTYPE_VERTEX:
			// gl_Position is not counted
			break;

		case glu::SHADERTYPE_FRAGMENT:
			// nada
			break;

		case glu::SHADERTYPE_GEOMETRY:
			// gl_Position in (point mode => size 1)
			retVal.numInputs			+= 1;
			retVal.numInputVectors		+= 1;
			retVal.numInputComponents	+= 4;

			// gl_Position out
			retVal.numOutputs			+= 1;
			retVal.numOutputVectors		+= 1;
			retVal.numOutputComponents	+= 4;
			break;

		case glu::SHADERTYPE_TESSELLATION_CONTROL:
			// gl_Position in is read up to gl_InstanceID
			retVal.numInputs			+= 1 * program->getTessellationNumOutputPatchVertices();
			retVal.numInputVectors		+= 1 * program->getTessellationNumOutputPatchVertices();
			retVal.numInputComponents	+= 4 * program->getTessellationNumOutputPatchVertices();

			// gl_Position out, size = num patch out vertices
			retVal.numOutputs			+= 1 * program->getTessellationNumOutputPatchVertices();
			retVal.numOutputVectors		+= 1 * program->getTessellationNumOutputPatchVertices();
			retVal.numOutputComponents	+= 4 * program->getTessellationNumOutputPatchVertices();
			break;

		case glu::SHADERTYPE_TESSELLATION_EVALUATION:
			// gl_Position in is read up to gl_InstanceID
			retVal.numInputs			+= 1 * program->getTessellationNumOutputPatchVertices();
			retVal.numInputVectors		+= 1 * program->getTessellationNumOutputPatchVertices();
			retVal.numInputComponents	+= 4 * program->getTessellationNumOutputPatchVertices();

			// gl_Position out
			retVal.numOutputs			+= 1;
			retVal.numOutputVectors		+= 1;
			retVal.numOutputComponents	+= 4;
			break;

		case glu::SHADERTYPE_COMPUTE:
			// nada
			break;

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

ProgramInterfaceDefinition::ProgramResourceUsage getCombinedProgramResourceUsage (const ProgramInterfaceDefinition::Program* program)
{
	ProgramInterfaceDefinition::ProgramResourceUsage	retVal;
	int													numVertexOutputComponents	= 0;
	int													numFragmentInputComponents	= 0;
	int													numVertexOutputVectors		= 0;
	int													numFragmentInputVectors		= 0;

	retVal.uniformBufferMaxBinding					= -1; // max binding is inclusive upper bound. Allow 0 bindings by using negative value
	retVal.uniformBufferMaxSize						= 0;
	retVal.numUniformBlocks							= 0;
	retVal.numCombinedVertexUniformComponents		= 0;
	retVal.numCombinedFragmentUniformComponents		= 0;
	retVal.numCombinedGeometryUniformComponents		= 0;
	retVal.numCombinedTessControlUniformComponents	= 0;
	retVal.numCombinedTessEvalUniformComponents		= 0;
	retVal.shaderStorageBufferMaxBinding			= -1; // see above
	retVal.shaderStorageBufferMaxSize				= 0;
	retVal.numShaderStorageBlocks					= 0;
	retVal.numVaryingComponents						= 0;
	retVal.numVaryingVectors						= 0;
	retVal.numCombinedSamplers						= 0;
	retVal.atomicCounterBufferMaxBinding			= -1; // see above
	retVal.atomicCounterBufferMaxSize				= 0;
	retVal.numAtomicCounterBuffers					= 0;
	retVal.numAtomicCounters						= 0;
	retVal.maxImageBinding							= -1; // see above
	retVal.numCombinedImages						= 0;
	retVal.numCombinedOutputResources				= 0;
	retVal.numXFBInterleavedComponents				= 0;
	retVal.numXFBSeparateAttribs					= 0;
	retVal.numXFBSeparateComponents					= 0;
	retVal.fragmentOutputMaxBinding					= -1; // see above

	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
	{
		const ProgramInterfaceDefinition::Shader* const shader = program->getShaders()[shaderNdx];

		retVal.uniformBufferMaxBinding		= de::max(retVal.uniformBufferMaxBinding, getMaxBufferBinding(shader, glu::STORAGE_UNIFORM));
		retVal.uniformBufferMaxSize			= de::max(retVal.uniformBufferMaxSize, getBufferMaxSize(shader, glu::STORAGE_UNIFORM));
		retVal.numUniformBlocks				+= getNumShaderBlocks(shader, glu::STORAGE_UNIFORM);

		switch (shader->getType())
		{
			case glu::SHADERTYPE_VERTEX:					retVal.numCombinedVertexUniformComponents		+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
			case glu::SHADERTYPE_FRAGMENT:					retVal.numCombinedFragmentUniformComponents		+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
			case glu::SHADERTYPE_GEOMETRY:					retVal.numCombinedGeometryUniformComponents		+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
			case glu::SHADERTYPE_TESSELLATION_CONTROL:		retVal.numCombinedTessControlUniformComponents	+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
			case glu::SHADERTYPE_TESSELLATION_EVALUATION:	retVal.numCombinedTessEvalUniformComponents		+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
			default: break;
		}

		retVal.shaderStorageBufferMaxBinding	= de::max(retVal.shaderStorageBufferMaxBinding, getMaxBufferBinding(shader, glu::STORAGE_BUFFER));
		retVal.shaderStorageBufferMaxSize		= de::max(retVal.shaderStorageBufferMaxSize, getBufferMaxSize(shader, glu::STORAGE_BUFFER));
		retVal.numShaderStorageBlocks			+= getNumShaderBlocks(shader, glu::STORAGE_BUFFER);

		if (shader->getType() == glu::SHADERTYPE_VERTEX)
		{
			numVertexOutputComponents	+= getNumComponents(shader, glu::STORAGE_OUT);
			numVertexOutputVectors		+= getNumVectors(shader, glu::STORAGE_OUT);
		}
		else if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
		{
			numFragmentInputComponents	+= getNumComponents(shader, glu::STORAGE_IN);
			numFragmentInputVectors		+= getNumVectors(shader, glu::STORAGE_IN);
		}

		retVal.numCombinedSamplers	+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeSampler);

		retVal.atomicCounterBufferMaxBinding	= de::max(retVal.atomicCounterBufferMaxBinding, getAtomicCounterMaxBinding(shader));
		retVal.atomicCounterBufferMaxSize		= de::max(retVal.atomicCounterBufferMaxSize, getAtomicCounterMaxBufferSize(shader));
		retVal.numAtomicCounterBuffers			+= getNumAtomicCounterBuffers(shader);
		retVal.numAtomicCounters				+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeAtomicCounter);
		retVal.maxImageBinding					= de::max(retVal.maxImageBinding, getUniformMaxBinding(shader, glu::isDataTypeImage));
		retVal.numCombinedImages				+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage);

		retVal.numCombinedOutputResources		+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage);
		retVal.numCombinedOutputResources		+= getNumShaderBlocks(shader, glu::STORAGE_BUFFER);

		if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
		{
			retVal.numCombinedOutputResources += getNumVectors(shader, glu::STORAGE_OUT);
			retVal.fragmentOutputMaxBinding = de::max(retVal.fragmentOutputMaxBinding, getFragmentOutputMaxLocation(shader));
		}
	}

	if (program->getTransformFeedbackMode() == GL_INTERLEAVED_ATTRIBS)
		retVal.numXFBInterleavedComponents = getNumXFBComponents(program);
	else if (program->getTransformFeedbackMode() == GL_SEPARATE_ATTRIBS)
	{
		retVal.numXFBSeparateAttribs	= (int)program->getTransformFeedbackVaryings().size();
		retVal.numXFBSeparateComponents	= getNumMaxXFBOutputComponents(program);
	}

	// legacy limits
	retVal.numVaryingComponents	= de::max(numVertexOutputComponents, numFragmentInputComponents);
	retVal.numVaryingVectors	= de::max(numVertexOutputVectors, numFragmentInputVectors);

	return retVal;
}

} // Functional
} // gles31
} // deqp
