Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Program interface utilities
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fProgramInterfaceDefinitionUtil.hpp"
     25 #include "es31fProgramInterfaceDefinition.hpp"
     26 #include "gluVarType.hpp"
     27 #include "gluVarTypeUtil.hpp"
     28 #include "gluShaderUtil.hpp"
     29 #include "deString.h"
     30 #include "deStringUtil.hpp"
     31 #include "glwEnums.hpp"
     32 
     33 #include <set>
     34 #include <map>
     35 #include <sstream>
     36 #include <vector>
     37 #include <algorithm>
     38 
     39 namespace deqp
     40 {
     41 namespace gles31
     42 {
     43 namespace Functional
     44 {
     45 namespace ProgramInterfaceDefinition
     46 {
     47 
     48 VariableSearchFilter::VariableSearchFilter (void)
     49 	: m_shaderTypeBits	(0xFFFFFFFFul)
     50 	, m_storageBits		(0xFFFFFFFFul)
     51 {
     52 }
     53 
     54 VariableSearchFilter VariableSearchFilter::createShaderTypeFilter (glu::ShaderType type)
     55 {
     56 	DE_ASSERT(type < glu::SHADERTYPE_LAST);
     57 
     58 	VariableSearchFilter filter;
     59 	filter.m_shaderTypeBits = (1u << type);
     60 	return filter;
     61 }
     62 
     63 VariableSearchFilter VariableSearchFilter::createStorageFilter (glu::Storage storage)
     64 {
     65 	DE_ASSERT(storage < glu::STORAGE_LAST);
     66 
     67 	VariableSearchFilter filter;
     68 	filter.m_storageBits = (1u << storage);
     69 	return filter;
     70 }
     71 
     72 VariableSearchFilter VariableSearchFilter::createShaderTypeStorageFilter (glu::ShaderType type, glu::Storage storage)
     73 {
     74 	return logicalAnd(createShaderTypeFilter(type), createStorageFilter(storage));
     75 }
     76 
     77 VariableSearchFilter VariableSearchFilter::logicalOr (const VariableSearchFilter& a, const VariableSearchFilter& b)
     78 {
     79 	VariableSearchFilter filter;
     80 	filter.m_shaderTypeBits	= a.m_shaderTypeBits | b.m_shaderTypeBits;
     81 	filter.m_storageBits	= a.m_storageBits | b.m_storageBits;
     82 	return filter;
     83 }
     84 
     85 VariableSearchFilter VariableSearchFilter::logicalAnd (const VariableSearchFilter& a, const VariableSearchFilter& b)
     86 {
     87 	VariableSearchFilter filter;
     88 	filter.m_shaderTypeBits	= a.m_shaderTypeBits & b.m_shaderTypeBits;
     89 	filter.m_storageBits	= a.m_storageBits & b.m_storageBits;
     90 	return filter;
     91 }
     92 
     93 bool VariableSearchFilter::matchesFilter (const ProgramInterfaceDefinition::Shader* shader) const
     94 {
     95 	DE_ASSERT(shader->getType() < glu::SHADERTYPE_LAST);
     96 	return (m_shaderTypeBits & (1u << shader->getType())) != 0;
     97 }
     98 
     99 bool VariableSearchFilter::matchesFilter (const glu::VariableDeclaration& variable) const
    100 {
    101 	DE_ASSERT(variable.storage < glu::STORAGE_LAST);
    102 	return (m_storageBits & (1u << variable.storage)) != 0;
    103 }
    104 
    105 bool VariableSearchFilter::matchesFilter (const glu::InterfaceBlock& block) const
    106 {
    107 	DE_ASSERT(block.storage < glu::STORAGE_LAST);
    108 	return (m_storageBits & (1u << block.storage)) != 0;
    109 }
    110 
    111 } // ProgramInterfaceDefinition
    112 
    113 static bool incrementMultiDimensionIndex (std::vector<int>& index, const std::vector<int>& dimensions)
    114 {
    115 	int incrementDimensionNdx = (int)(index.size() - 1);
    116 
    117 	while (incrementDimensionNdx >= 0)
    118 	{
    119 		if (++index[incrementDimensionNdx] == dimensions[incrementDimensionNdx])
    120 			index[incrementDimensionNdx--] = 0;
    121 		else
    122 			break;
    123 	}
    124 
    125 	return (incrementDimensionNdx != -1);
    126 }
    127 
    128 bool programContainsIOBlocks (const ProgramInterfaceDefinition::Program* program)
    129 {
    130 	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
    131 	{
    132 		if (shaderContainsIOBlocks(program->getShaders()[shaderNdx]))
    133 			return true;
    134 	}
    135 
    136 	return false;
    137 }
    138 
    139 bool shaderContainsIOBlocks (const ProgramInterfaceDefinition::Shader* shader)
    140 {
    141 	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
    142 	{
    143 		const glu::Storage storage = shader->getDefaultBlock().interfaceBlocks[ndx].storage;
    144 		if (storage == glu::STORAGE_IN			||
    145 			storage == glu::STORAGE_OUT			||
    146 			storage == glu::STORAGE_PATCH_IN	||
    147 			storage == glu::STORAGE_PATCH_OUT)
    148 		{
    149 			return true;
    150 		}
    151 	}
    152 	return false;
    153 }
    154 
    155 glu::ShaderType getProgramTransformFeedbackStage (const ProgramInterfaceDefinition::Program* program)
    156 {
    157 	if (program->hasStage(glu::SHADERTYPE_GEOMETRY))
    158 		return glu::SHADERTYPE_GEOMETRY;
    159 
    160 	if (program->hasStage(glu::SHADERTYPE_TESSELLATION_EVALUATION))
    161 		return glu::SHADERTYPE_TESSELLATION_EVALUATION;
    162 
    163 	if (program->hasStage(glu::SHADERTYPE_VERTEX))
    164 		return glu::SHADERTYPE_VERTEX;
    165 
    166 	DE_ASSERT(false);
    167 	return glu::SHADERTYPE_LAST;
    168 }
    169 
    170 void generateVariableTypeResourceNames (std::vector<std::string>& resources, const std::string& name, const glu::VarType& type, deUint32 resourceNameGenerationFlags)
    171 {
    172 	DE_ASSERT((resourceNameGenerationFlags & (~RESOURCE_NAME_GENERATION_FLAG_MASK)) == 0);
    173 
    174 	// remove top-level flag from children
    175 	const deUint32 childFlags = resourceNameGenerationFlags & ~((deUint32)RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE);
    176 
    177 	if (type.isBasicType())
    178 		resources.push_back(name);
    179 	else if (type.isStructType())
    180 	{
    181 		const glu::StructType* structType = type.getStructPtr();
    182 		for (int ndx = 0; ndx < structType->getNumMembers(); ++ndx)
    183 			generateVariableTypeResourceNames(resources, name + "." + structType->getMember(ndx).getName(), structType->getMember(ndx).getType(), childFlags);
    184 	}
    185 	else if (type.isArrayType())
    186 	{
    187 		// Bottom-level arrays of basic types of a transform feedback variable will produce only the first
    188 		// element but without the trailing "[0]"
    189 		if (type.getElementType().isBasicType() &&
    190 			(resourceNameGenerationFlags & RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE) != 0)
    191 		{
    192 			resources.push_back(name);
    193 		}
    194 		// Bottom-level arrays of basic types and SSBO top-level arrays of any type procude only first element
    195 		else if (type.getElementType().isBasicType() ||
    196 				 (resourceNameGenerationFlags & RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE) != 0)
    197 		{
    198 			generateVariableTypeResourceNames(resources, name + "[0]", type.getElementType(), childFlags);
    199 		}
    200 		// Other arrays of aggregate types are expanded
    201 		else
    202 		{
    203 			for (int ndx = 0; ndx < type.getArraySize(); ++ndx)
    204 				generateVariableTypeResourceNames(resources, name + "[" + de::toString(ndx) + "]", type.getElementType(), childFlags);
    205 		}
    206 	}
    207 	else
    208 		DE_ASSERT(false);
    209 }
    210 
    211 // Program source generation
    212 
    213 namespace
    214 {
    215 
    216 using ProgramInterfaceDefinition::VariablePathComponent;
    217 using ProgramInterfaceDefinition::VariableSearchFilter;
    218 
    219 static std::string getShaderExtensionDeclarations (const ProgramInterfaceDefinition::Shader* shader)
    220 {
    221 	std::vector<std::string>	extensions;
    222 	std::ostringstream			buf;
    223 
    224 	if (shader->getType() == glu::SHADERTYPE_GEOMETRY)
    225 	{
    226 		extensions.push_back("GL_EXT_geometry_shader");
    227 	}
    228 	else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_CONTROL ||
    229 			 shader->getType() == glu::SHADERTYPE_TESSELLATION_EVALUATION)
    230 	{
    231 		extensions.push_back("GL_EXT_tessellation_shader");
    232 	}
    233 
    234 	if (shaderContainsIOBlocks(shader))
    235 		extensions.push_back("GL_EXT_shader_io_blocks");
    236 
    237 	for (int ndx = 0; ndx < (int)extensions.size(); ++ndx)
    238 		buf << "#extension " << extensions[ndx] << " : require\n";
    239 	return buf.str();
    240 }
    241 
    242 static std::string getShaderTypeDeclarations (const ProgramInterfaceDefinition::Program* program, glu::ShaderType type)
    243 {
    244 	switch (type)
    245 	{
    246 		case glu::SHADERTYPE_VERTEX:
    247 			return "";
    248 
    249 		case glu::SHADERTYPE_FRAGMENT:
    250 			return "";
    251 
    252 		case glu::SHADERTYPE_GEOMETRY:
    253 		{
    254 			std::ostringstream buf;
    255 			buf <<	"layout(points) in;\n"
    256 					"layout(points, max_vertices=" << program->getGeometryNumOutputVertices() << ") out;\n";
    257 			return buf.str();
    258 		}
    259 
    260 		case glu::SHADERTYPE_TESSELLATION_CONTROL:
    261 		{
    262 			std::ostringstream buf;
    263 			buf << "layout(vertices=" << program->getTessellationNumOutputPatchVertices() << ") out;\n";
    264 			return buf.str();
    265 		}
    266 
    267 		case glu::SHADERTYPE_TESSELLATION_EVALUATION:
    268 			return "layout(triangles, point_mode) in;\n";
    269 
    270 		case glu::SHADERTYPE_COMPUTE:
    271 			return "layout(local_size_x=1) in;\n";
    272 
    273 		default:
    274 			DE_ASSERT(false);
    275 			return "";
    276 	}
    277 }
    278 
    279 class StructNameEqualPredicate
    280 {
    281 public:
    282 				StructNameEqualPredicate	(const char* name) : m_name(name) { }
    283 	bool		operator()					(const glu::StructType* type) { return type->hasTypeName() && (deStringEqual(m_name, type->getTypeName()) == DE_TRUE); }
    284 private:
    285 	const char*	m_name;
    286 };
    287 
    288 static void collectNamedStructureDefinitions (std::vector<const glu::StructType*>& dst, const glu::VarType& type)
    289 {
    290 	if (type.isBasicType())
    291 		return;
    292 	else if (type.isArrayType())
    293 		return collectNamedStructureDefinitions(dst, type.getElementType());
    294 	else if (type.isStructType())
    295 	{
    296 		if (type.getStructPtr()->hasTypeName())
    297 		{
    298 			// must be unique (may share the the same struct)
    299 			std::vector<const glu::StructType*>::iterator where = std::find_if(dst.begin(), dst.end(), StructNameEqualPredicate(type.getStructPtr()->getTypeName()));
    300 			if (where != dst.end())
    301 			{
    302 				DE_ASSERT(**where == *type.getStructPtr());
    303 
    304 				// identical type has been added already, types of members must be added too
    305 				return;
    306 			}
    307 		}
    308 
    309 		// Add types of members first
    310 		for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
    311 			collectNamedStructureDefinitions(dst, type.getStructPtr()->getMember(ndx).getType());
    312 
    313 		dst.push_back(type.getStructPtr());
    314 	}
    315 	else
    316 		DE_ASSERT(false);
    317 }
    318 
    319 static void writeStructureDefinitions (std::ostringstream& buf, const ProgramInterfaceDefinition::DefaultBlock& defaultBlock)
    320 {
    321 	std::vector<const glu::StructType*> namedStructs;
    322 
    323 	// Collect all structs in post order
    324 
    325 	for (int ndx = 0; ndx < (int)defaultBlock.variables.size(); ++ndx)
    326 		collectNamedStructureDefinitions(namedStructs, defaultBlock.variables[ndx].varType);
    327 
    328 	for (int blockNdx = 0; blockNdx < (int)defaultBlock.interfaceBlocks.size(); ++blockNdx)
    329 		for (int ndx = 0; ndx < (int)defaultBlock.interfaceBlocks[blockNdx].variables.size(); ++ndx)
    330 			collectNamedStructureDefinitions(namedStructs, defaultBlock.interfaceBlocks[blockNdx].variables[ndx].varType);
    331 
    332 	// Write
    333 
    334 	for (int structNdx = 0; structNdx < (int)namedStructs.size(); ++structNdx)
    335 	{
    336 		buf <<	"struct " << namedStructs[structNdx]->getTypeName() << "\n"
    337 				"{\n";
    338 
    339 		for (int memberNdx = 0; memberNdx < namedStructs[structNdx]->getNumMembers(); ++memberNdx)
    340 			buf << glu::indent(1) << glu::declare(namedStructs[structNdx]->getMember(memberNdx).getType(), namedStructs[structNdx]->getMember(memberNdx).getName(), 1) << ";\n";
    341 
    342 		buf <<	"};\n";
    343 	}
    344 
    345 	if (!namedStructs.empty())
    346 		buf << "\n";
    347 }
    348 
    349 static void writeInterfaceBlock (std::ostringstream& buf, const glu::InterfaceBlock& interfaceBlock)
    350 {
    351 	buf << interfaceBlock.layout;
    352 
    353 	if (interfaceBlock.layout != glu::Layout())
    354 		buf << " ";
    355 
    356 	buf	<< glu::getStorageName(interfaceBlock.storage) << " " << interfaceBlock.interfaceName << "\n"
    357 		<< "{\n";
    358 
    359 	for (int ndx = 0; ndx < (int)interfaceBlock.variables.size(); ++ndx)
    360 		buf << glu::indent(1) << interfaceBlock.variables[ndx] << ";\n";
    361 
    362 	buf << "}";
    363 
    364 	if (!interfaceBlock.instanceName.empty())
    365 		buf << " " << interfaceBlock.instanceName;
    366 
    367 	for (int dimensionNdx = 0; dimensionNdx < (int)interfaceBlock.dimensions.size(); ++dimensionNdx)
    368 		buf << "[" << interfaceBlock.dimensions[dimensionNdx] << "]";
    369 
    370 	buf << ";\n\n";
    371 }
    372 
    373 static bool isReadableInterface (const glu::InterfaceBlock& interface)
    374 {
    375 	return	interface.storage == glu::STORAGE_UNIFORM	||
    376 			interface.storage == glu::STORAGE_IN		||
    377 			interface.storage == glu::STORAGE_PATCH_IN	||
    378 			(interface.storage == glu::STORAGE_BUFFER && (interface.memoryAccessQualifierFlags & glu::MEMORYACCESSQUALIFIER_WRITEONLY_BIT) == 0);
    379 }
    380 
    381 static bool isWritableInterface (const glu::InterfaceBlock& interface)
    382 {
    383 	return	interface.storage == glu::STORAGE_OUT		||
    384 			interface.storage == glu::STORAGE_PATCH_OUT	||
    385 			(interface.storage == glu::STORAGE_BUFFER && (interface.memoryAccessQualifierFlags & glu::MEMORYACCESSQUALIFIER_READONLY_BIT) == 0);
    386 }
    387 
    388 
    389 static void writeVariableReadAccumulateExpression (std::ostringstream&							buf,
    390 												   const std::string&							accumulatorName,
    391 												   const std::string&							name,
    392 												   glu::ShaderType								shaderType,
    393 												   glu::Storage									storage,
    394 												   const ProgramInterfaceDefinition::Program*	program,
    395 												   const glu::VarType&							varType)
    396 {
    397 	if (varType.isBasicType())
    398 	{
    399 		buf << "\t" << accumulatorName << " += ";
    400 
    401 		if (glu::isDataTypeScalar(varType.getBasicType()))
    402 			buf << "vec4(float(" << name << "))";
    403 		else if (glu::isDataTypeVector(varType.getBasicType()))
    404 			buf << "vec4(" << name << ".xyxy)";
    405 		else if (glu::isDataTypeMatrix(varType.getBasicType()))
    406 			buf << "vec4(float(" << name << "[0][0]))";
    407 		else if (glu::isDataTypeSamplerMultisample(varType.getBasicType()))
    408 			buf << "vec4(float(textureSize(" << name << ").x))";
    409 		else if (glu::isDataTypeSampler(varType.getBasicType()))
    410 			buf << "vec4(float(textureSize(" << name << ", 0).x))";
    411 		else if (glu::isDataTypeImage(varType.getBasicType()))
    412 			buf << "vec4(float(imageSize(" << name << ").x))";
    413 		else if (varType.getBasicType() == glu::TYPE_UINT_ATOMIC_COUNTER)
    414 			buf << "vec4(float(atomicCounterIncrement(" << name << ")))";
    415 		else
    416 			DE_ASSERT(false);
    417 
    418 		buf << ";\n";
    419 	}
    420 	else if (varType.isStructType())
    421 	{
    422 		for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
    423 			writeVariableReadAccumulateExpression(buf,
    424 												  accumulatorName,
    425 												  name + "." + varType.getStructPtr()->getMember(ndx).getName(),
    426 												  shaderType,
    427 												  storage,
    428 												  program,
    429 												  varType.getStructPtr()->getMember(ndx).getType());
    430 	}
    431 	else if (varType.isArrayType())
    432 	{
    433 		if (varType.getArraySize() != glu::VarType::UNSIZED_ARRAY)
    434 		{
    435 			for (int ndx = 0; ndx < varType.getArraySize(); ++ndx)
    436 				writeVariableReadAccumulateExpression(buf,
    437 													  accumulatorName,
    438 													  name + "[" + de::toString(ndx) + "]",
    439 													  shaderType,
    440 													  storage,
    441 													  program,
    442 													  varType.getElementType());
    443 		}
    444 		else if (storage == glu::STORAGE_BUFFER)
    445 		{
    446 			// run-time sized array, read arbitrary
    447 			writeVariableReadAccumulateExpression(buf,
    448 												  accumulatorName,
    449 												  name + "[8]",
    450 												  shaderType,
    451 												  storage,
    452 												  program,
    453 												  varType.getElementType());
    454 		}
    455 		else
    456 		{
    457 			DE_ASSERT(storage == glu::STORAGE_IN);
    458 
    459 			if (shaderType == glu::SHADERTYPE_GEOMETRY)
    460 			{
    461 				// implicit sized geometry input array, size = primitive size. Just reading first is enough
    462 				writeVariableReadAccumulateExpression(buf,
    463 													  accumulatorName,
    464 													  name + "[0]",
    465 													  shaderType,
    466 													  storage,
    467 													  program,
    468 													  varType.getElementType());
    469 			}
    470 			else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
    471 			{
    472 				// implicit sized tessellation input array, size = input patch max size. Just reading current is enough
    473 				writeVariableReadAccumulateExpression(buf,
    474 													  accumulatorName,
    475 													  name + "[gl_InvocationID]",
    476 													  shaderType,
    477 													  storage,
    478 													  program,
    479 													  varType.getElementType());
    480 			}
    481 			else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
    482 			{
    483 				// implicit sized tessellation input array, size = output patch max size. Read all to prevent optimizations
    484 				DE_ASSERT(program->getTessellationNumOutputPatchVertices() > 0);
    485 				for (int ndx = 0; ndx < (int)program->getTessellationNumOutputPatchVertices(); ++ndx)
    486 				{
    487 					writeVariableReadAccumulateExpression(buf,
    488 														  accumulatorName,
    489 														  name + "[" + de::toString(ndx) + "]",
    490 														  shaderType,
    491 														  storage,
    492 														  program,
    493 														  varType.getElementType());
    494 				}
    495 			}
    496 			else
    497 				DE_ASSERT(false);
    498 		}
    499 	}
    500 	else
    501 		DE_ASSERT(false);
    502 }
    503 
    504 static void writeInterfaceReadAccumulateExpression (std::ostringstream&							buf,
    505 													const std::string&							accumulatorName,
    506 													const glu::InterfaceBlock&					block,
    507 													glu::ShaderType								shaderType,
    508 													const ProgramInterfaceDefinition::Program*	program)
    509 {
    510 	if (block.dimensions.empty())
    511 	{
    512 		const std::string prefix = (block.instanceName.empty()) ? ("") : (block.instanceName + ".");
    513 
    514 		for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
    515 		{
    516 			writeVariableReadAccumulateExpression(buf,
    517 												  accumulatorName,
    518 												  prefix + block.variables[ndx].name,
    519 												  shaderType,
    520 												  block.storage,
    521 												  program,
    522 												  block.variables[ndx].varType);
    523 		}
    524 	}
    525 	else
    526 	{
    527 		std::vector<int> index(block.dimensions.size(), 0);
    528 
    529 		for (;;)
    530 		{
    531 			// access element
    532 			{
    533 				std::ostringstream name;
    534 				name << block.instanceName;
    535 
    536 				for (int dimensionNdx = 0; dimensionNdx < (int)block.dimensions.size(); ++dimensionNdx)
    537 					name << "[" << index[dimensionNdx] << "]";
    538 
    539 				for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
    540 				{
    541 					writeVariableReadAccumulateExpression(buf,
    542 														  accumulatorName,
    543 														  name.str() + "." + block.variables[ndx].name,
    544 														  shaderType,
    545 														  block.storage,
    546 														  program,
    547 														  block.variables[ndx].varType);
    548 				}
    549 			}
    550 
    551 			// increment index
    552 			if (!incrementMultiDimensionIndex(index, block.dimensions))
    553 				break;
    554 		}
    555 	}
    556 }
    557 
    558 static void writeVariableWriteExpression (std::ostringstream&							buf,
    559 										  const std::string&							sourceVec4Name,
    560 										  const std::string&							name,
    561 										  glu::ShaderType								shaderType,
    562 										  glu::Storage									storage,
    563 										  const ProgramInterfaceDefinition::Program*	program,
    564 										  const glu::VarType&							varType)
    565 {
    566 	if (varType.isBasicType())
    567 	{
    568 		buf << "\t" << name << " = ";
    569 
    570 		if (glu::isDataTypeScalar(varType.getBasicType()))
    571 			buf << glu::getDataTypeName(varType.getBasicType()) << "(" << sourceVec4Name << ".y)";
    572 		else if (glu::isDataTypeVector(varType.getBasicType()) || glu::isDataTypeMatrix(varType.getBasicType()))
    573 			buf << glu::getDataTypeName(varType.getBasicType()) << "(" << glu::getDataTypeName(glu::getDataTypeScalarType(varType.getBasicType())) << "(" << sourceVec4Name << ".y))";
    574 		else
    575 			DE_ASSERT(false);
    576 
    577 		buf << ";\n";
    578 	}
    579 	else if (varType.isStructType())
    580 	{
    581 		for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
    582 			writeVariableWriteExpression(buf,
    583 										 sourceVec4Name,
    584 										 name + "." + varType.getStructPtr()->getMember(ndx).getName(),
    585 										 shaderType,
    586 										 storage,
    587 										 program,
    588 										 varType.getStructPtr()->getMember(ndx).getType());
    589 	}
    590 	else if (varType.isArrayType())
    591 	{
    592 		if (varType.getArraySize() != glu::VarType::UNSIZED_ARRAY)
    593 		{
    594 			for (int ndx = 0; ndx < varType.getArraySize(); ++ndx)
    595 				writeVariableWriteExpression(buf,
    596 											 sourceVec4Name,
    597 											 name + "[" + de::toString(ndx) + "]",
    598 											 shaderType,
    599 											 storage,
    600 											 program,
    601 											 varType.getElementType());
    602 		}
    603 		else if (storage == glu::STORAGE_BUFFER)
    604 		{
    605 			// run-time sized array, write arbitrary
    606 			writeVariableWriteExpression(buf,
    607 										 sourceVec4Name,
    608 										 name + "[9]",
    609 										 shaderType,
    610 										 storage,
    611 										 program,
    612 										 varType.getElementType());
    613 		}
    614 		else
    615 		{
    616 			DE_ASSERT(storage == glu::STORAGE_OUT);
    617 
    618 			if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
    619 			{
    620 				// implicit sized tessellation onput array, size = output patch max size. Can only write to gl_InvocationID
    621 				writeVariableWriteExpression(buf,
    622 											 sourceVec4Name,
    623 											 name + "[gl_InvocationID]",
    624 											 shaderType,
    625 											 storage,
    626 											 program,
    627 											 varType.getElementType());
    628 			}
    629 			else
    630 				DE_ASSERT(false);
    631 		}
    632 	}
    633 	else
    634 		DE_ASSERT(false);
    635 }
    636 
    637 static void writeInterfaceWriteExpression (std::ostringstream&							buf,
    638 										   const std::string&							sourceVec4Name,
    639 										   const glu::InterfaceBlock&					block,
    640 										   glu::ShaderType								shaderType,
    641 										   const ProgramInterfaceDefinition::Program*	program)
    642 {
    643 	if (block.dimensions.empty())
    644 	{
    645 		const std::string prefix = (block.instanceName.empty()) ? ("") : (block.instanceName + ".");
    646 
    647 		for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
    648 		{
    649 			writeVariableWriteExpression(buf,
    650 										 sourceVec4Name,
    651 										 prefix + block.variables[ndx].name,
    652 										 shaderType,
    653 										 block.storage,
    654 										 program,
    655 										 block.variables[ndx].varType);
    656 		}
    657 	}
    658 	else
    659 	{
    660 		std::vector<int> index(block.dimensions.size(), 0);
    661 
    662 		for (;;)
    663 		{
    664 			// access element
    665 			{
    666 				std::ostringstream name;
    667 				name << block.instanceName;
    668 
    669 				for (int dimensionNdx = 0; dimensionNdx < (int)block.dimensions.size(); ++dimensionNdx)
    670 					name << "[" << index[dimensionNdx] << "]";
    671 
    672 				for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
    673 				{
    674 					writeVariableWriteExpression(buf,
    675 												 sourceVec4Name,
    676 												 name.str() + "." + block.variables[ndx].name,
    677 												 shaderType,
    678 												 block.storage,
    679 												 program,
    680 												 block.variables[ndx].varType);
    681 				}
    682 			}
    683 
    684 			// increment index
    685 			if (!incrementMultiDimensionIndex(index, block.dimensions))
    686 				break;
    687 		}
    688 	}
    689 }
    690 
    691 static bool traverseVariablePath (std::vector<VariablePathComponent>& typePath, const char* subPath, const glu::VarType& type)
    692 {
    693 	glu::VarTokenizer tokenizer(subPath);
    694 
    695 	typePath.push_back(VariablePathComponent(&type));
    696 
    697 	if (tokenizer.getToken() == glu::VarTokenizer::TOKEN_END)
    698 		return true;
    699 
    700 	if (type.isStructType() && tokenizer.getToken() == glu::VarTokenizer::TOKEN_PERIOD)
    701 	{
    702 		tokenizer.advance();
    703 
    704 		// malformed path
    705 		if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_IDENTIFIER)
    706 			return false;
    707 
    708 		for (int memberNdx = 0; memberNdx < type.getStructPtr()->getNumMembers(); ++memberNdx)
    709 			if (type.getStructPtr()->getMember(memberNdx).getName() == tokenizer.getIdentifier())
    710 				return traverseVariablePath(typePath, subPath + tokenizer.getCurrentTokenEndLocation(), type.getStructPtr()->getMember(memberNdx).getType());
    711 
    712 		// malformed path, no such member
    713 		return false;
    714 	}
    715 	else if (type.isArrayType() && tokenizer.getToken() == glu::VarTokenizer::TOKEN_LEFT_BRACKET)
    716 	{
    717 		tokenizer.advance();
    718 
    719 		// malformed path
    720 		if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_NUMBER)
    721 			return false;
    722 
    723 		tokenizer.advance();
    724 		if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_RIGHT_BRACKET)
    725 			return false;
    726 
    727 		return traverseVariablePath(typePath, subPath + tokenizer.getCurrentTokenEndLocation(), type.getElementType());
    728 	}
    729 
    730 	return false;
    731 }
    732 
    733 static bool traverseVariablePath (std::vector<VariablePathComponent>& typePath, const std::string& path, const glu::VariableDeclaration& var)
    734 {
    735 	if (glu::parseVariableName(path.c_str()) != var.name)
    736 		return false;
    737 
    738 	typePath.push_back(VariablePathComponent(&var));
    739 	return traverseVariablePath(typePath, path.c_str() + var.name.length(), var.varType);
    740 }
    741 
    742 static bool traverseShaderVariablePath (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Shader* shader, const std::string& path, const VariableSearchFilter& filter)
    743 {
    744 	// Default block variable?
    745 	for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx)
    746 		if (filter.matchesFilter(shader->getDefaultBlock().variables[varNdx]))
    747 			if (traverseVariablePath(typePath, path, shader->getDefaultBlock().variables[varNdx]))
    748 				return true;
    749 
    750 	// is variable an interface block variable?
    751 	{
    752 		const std::string blockName = glu::parseVariableName(path.c_str());
    753 
    754 		for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
    755 		{
    756 			if (!filter.matchesFilter(shader->getDefaultBlock().interfaceBlocks[interfaceNdx]))
    757 				continue;
    758 
    759 			if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].interfaceName == blockName)
    760 			{
    761 				// resource is a member of a named interface block
    762 				// \note there is no array index specifier even if the interface is declared as an array of instances
    763 				const std::string blockMemberPath = path.substr(blockName.size() + 1);
    764 				const std::string blockMemeberName = glu::parseVariableName(blockMemberPath.c_str());
    765 
    766 				for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables.size(); ++varNdx)
    767 				{
    768 					if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx].name == blockMemeberName)
    769 					{
    770 						typePath.push_back(VariablePathComponent(&shader->getDefaultBlock().interfaceBlocks[interfaceNdx]));
    771 						return traverseVariablePath(typePath, blockMemberPath, shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx]);
    772 					}
    773 				}
    774 
    775 				// terminate search
    776 				return false;
    777 			}
    778 			else if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].instanceName.empty())
    779 			{
    780 				const std::string blockMemeberName = glu::parseVariableName(path.c_str());
    781 
    782 				// unnamed block contains such variable?
    783 				for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables.size(); ++varNdx)
    784 				{
    785 					if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx].name == blockMemeberName)
    786 					{
    787 						typePath.push_back(VariablePathComponent(&shader->getDefaultBlock().interfaceBlocks[interfaceNdx]));
    788 						return traverseVariablePath(typePath, path, shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx]);
    789 					}
    790 				}
    791 
    792 				// continue search
    793 			}
    794 		}
    795 	}
    796 
    797 	return false;
    798 }
    799 
    800 static bool traverseProgramVariablePath (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Program* program, const std::string& path, const VariableSearchFilter& filter)
    801 {
    802 	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
    803 	{
    804 		const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];
    805 
    806 		if (filter.matchesFilter(shader))
    807 		{
    808 			// \note modifying output variable even when returning false
    809 			typePath.clear();
    810 			if (traverseShaderVariablePath(typePath, shader, path, filter))
    811 				return true;
    812 		}
    813 	}
    814 
    815 	return false;
    816 }
    817 
    818 static bool containsSubType (const glu::VarType& complexType, glu::DataType basicType)
    819 {
    820 	if (complexType.isBasicType())
    821 	{
    822 		return complexType.getBasicType() == basicType;
    823 	}
    824 	else if (complexType.isArrayType())
    825 	{
    826 		return containsSubType(complexType.getElementType(), basicType);
    827 	}
    828 	else if (complexType.isStructType())
    829 	{
    830 		for (int ndx = 0; ndx < complexType.getStructPtr()->getNumMembers(); ++ndx)
    831 			if (containsSubType(complexType.getStructPtr()->getMember(ndx).getType(), basicType))
    832 				return true;
    833 		return false;
    834 	}
    835 	else
    836 	{
    837 		DE_ASSERT(false);
    838 		return false;
    839 	}
    840 }
    841 
    842 static int getNumShaderBlocks (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
    843 {
    844 	int retVal = 0;
    845 
    846 	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
    847 	{
    848 		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
    849 		{
    850 			int numInstances = 1;
    851 
    852 			for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx)
    853 				numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx];
    854 
    855 			retVal += numInstances;
    856 		}
    857 	}
    858 
    859 	return retVal;
    860 }
    861 
    862 static int getNumAtomicCounterBuffers (const ProgramInterfaceDefinition::Shader* shader)
    863 {
    864 	std::set<int> buffers;
    865 
    866 	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
    867 	{
    868 		if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER))
    869 		{
    870 			DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1);
    871 			buffers.insert(shader->getDefaultBlock().variables[ndx].layout.binding);
    872 		}
    873 	}
    874 
    875 	return (int)buffers.size();
    876 }
    877 
    878 template <typename DataTypeMap>
    879 static int accumulateComplexType (const glu::VarType& complexType, const DataTypeMap& dTypeMap)
    880 {
    881 	if (complexType.isBasicType())
    882 		return dTypeMap(complexType.getBasicType());
    883 	else if (complexType.isArrayType())
    884 	{
    885 		const int arraySize = (complexType.getArraySize() == glu::VarType::UNSIZED_ARRAY) ? (1) : (complexType.getArraySize());
    886 		return arraySize * accumulateComplexType(complexType.getElementType(), dTypeMap);
    887 	}
    888 	else if (complexType.isStructType())
    889 	{
    890 		int sum = 0;
    891 		for (int ndx = 0; ndx < complexType.getStructPtr()->getNumMembers(); ++ndx)
    892 			sum += accumulateComplexType(complexType.getStructPtr()->getMember(ndx).getType(), dTypeMap);
    893 		return sum;
    894 	}
    895 	else
    896 	{
    897 		DE_ASSERT(false);
    898 		return false;
    899 	}
    900 }
    901 
    902 template <typename InterfaceBlockFilter, typename VarDeclFilter, typename DataTypeMap>
    903 static int accumulateShader (const ProgramInterfaceDefinition::Shader* shader,
    904 							 const InterfaceBlockFilter& ibFilter,
    905 							 const VarDeclFilter& vdFilter,
    906 							 const DataTypeMap& dMap)
    907 {
    908 	int retVal = 0;
    909 
    910 	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
    911 	{
    912 		if (ibFilter(shader->getDefaultBlock().interfaceBlocks[ndx]))
    913 		{
    914 			int numInstances = 1;
    915 
    916 			for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx)
    917 				numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx];
    918 
    919 			for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].variables.size(); ++varNdx)
    920 				retVal += numInstances * accumulateComplexType(shader->getDefaultBlock().interfaceBlocks[ndx].variables[varNdx].varType, dMap);
    921 		}
    922 	}
    923 
    924 	for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx)
    925 		if (vdFilter(shader->getDefaultBlock().variables[varNdx]))
    926 			retVal += accumulateComplexType(shader->getDefaultBlock().variables[varNdx].varType, dMap);
    927 
    928 	return retVal;
    929 }
    930 
    931 static bool dummyTrueConstantTypeFilter (glu::DataType d)
    932 {
    933 	DE_UNREF(d);
    934 	return true;
    935 }
    936 
    937 class InstanceCounter
    938 {
    939 public:
    940 	InstanceCounter (bool (*predicate)(glu::DataType))
    941 		: m_predicate(predicate)
    942 	{
    943 	}
    944 
    945 	int operator() (glu::DataType t) const
    946 	{
    947 		return (m_predicate(t)) ? (1) : (0);
    948 	}
    949 
    950 private:
    951 	bool (*const m_predicate)(glu::DataType);
    952 };
    953 
    954 class InterfaceBlockStorageFilter
    955 {
    956 public:
    957 	InterfaceBlockStorageFilter (glu::Storage storage)
    958 		: m_storage(storage)
    959 	{
    960 	}
    961 
    962 	bool operator() (const glu::InterfaceBlock& b) const
    963 	{
    964 		return m_storage == b.storage;
    965 	}
    966 
    967 private:
    968 	const glu::Storage m_storage;
    969 };
    970 
    971 class VariableDeclarationStorageFilter
    972 {
    973 public:
    974 	VariableDeclarationStorageFilter (glu::Storage storage)
    975 		: m_storage(storage)
    976 	{
    977 	}
    978 
    979 	bool operator() (const glu::VariableDeclaration& d) const
    980 	{
    981 		return m_storage == d.storage;
    982 	}
    983 
    984 private:
    985 	const glu::Storage m_storage;
    986 };
    987 
    988 static int getNumTypeInstances (const glu::VarType& complexType, bool (*predicate)(glu::DataType))
    989 {
    990 	return accumulateComplexType(complexType, InstanceCounter(predicate));
    991 }
    992 
    993 static int getNumTypeInstances (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage, bool (*predicate)(glu::DataType))
    994 {
    995 	return accumulateShader(shader, InterfaceBlockStorageFilter(storage), VariableDeclarationStorageFilter(storage), InstanceCounter(predicate));
    996 }
    997 
    998 static int getNumTypeInstances (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
    999 {
   1000 	return getNumTypeInstances(shader, storage, dummyTrueConstantTypeFilter);
   1001 }
   1002 
   1003 static int accumulateShaderStorage (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage, int (*typeMap)(glu::DataType))
   1004 {
   1005 	return accumulateShader(shader, InterfaceBlockStorageFilter(storage), VariableDeclarationStorageFilter(storage), typeMap);
   1006 }
   1007 
   1008 static int getNumDataTypeComponents (glu::DataType type)
   1009 {
   1010 	if (glu::isDataTypeScalarOrVector(type) || glu::isDataTypeMatrix(type))
   1011 		return glu::getDataTypeScalarSize(type);
   1012 	else
   1013 		return 0;
   1014 }
   1015 
   1016 static int getNumDataTypeVectors (glu::DataType type)
   1017 {
   1018 	if (glu::isDataTypeScalar(type))
   1019 		return 1;
   1020 	else if (glu::isDataTypeVector(type))
   1021 		return 1;
   1022 	else if (glu::isDataTypeMatrix(type))
   1023 		return glu::getDataTypeMatrixNumColumns(type);
   1024 	else
   1025 		return 0;
   1026 }
   1027 
   1028 static int getNumComponents (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
   1029 {
   1030 	return accumulateShaderStorage(shader, storage, getNumDataTypeComponents);
   1031 }
   1032 
   1033 static int getNumVectors (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
   1034 {
   1035 	return accumulateShaderStorage(shader, storage, getNumDataTypeVectors);
   1036 }
   1037 
   1038 static int getNumDefaultBlockComponents (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
   1039 {
   1040 	int retVal = 0;
   1041 
   1042 	for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx)
   1043 		if (shader->getDefaultBlock().variables[varNdx].storage == storage)
   1044 			retVal += accumulateComplexType(shader->getDefaultBlock().variables[varNdx].varType, getNumDataTypeComponents);
   1045 
   1046 	return retVal;
   1047 }
   1048 
   1049 static int getMaxBufferBinding (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
   1050 {
   1051 	int maxBinding = -1;
   1052 
   1053 	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
   1054 	{
   1055 		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
   1056 		{
   1057 			const int	binding			= (shader->getDefaultBlock().interfaceBlocks[ndx].layout.binding == -1) ? (0) : (shader->getDefaultBlock().interfaceBlocks[ndx].layout.binding);
   1058 			int			numInstances	= 1;
   1059 
   1060 			for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx)
   1061 				numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx];
   1062 
   1063 			maxBinding = de::max(maxBinding, binding + numInstances - 1);
   1064 		}
   1065 	}
   1066 
   1067 	return (int)maxBinding;
   1068 }
   1069 
   1070 static int getBufferTypeSize (glu::DataType type, glu::MatrixOrder order)
   1071 {
   1072 	// assume vec4 alignments, should produce values greater than or equal to the actual resource usage
   1073 	int numVectors = 0;
   1074 
   1075 	if (glu::isDataTypeScalarOrVector(type))
   1076 		numVectors = 1;
   1077 	else if (glu::isDataTypeMatrix(type) && order == glu::MATRIXORDER_ROW_MAJOR)
   1078 		numVectors = glu::getDataTypeMatrixNumRows(type);
   1079 	else if (glu::isDataTypeMatrix(type) && order != glu::MATRIXORDER_ROW_MAJOR)
   1080 		numVectors = glu::getDataTypeMatrixNumColumns(type);
   1081 	else
   1082 		DE_ASSERT(false);
   1083 
   1084 	return 4 * numVectors;
   1085 }
   1086 
   1087 static int getBufferVariableSize (const glu::VarType& type, glu::MatrixOrder order)
   1088 {
   1089 	if (type.isBasicType())
   1090 		return getBufferTypeSize(type.getBasicType(), order);
   1091 	else if (type.isArrayType())
   1092 	{
   1093 		const int arraySize = (type.getArraySize() == glu::VarType::UNSIZED_ARRAY) ? (1) : (type.getArraySize());
   1094 		return arraySize * getBufferVariableSize(type.getElementType(), order);
   1095 	}
   1096 	else if (type.isStructType())
   1097 	{
   1098 		int sum = 0;
   1099 		for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
   1100 			sum += getBufferVariableSize(type.getStructPtr()->getMember(ndx).getType(), order);
   1101 		return sum;
   1102 	}
   1103 	else
   1104 	{
   1105 		DE_ASSERT(false);
   1106 		return false;
   1107 	}
   1108 }
   1109 
   1110 static int getBufferSize (const glu::InterfaceBlock& block, glu::MatrixOrder blockOrder)
   1111 {
   1112 	int size = 0;
   1113 
   1114 	for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
   1115 		size += getBufferVariableSize(block.variables[ndx].varType, (block.variables[ndx].layout.matrixOrder == glu::MATRIXORDER_LAST) ? (blockOrder) : (block.variables[ndx].layout.matrixOrder));
   1116 
   1117 	return size;
   1118 }
   1119 
   1120 static int getBufferMaxSize (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
   1121 {
   1122 	int maxSize = 0;
   1123 
   1124 	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
   1125 		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
   1126 			maxSize = de::max(maxSize, getBufferSize(shader->getDefaultBlock().interfaceBlocks[ndx], shader->getDefaultBlock().interfaceBlocks[ndx].layout.matrixOrder));
   1127 
   1128 	return (int)maxSize;
   1129 }
   1130 
   1131 static int getAtomicCounterMaxBinding (const ProgramInterfaceDefinition::Shader* shader)
   1132 {
   1133 	int maxBinding = -1;
   1134 
   1135 	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
   1136 	{
   1137 		if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER))
   1138 		{
   1139 			DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1);
   1140 			maxBinding = de::max(maxBinding, shader->getDefaultBlock().variables[ndx].layout.binding);
   1141 		}
   1142 	}
   1143 
   1144 	return (int)maxBinding;
   1145 }
   1146 
   1147 static int getUniformMaxBinding (const ProgramInterfaceDefinition::Shader* shader, bool (*predicate)(glu::DataType))
   1148 {
   1149 	int maxBinding = -1;
   1150 
   1151 	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
   1152 	{
   1153 		const int binding		= (shader->getDefaultBlock().variables[ndx].layout.binding == -1) ? (0) : (shader->getDefaultBlock().variables[ndx].layout.binding);
   1154 		const int numInstances	= getNumTypeInstances(shader->getDefaultBlock().variables[ndx].varType, predicate);
   1155 
   1156 		maxBinding = de::max(maxBinding, binding + numInstances - 1);
   1157 	}
   1158 
   1159 	return maxBinding;
   1160 }
   1161 
   1162 static int getAtomicCounterMaxBufferSize (const ProgramInterfaceDefinition::Shader* shader)
   1163 {
   1164 	std::map<int, int>	bufferSizes;
   1165 	int					maxSize			= 0;
   1166 
   1167 	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
   1168 	{
   1169 		if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER))
   1170 		{
   1171 			const int bufferBinding	= shader->getDefaultBlock().variables[ndx].layout.binding;
   1172 			const int offset		= (shader->getDefaultBlock().variables[ndx].layout.offset == -1) ? (0) : (shader->getDefaultBlock().variables[ndx].layout.offset);
   1173 			const int size			= offset + 4 * getNumTypeInstances(shader->getDefaultBlock().variables[ndx].varType, glu::isDataTypeAtomicCounter);
   1174 
   1175 			DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1);
   1176 
   1177 			if (bufferSizes.find(bufferBinding) == bufferSizes.end())
   1178 				bufferSizes[bufferBinding] = size;
   1179 			else
   1180 				bufferSizes[bufferBinding] = de::max<int>(bufferSizes[bufferBinding], size);
   1181 		}
   1182 	}
   1183 
   1184 	for (std::map<int, int>::iterator it = bufferSizes.begin(); it != bufferSizes.end(); ++it)
   1185 		maxSize = de::max<int>(maxSize, it->second);
   1186 
   1187 	return maxSize;
   1188 }
   1189 
   1190 static int getNumFeedbackVaryingComponents (const ProgramInterfaceDefinition::Program* program, const std::string& name)
   1191 {
   1192 	std::vector<VariablePathComponent> path;
   1193 
   1194 	if (name == "gl_Position")
   1195 		return 4;
   1196 
   1197 	DE_ASSERT(deStringBeginsWith(name.c_str(), "gl_") == DE_FALSE);
   1198 
   1199 	if (!traverseProgramVariablePath(path, program, name, VariableSearchFilter::createShaderTypeStorageFilter(getProgramTransformFeedbackStage(program), glu::STORAGE_OUT)))
   1200 		DE_ASSERT(false); // Program failed validate, invalid operation
   1201 
   1202 	return accumulateComplexType(*path.back().getVariableType(), getNumDataTypeComponents);
   1203 }
   1204 
   1205 static int getNumXFBComponents (const ProgramInterfaceDefinition::Program* program)
   1206 {
   1207 	int numComponents = 0;
   1208 
   1209 	for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx)
   1210 		numComponents += getNumFeedbackVaryingComponents(program, program->getTransformFeedbackVaryings()[ndx]);
   1211 
   1212 	return numComponents;
   1213 }
   1214 
   1215 static int getNumMaxXFBOutputComponents (const ProgramInterfaceDefinition::Program* program)
   1216 {
   1217 	int numComponents = 0;
   1218 
   1219 	for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx)
   1220 		numComponents = de::max(numComponents, getNumFeedbackVaryingComponents(program, program->getTransformFeedbackVaryings()[ndx]));
   1221 
   1222 	return numComponents;
   1223 }
   1224 
   1225 static int getFragmentOutputMaxLocation (const ProgramInterfaceDefinition::Shader* shader)
   1226 {
   1227 	DE_ASSERT(shader->getType() == glu::SHADERTYPE_FRAGMENT);
   1228 
   1229 	int maxOutputLocation = -1;
   1230 
   1231 	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
   1232 	{
   1233 		if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_OUT)
   1234 		{
   1235 			// missing location qualifier means location == 0
   1236 			const int outputLocation 		= (shader->getDefaultBlock().variables[ndx].layout.location == -1)
   1237 												? (0)
   1238 												: (shader->getDefaultBlock().variables[ndx].layout.location);
   1239 
   1240 			// only basic types or arrays of basic types possible
   1241 			DE_ASSERT(!shader->getDefaultBlock().variables[ndx].varType.isStructType());
   1242 
   1243 			const int locationSlotsTaken	= (shader->getDefaultBlock().variables[ndx].varType.isArrayType())
   1244 												? (shader->getDefaultBlock().variables[ndx].varType.getArraySize())
   1245 												: (1);
   1246 
   1247 			maxOutputLocation = de::max(maxOutputLocation, outputLocation + locationSlotsTaken - 1);
   1248 		}
   1249 	}
   1250 
   1251 	return maxOutputLocation;
   1252 }
   1253 
   1254 } // anonymous
   1255 
   1256 std::vector<std::string> getProgramInterfaceBlockMemberResourceList (const glu::InterfaceBlock& interfaceBlock)
   1257 {
   1258 	const std::string			namePrefix					= (!interfaceBlock.instanceName.empty()) ? (interfaceBlock.interfaceName + ".") : ("");
   1259 	const bool					isTopLevelBufferVariable	= (interfaceBlock.storage == glu::STORAGE_BUFFER);
   1260 	std::vector<std::string>	resources;
   1261 
   1262 	// \note this is defined in the GLSL spec, not in the GL spec
   1263 	for (int variableNdx = 0; variableNdx < (int)interfaceBlock.variables.size(); ++variableNdx)
   1264 		generateVariableTypeResourceNames(resources,
   1265 										  namePrefix + interfaceBlock.variables[variableNdx].name,
   1266 										  interfaceBlock.variables[variableNdx].varType,
   1267 										  (isTopLevelBufferVariable) ?
   1268 											(RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE) :
   1269 											(RESOURCE_NAME_GENERATION_FLAG_DEFAULT));
   1270 
   1271 	return resources;
   1272 }
   1273 
   1274 std::vector<std::string> getProgramInterfaceResourceList (const ProgramInterfaceDefinition::Program* program, ProgramInterface interface)
   1275 {
   1276 	// The same {uniform (block), buffer (variable)} can exist in multiple shaders, remove duplicates but keep order
   1277 	const bool					removeDuplicated	= (interface == PROGRAMINTERFACE_UNIFORM)			||
   1278 													  (interface == PROGRAMINTERFACE_UNIFORM_BLOCK)		||
   1279 													  (interface == PROGRAMINTERFACE_BUFFER_VARIABLE)	||
   1280 													  (interface == PROGRAMINTERFACE_SHADER_STORAGE_BLOCK);
   1281 	std::vector<std::string>	resources;
   1282 
   1283 	switch (interface)
   1284 	{
   1285 		case PROGRAMINTERFACE_UNIFORM:
   1286 		case PROGRAMINTERFACE_BUFFER_VARIABLE:
   1287 		{
   1288 			const glu::Storage storage = (interface == PROGRAMINTERFACE_UNIFORM) ? (glu::STORAGE_UNIFORM) : (glu::STORAGE_BUFFER);
   1289 
   1290 			for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
   1291 			{
   1292 				const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];
   1293 
   1294 				for (int variableNdx = 0; variableNdx < (int)shader->getDefaultBlock().variables.size(); ++variableNdx)
   1295 					if (shader->getDefaultBlock().variables[variableNdx].storage == storage)
   1296 						generateVariableTypeResourceNames(resources,
   1297 														  shader->getDefaultBlock().variables[variableNdx].name,
   1298 														  shader->getDefaultBlock().variables[variableNdx].varType,
   1299 														  RESOURCE_NAME_GENERATION_FLAG_DEFAULT);
   1300 
   1301 				for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
   1302 				{
   1303 					const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
   1304 					if (interfaceBlock.storage == storage)
   1305 					{
   1306 						const std::vector<std::string> blockResources = getProgramInterfaceBlockMemberResourceList(interfaceBlock);
   1307 						resources.insert(resources.end(), blockResources.begin(), blockResources.end());
   1308 					}
   1309 				}
   1310 			}
   1311 			break;
   1312 		}
   1313 
   1314 		case PROGRAMINTERFACE_UNIFORM_BLOCK:
   1315 		case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK:
   1316 		{
   1317 			const glu::Storage storage = (interface == PROGRAMINTERFACE_UNIFORM_BLOCK) ? (glu::STORAGE_UNIFORM) : (glu::STORAGE_BUFFER);
   1318 
   1319 			for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
   1320 			{
   1321 				const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];
   1322 				for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
   1323 				{
   1324 					const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
   1325 					if (interfaceBlock.storage == storage)
   1326 					{
   1327 						std::vector<int> index(interfaceBlock.dimensions.size(), 0);
   1328 
   1329 						for (;;)
   1330 						{
   1331 							// add resource string for each element
   1332 							{
   1333 								std::ostringstream name;
   1334 								name << interfaceBlock.interfaceName;
   1335 
   1336 								for (int dimensionNdx = 0; dimensionNdx < (int)interfaceBlock.dimensions.size(); ++dimensionNdx)
   1337 									name << "[" << index[dimensionNdx] << "]";
   1338 
   1339 								resources.push_back(name.str());
   1340 							}
   1341 
   1342 							// increment index
   1343 							if (!incrementMultiDimensionIndex(index, interfaceBlock.dimensions))
   1344 								break;
   1345 						}
   1346 					}
   1347 				}
   1348 			}
   1349 			break;
   1350 		}
   1351 
   1352 		case PROGRAMINTERFACE_PROGRAM_INPUT:
   1353 		case PROGRAMINTERFACE_PROGRAM_OUTPUT:
   1354 		{
   1355 			const glu::Storage		queryStorage		= (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (glu::STORAGE_IN) : (glu::STORAGE_OUT);
   1356 			const glu::Storage		queryPatchStorage	= (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (glu::STORAGE_PATCH_IN) : (glu::STORAGE_PATCH_OUT);
   1357 			const glu::ShaderType	shaderType			= (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (program->getFirstStage()) : (program->getLastStage());
   1358 
   1359 			for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
   1360 			{
   1361 				const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];
   1362 
   1363 				if (shader->getType() != shaderType)
   1364 					continue;
   1365 
   1366 				for (int variableNdx = 0; variableNdx < (int)shader->getDefaultBlock().variables.size(); ++variableNdx)
   1367 				{
   1368 					const glu::Storage variableStorage = shader->getDefaultBlock().variables[variableNdx].storage;
   1369 					if (variableStorage == queryStorage || variableStorage == queryPatchStorage)
   1370 						generateVariableTypeResourceNames(resources,
   1371 														  shader->getDefaultBlock().variables[variableNdx].name,
   1372 														  shader->getDefaultBlock().variables[variableNdx].varType,
   1373 														  RESOURCE_NAME_GENERATION_FLAG_DEFAULT);
   1374 				}
   1375 
   1376 				for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
   1377 				{
   1378 					const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
   1379 					if (interfaceBlock.storage == queryStorage || interfaceBlock.storage == queryPatchStorage)
   1380 					{
   1381 						const std::vector<std::string> blockResources = getProgramInterfaceBlockMemberResourceList(interfaceBlock);
   1382 						resources.insert(resources.end(), blockResources.begin(), blockResources.end());
   1383 					}
   1384 				}
   1385 			}
   1386 
   1387 			// built-ins
   1388 			if (interface == PROGRAMINTERFACE_PROGRAM_INPUT)
   1389 			{
   1390 				if (shaderType == glu::SHADERTYPE_VERTEX && resources.empty())
   1391 					resources.push_back("gl_VertexID"); // only read from when there are no other inputs
   1392 				else if (shaderType == glu::SHADERTYPE_FRAGMENT && resources.empty())
   1393 					resources.push_back("gl_FragCoord"); // only read from when there are no other inputs
   1394 				else if (shaderType == glu::SHADERTYPE_GEOMETRY)
   1395 					resources.push_back("gl_PerVertex.gl_Position");
   1396 				else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
   1397 				{
   1398 					resources.push_back("gl_InvocationID");
   1399 					resources.push_back("gl_PerVertex.gl_Position");
   1400 				}
   1401 				else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
   1402 					resources.push_back("gl_PerVertex.gl_Position");
   1403 				else if (shaderType == glu::SHADERTYPE_COMPUTE && resources.empty())
   1404 					resources.push_back("gl_NumWorkGroups"); // only read from when there are no other inputs
   1405 			}
   1406 			else if (interface == PROGRAMINTERFACE_PROGRAM_OUTPUT)
   1407 			{
   1408 				if (shaderType == glu::SHADERTYPE_VERTEX)
   1409 					resources.push_back("gl_Position");
   1410 				else if (shaderType == glu::SHADERTYPE_FRAGMENT && resources.empty())
   1411 					resources.push_back("gl_FragDepth"); // only written to when there are no other outputs
   1412 				else if (shaderType == glu::SHADERTYPE_GEOMETRY)
   1413 					resources.push_back("gl_Position");
   1414 				else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
   1415 				{
   1416 					resources.push_back("gl_PerVertex.gl_Position");
   1417 					resources.push_back("gl_TessLevelOuter[0]");
   1418 					resources.push_back("gl_TessLevelInner[0]");
   1419 				}
   1420 				else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
   1421 					resources.push_back("gl_Position");
   1422 			}
   1423 
   1424 			break;
   1425 		}
   1426 
   1427 		case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING:
   1428 		{
   1429 			const glu::ShaderType xfbStage = getProgramTransformFeedbackStage(program);
   1430 
   1431 			for (int varyingNdx = 0; varyingNdx < (int)program->getTransformFeedbackVaryings().size(); ++varyingNdx)
   1432 			{
   1433 				const std::string& varyingName = program->getTransformFeedbackVaryings()[varyingNdx];
   1434 
   1435 				if (deStringBeginsWith(varyingName.c_str(), "gl_"))
   1436 					resources.push_back(varyingName); // builtin
   1437 				else
   1438 				{
   1439 					std::vector<VariablePathComponent> path;
   1440 
   1441 					if (!traverseProgramVariablePath(path, program, varyingName, VariableSearchFilter::createShaderTypeStorageFilter(xfbStage, glu::STORAGE_OUT)))
   1442 						DE_ASSERT(false); // Program failed validate, invalid operation
   1443 
   1444 					generateVariableTypeResourceNames(resources,
   1445 													  varyingName,
   1446 													  *path.back().getVariableType(),
   1447 													  RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE);
   1448 				}
   1449 			}
   1450 
   1451 			break;
   1452 		}
   1453 
   1454 		default:
   1455 			DE_ASSERT(false);
   1456 	}
   1457 
   1458 	if (removeDuplicated)
   1459 	{
   1460 		std::set<std::string>		addedVariables;
   1461 		std::vector<std::string>	uniqueResouces;
   1462 
   1463 		for (int ndx = 0; ndx < (int)resources.size(); ++ndx)
   1464 		{
   1465 			if (addedVariables.find(resources[ndx]) == addedVariables.end())
   1466 			{
   1467 				addedVariables.insert(resources[ndx]);
   1468 				uniqueResouces.push_back(resources[ndx]);
   1469 			}
   1470 		}
   1471 
   1472 		uniqueResouces.swap(resources);
   1473 	}
   1474 
   1475 	return resources;
   1476 }
   1477 
   1478 glu::ProgramSources generateProgramInterfaceProgramSources (const ProgramInterfaceDefinition::Program* program)
   1479 {
   1480 	glu::ProgramSources sources;
   1481 
   1482 	DE_ASSERT(program->isValid());
   1483 
   1484 	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
   1485 	{
   1486 		const ProgramInterfaceDefinition::Shader*	shader						= program->getShaders()[shaderNdx];
   1487 		bool										containsUserDefinedOutputs	= false;
   1488 		bool										containsUserDefinedInputs	= false;
   1489 		std::ostringstream							sourceBuf;
   1490 		std::ostringstream							usageBuf;
   1491 
   1492 		sourceBuf	<< glu::getGLSLVersionDeclaration(shader->getVersion()) << "\n"
   1493 					<< getShaderExtensionDeclarations(shader)
   1494 					<< getShaderTypeDeclarations(program, shader->getType())
   1495 					<< "\n";
   1496 
   1497 		// Struct definitions
   1498 
   1499 		writeStructureDefinitions(sourceBuf, shader->getDefaultBlock());
   1500 
   1501 		// variables in the default scope
   1502 
   1503 		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
   1504 			sourceBuf << shader->getDefaultBlock().variables[ndx] << ";\n";
   1505 
   1506 		if (!shader->getDefaultBlock().variables.empty())
   1507 			sourceBuf << "\n";
   1508 
   1509 		// Interface blocks
   1510 
   1511 		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
   1512 			writeInterfaceBlock(sourceBuf, shader->getDefaultBlock().interfaceBlocks[ndx]);
   1513 
   1514 		// Use inputs and outputs so that they won't be removed by the optimizer
   1515 
   1516 		usageBuf <<	"highp vec4 readInputs()\n"
   1517 					"{\n"
   1518 					"	highp vec4 retValue = vec4(0.0);\n";
   1519 
   1520 		// User-defined inputs
   1521 
   1522 		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
   1523 		{
   1524 			if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_IN			||
   1525 				shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_PATCH_IN	||
   1526 				shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_UNIFORM)
   1527 			{
   1528 				writeVariableReadAccumulateExpression(usageBuf,
   1529 													  "retValue",
   1530 													  shader->getDefaultBlock().variables[ndx].name,
   1531 													  shader->getType(),
   1532 													  shader->getDefaultBlock().variables[ndx].storage,
   1533 													  program,
   1534 													  shader->getDefaultBlock().variables[ndx].varType);
   1535 				containsUserDefinedInputs = true;
   1536 			}
   1537 		}
   1538 
   1539 		for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
   1540 		{
   1541 			const glu::InterfaceBlock& interface = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
   1542 			if (isReadableInterface(interface))
   1543 			{
   1544 				writeInterfaceReadAccumulateExpression(usageBuf,
   1545 													   "retValue",
   1546 													   interface,
   1547 													   shader->getType(),
   1548 													   program);
   1549 				containsUserDefinedInputs = true;
   1550 			}
   1551 		}
   1552 
   1553 		// Built-in-inputs
   1554 
   1555 		switch (shader->getType())
   1556 		{
   1557 			case glu::SHADERTYPE_VERTEX:
   1558 				// make readInputs to never be compile time constant
   1559 				if (!containsUserDefinedInputs)
   1560 					usageBuf << "	retValue += vec4(float(gl_VertexID));\n";
   1561 				break;
   1562 
   1563 			case glu::SHADERTYPE_FRAGMENT:
   1564 				// make readInputs to never be compile time constant
   1565 				if (!containsUserDefinedInputs)
   1566 					usageBuf << "	retValue += gl_FragCoord;\n";
   1567 				break;
   1568 			case glu::SHADERTYPE_GEOMETRY:
   1569 				// always use previous stage's output values so that previous stage won't be optimized out
   1570 				usageBuf << "	retValue += gl_in[0].gl_Position;\n";
   1571 				break;
   1572 			case glu::SHADERTYPE_TESSELLATION_CONTROL:
   1573 				// always use previous stage's output values so that previous stage won't be optimized out
   1574 				usageBuf << "	retValue += gl_in[0].gl_Position;\n";
   1575 				break;
   1576 			case glu::SHADERTYPE_TESSELLATION_EVALUATION:
   1577 				// always use previous stage's output values so that previous stage won't be optimized out
   1578 				usageBuf << "	retValue += gl_in[0].gl_Position;\n";
   1579 				break;
   1580 
   1581 			case glu::SHADERTYPE_COMPUTE:
   1582 				// make readInputs to never be compile time constant
   1583 				if (!containsUserDefinedInputs)
   1584 					usageBuf << "	retValue += vec4(float(gl_NumWorkGroups.x));\n";
   1585 				break;
   1586 			default:
   1587 				DE_ASSERT(false);
   1588 		}
   1589 
   1590 		usageBuf <<	"	return retValue;\n"
   1591 					"}\n\n";
   1592 
   1593 		usageBuf <<	"void writeOutputs(in highp vec4 dummyValue)\n"
   1594 					"{\n";
   1595 
   1596 		// User-defined outputs
   1597 
   1598 		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
   1599 		{
   1600 			if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_OUT ||
   1601 				shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_PATCH_OUT)
   1602 			{
   1603 				writeVariableWriteExpression(usageBuf,
   1604 											 "dummyValue",
   1605 											 shader->getDefaultBlock().variables[ndx].name,
   1606 											 shader->getType(),
   1607 											 shader->getDefaultBlock().variables[ndx].storage,
   1608 											 program,
   1609 											 shader->getDefaultBlock().variables[ndx].varType);
   1610 				containsUserDefinedOutputs = true;
   1611 			}
   1612 		}
   1613 
   1614 		for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
   1615 		{
   1616 			const glu::InterfaceBlock& interface = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
   1617 			if (isWritableInterface(interface))
   1618 			{
   1619 				writeInterfaceWriteExpression(usageBuf, "dummyValue", interface, shader->getType(), program);
   1620 				containsUserDefinedOutputs = true;
   1621 			}
   1622 		}
   1623 
   1624 		// Builtin-outputs that must be written to
   1625 
   1626 		if (shader->getType() == glu::SHADERTYPE_VERTEX)
   1627 			usageBuf << "	gl_Position = dummyValue;\n";
   1628 		else if (shader->getType() == glu::SHADERTYPE_GEOMETRY)
   1629 			usageBuf << "	gl_Position = dummyValue;\n"
   1630 						 "	EmitVertex();\n";
   1631 		else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_CONTROL)
   1632 			usageBuf << "	gl_out[gl_InvocationID].gl_Position = dummyValue;\n"
   1633 						"	gl_TessLevelOuter[0] = 2.8;\n"
   1634 						"	gl_TessLevelOuter[1] = 2.8;\n"
   1635 						"	gl_TessLevelOuter[2] = 2.8;\n"
   1636 						"	gl_TessLevelOuter[3] = 2.8;\n"
   1637 						"	gl_TessLevelInner[0] = 2.8;\n"
   1638 						"	gl_TessLevelInner[1] = 2.8;\n";
   1639 		else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_EVALUATION)
   1640 			usageBuf << "	gl_Position = dummyValue;\n";
   1641 
   1642 		// Output to sink input data to
   1643 
   1644 		if (!containsUserDefinedOutputs)
   1645 		{
   1646 			if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
   1647 				usageBuf << "	gl_FragDepth = dot(dummyValue.xy, dummyValue.xw);\n";
   1648 			else if (shader->getType() == glu::SHADERTYPE_COMPUTE)
   1649 				usageBuf << "	dummyOutputBlock.dummyValue = dummyValue;\n";
   1650 		}
   1651 
   1652 		usageBuf <<	"}\n\n"
   1653 					"void main()\n"
   1654 					"{\n"
   1655 					"	writeOutputs(readInputs());\n"
   1656 					"}\n";
   1657 
   1658 		// Interface for dummy output
   1659 
   1660 		if (shader->getType() == glu::SHADERTYPE_COMPUTE && !containsUserDefinedOutputs)
   1661 		{
   1662 			sourceBuf	<< "writeonly buffer DummyOutputInterface\n"
   1663 						<< "{\n"
   1664 						<< "	highp vec4 dummyValue;\n"
   1665 						<< "} dummyOutputBlock;\n\n";
   1666 		}
   1667 
   1668 		sources << glu::ShaderSource(shader->getType(), sourceBuf.str() + usageBuf.str());
   1669 	}
   1670 
   1671 	if (program->isSeparable())
   1672 		sources << glu::ProgramSeparable(true);
   1673 
   1674 	for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx)
   1675 		sources << glu::TransformFeedbackVarying(program->getTransformFeedbackVaryings()[ndx]);
   1676 
   1677 	if (program->getTransformFeedbackMode())
   1678 		sources << glu::TransformFeedbackMode(program->getTransformFeedbackMode());
   1679 
   1680 	return sources;
   1681 }
   1682 
   1683 bool findProgramVariablePathByPathName (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Program* program, const std::string& pathName, const VariableSearchFilter& filter)
   1684 {
   1685 	std::vector<VariablePathComponent> modifiedPath;
   1686 
   1687 	if (!traverseProgramVariablePath(modifiedPath, program, pathName, filter))
   1688 		return false;
   1689 
   1690 	// modify param only on success
   1691 	typePath.swap(modifiedPath);
   1692 	return true;
   1693 }
   1694 
   1695 ProgramInterfaceDefinition::ShaderResourceUsage getShaderResourceUsage (const ProgramInterfaceDefinition::Program* program, const ProgramInterfaceDefinition::Shader* shader)
   1696 {
   1697 	ProgramInterfaceDefinition::ShaderResourceUsage retVal;
   1698 
   1699 	retVal.numInputs						= getNumTypeInstances(shader, glu::STORAGE_IN);
   1700 	retVal.numInputVectors					= getNumVectors(shader, glu::STORAGE_IN);
   1701 	retVal.numInputComponents				= getNumComponents(shader, glu::STORAGE_IN);
   1702 
   1703 	retVal.numOutputs						= getNumTypeInstances(shader, glu::STORAGE_OUT);
   1704 	retVal.numOutputVectors					= getNumVectors(shader, glu::STORAGE_OUT);
   1705 	retVal.numOutputComponents				= getNumComponents(shader, glu::STORAGE_OUT);
   1706 
   1707 	retVal.numPatchInputComponents			= getNumComponents(shader, glu::STORAGE_PATCH_IN);
   1708 	retVal.numPatchOutputComponents			= getNumComponents(shader, glu::STORAGE_PATCH_OUT);
   1709 
   1710 	retVal.numDefaultBlockUniformComponents	= getNumDefaultBlockComponents(shader, glu::STORAGE_UNIFORM);
   1711 	retVal.numCombinedUniformComponents		= getNumComponents(shader, glu::STORAGE_UNIFORM);
   1712 	retVal.numUniformVectors				= getNumVectors(shader, glu::STORAGE_UNIFORM);
   1713 
   1714 	retVal.numSamplers						= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeSampler);
   1715 	retVal.numImages						= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage);
   1716 
   1717 	retVal.numAtomicCounterBuffers			= getNumAtomicCounterBuffers(shader);
   1718 	retVal.numAtomicCounters				= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeAtomicCounter);
   1719 
   1720 	retVal.numUniformBlocks					= getNumShaderBlocks(shader, glu::STORAGE_UNIFORM);
   1721 	retVal.numShaderStorageBlocks			= getNumShaderBlocks(shader, glu::STORAGE_BUFFER);
   1722 
   1723 	// add builtins
   1724 	switch (shader->getType())
   1725 	{
   1726 		case glu::SHADERTYPE_VERTEX:
   1727 			// gl_Position is not counted
   1728 			break;
   1729 
   1730 		case glu::SHADERTYPE_FRAGMENT:
   1731 			// nada
   1732 			break;
   1733 
   1734 		case glu::SHADERTYPE_GEOMETRY:
   1735 			// gl_Position in (point mode => size 1)
   1736 			retVal.numInputs			+= 1;
   1737 			retVal.numInputVectors		+= 1;
   1738 			retVal.numInputComponents	+= 4;
   1739 
   1740 			// gl_Position out
   1741 			retVal.numOutputs			+= 1;
   1742 			retVal.numOutputVectors		+= 1;
   1743 			retVal.numOutputComponents	+= 4;
   1744 			break;
   1745 
   1746 		case glu::SHADERTYPE_TESSELLATION_CONTROL:
   1747 			// gl_Position in is read up to gl_InstanceID
   1748 			retVal.numInputs			+= 1 * program->getTessellationNumOutputPatchVertices();
   1749 			retVal.numInputVectors		+= 1 * program->getTessellationNumOutputPatchVertices();
   1750 			retVal.numInputComponents	+= 4 * program->getTessellationNumOutputPatchVertices();
   1751 
   1752 			// gl_Position out, size = num patch out vertices
   1753 			retVal.numOutputs			+= 1 * program->getTessellationNumOutputPatchVertices();
   1754 			retVal.numOutputVectors		+= 1 * program->getTessellationNumOutputPatchVertices();
   1755 			retVal.numOutputComponents	+= 4 * program->getTessellationNumOutputPatchVertices();
   1756 			break;
   1757 
   1758 		case glu::SHADERTYPE_TESSELLATION_EVALUATION:
   1759 			// gl_Position in is read up to gl_InstanceID
   1760 			retVal.numInputs			+= 1 * program->getTessellationNumOutputPatchVertices();
   1761 			retVal.numInputVectors		+= 1 * program->getTessellationNumOutputPatchVertices();
   1762 			retVal.numInputComponents	+= 4 * program->getTessellationNumOutputPatchVertices();
   1763 
   1764 			// gl_Position out
   1765 			retVal.numOutputs			+= 1;
   1766 			retVal.numOutputVectors		+= 1;
   1767 			retVal.numOutputComponents	+= 4;
   1768 			break;
   1769 
   1770 		case glu::SHADERTYPE_COMPUTE:
   1771 			// nada
   1772 			break;
   1773 
   1774 		default:
   1775 			DE_ASSERT(false);
   1776 			break;
   1777 	}
   1778 	return retVal;
   1779 }
   1780 
   1781 ProgramInterfaceDefinition::ProgramResourceUsage getCombinedProgramResourceUsage (const ProgramInterfaceDefinition::Program* program)
   1782 {
   1783 	ProgramInterfaceDefinition::ProgramResourceUsage	retVal;
   1784 	int													numVertexOutputComponents	= 0;
   1785 	int													numFragmentInputComponents	= 0;
   1786 	int													numVertexOutputVectors		= 0;
   1787 	int													numFragmentInputVectors		= 0;
   1788 
   1789 	retVal.uniformBufferMaxBinding					= -1; // max binding is inclusive upper bound. Allow 0 bindings by using negative value
   1790 	retVal.uniformBufferMaxSize						= 0;
   1791 	retVal.numUniformBlocks							= 0;
   1792 	retVal.numCombinedVertexUniformComponents		= 0;
   1793 	retVal.numCombinedFragmentUniformComponents		= 0;
   1794 	retVal.numCombinedGeometryUniformComponents		= 0;
   1795 	retVal.numCombinedTessControlUniformComponents	= 0;
   1796 	retVal.numCombinedTessEvalUniformComponents		= 0;
   1797 	retVal.shaderStorageBufferMaxBinding			= -1; // see above
   1798 	retVal.shaderStorageBufferMaxSize				= 0;
   1799 	retVal.numShaderStorageBlocks					= 0;
   1800 	retVal.numVaryingComponents						= 0;
   1801 	retVal.numVaryingVectors						= 0;
   1802 	retVal.numCombinedSamplers						= 0;
   1803 	retVal.atomicCounterBufferMaxBinding			= -1; // see above
   1804 	retVal.atomicCounterBufferMaxSize				= 0;
   1805 	retVal.numAtomicCounterBuffers					= 0;
   1806 	retVal.numAtomicCounters						= 0;
   1807 	retVal.maxImageBinding							= -1; // see above
   1808 	retVal.numCombinedImages						= 0;
   1809 	retVal.numCombinedOutputResources				= 0;
   1810 	retVal.numXFBInterleavedComponents				= 0;
   1811 	retVal.numXFBSeparateAttribs					= 0;
   1812 	retVal.numXFBSeparateComponents					= 0;
   1813 	retVal.fragmentOutputMaxBinding					= -1; // see above
   1814 
   1815 	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
   1816 	{
   1817 		const ProgramInterfaceDefinition::Shader* const shader = program->getShaders()[shaderNdx];
   1818 
   1819 		retVal.uniformBufferMaxBinding		= de::max(retVal.uniformBufferMaxBinding, getMaxBufferBinding(shader, glu::STORAGE_UNIFORM));
   1820 		retVal.uniformBufferMaxSize			= de::max(retVal.uniformBufferMaxSize, getBufferMaxSize(shader, glu::STORAGE_UNIFORM));
   1821 		retVal.numUniformBlocks				+= getNumShaderBlocks(shader, glu::STORAGE_UNIFORM);
   1822 
   1823 		switch (shader->getType())
   1824 		{
   1825 			case glu::SHADERTYPE_VERTEX:					retVal.numCombinedVertexUniformComponents		+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
   1826 			case glu::SHADERTYPE_FRAGMENT:					retVal.numCombinedFragmentUniformComponents		+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
   1827 			case glu::SHADERTYPE_GEOMETRY:					retVal.numCombinedGeometryUniformComponents		+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
   1828 			case glu::SHADERTYPE_TESSELLATION_CONTROL:		retVal.numCombinedTessControlUniformComponents	+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
   1829 			case glu::SHADERTYPE_TESSELLATION_EVALUATION:	retVal.numCombinedTessEvalUniformComponents		+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
   1830 			default: break;
   1831 		}
   1832 
   1833 		retVal.shaderStorageBufferMaxBinding	= de::max(retVal.shaderStorageBufferMaxBinding, getMaxBufferBinding(shader, glu::STORAGE_BUFFER));
   1834 		retVal.shaderStorageBufferMaxSize		= de::max(retVal.shaderStorageBufferMaxSize, getBufferMaxSize(shader, glu::STORAGE_BUFFER));
   1835 		retVal.numShaderStorageBlocks			+= getNumShaderBlocks(shader, glu::STORAGE_BUFFER);
   1836 
   1837 		if (shader->getType() == glu::SHADERTYPE_VERTEX)
   1838 		{
   1839 			numVertexOutputComponents	+= getNumComponents(shader, glu::STORAGE_OUT);
   1840 			numVertexOutputVectors		+= getNumVectors(shader, glu::STORAGE_OUT);
   1841 		}
   1842 		else if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
   1843 		{
   1844 			numFragmentInputComponents	+= getNumComponents(shader, glu::STORAGE_IN);
   1845 			numFragmentInputVectors		+= getNumVectors(shader, glu::STORAGE_IN);
   1846 		}
   1847 
   1848 		retVal.numCombinedSamplers	+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeSampler);
   1849 
   1850 		retVal.atomicCounterBufferMaxBinding	= de::max(retVal.atomicCounterBufferMaxBinding, getAtomicCounterMaxBinding(shader));
   1851 		retVal.atomicCounterBufferMaxSize		= de::max(retVal.atomicCounterBufferMaxSize, getAtomicCounterMaxBufferSize(shader));
   1852 		retVal.numAtomicCounterBuffers			+= getNumAtomicCounterBuffers(shader);
   1853 		retVal.numAtomicCounters				+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeAtomicCounter);
   1854 		retVal.maxImageBinding					= de::max(retVal.maxImageBinding, getUniformMaxBinding(shader, glu::isDataTypeImage));
   1855 		retVal.numCombinedImages				+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage);
   1856 
   1857 		retVal.numCombinedOutputResources		+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage);
   1858 		retVal.numCombinedOutputResources		+= getNumShaderBlocks(shader, glu::STORAGE_BUFFER);
   1859 
   1860 		if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
   1861 		{
   1862 			retVal.numCombinedOutputResources += getNumVectors(shader, glu::STORAGE_OUT);
   1863 			retVal.fragmentOutputMaxBinding = de::max(retVal.fragmentOutputMaxBinding, getFragmentOutputMaxLocation(shader));
   1864 		}
   1865 	}
   1866 
   1867 	if (program->getTransformFeedbackMode() == GL_INTERLEAVED_ATTRIBS)
   1868 		retVal.numXFBInterleavedComponents = getNumXFBComponents(program);
   1869 	else if (program->getTransformFeedbackMode() == GL_SEPARATE_ATTRIBS)
   1870 	{
   1871 		retVal.numXFBSeparateAttribs	= (int)program->getTransformFeedbackVaryings().size();
   1872 		retVal.numXFBSeparateComponents	= getNumMaxXFBOutputComponents(program);
   1873 	}
   1874 
   1875 	// legacy limits
   1876 	retVal.numVaryingComponents	= de::max(numVertexOutputComponents, numFragmentInputComponents);
   1877 	retVal.numVaryingVectors	= de::max(numVertexOutputVectors, numFragmentInputVectors);
   1878 
   1879 	return retVal;
   1880 }
   1881 
   1882 } // Functional
   1883 } // gles31
   1884 } // deqp
   1885