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 query tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fProgramInterfaceQueryTests.hpp"
     25 #include "es31fProgramInterfaceQueryTestCase.hpp"
     26 #include "es31fProgramInterfaceDefinition.hpp"
     27 #include "es31fProgramInterfaceDefinitionUtil.hpp"
     28 #include "tcuTestLog.hpp"
     29 #include "gluShaderProgram.hpp"
     30 #include "gluVarTypeUtil.hpp"
     31 #include "gluStrUtil.hpp"
     32 #include "glwFunctions.hpp"
     33 #include "glwEnums.hpp"
     34 #include "deRandom.hpp"
     35 #include "deString.h"
     36 #include "deStringUtil.hpp"
     37 #include "deSharedPtr.hpp"
     38 #include "deUniquePtr.hpp"
     39 #include "deSTLUtil.hpp"
     40 
     41 #include <set>
     42 #include <map>
     43 
     44 namespace deqp
     45 {
     46 namespace gles31
     47 {
     48 namespace Functional
     49 {
     50 namespace
     51 {
     52 
     53 static bool stringEndsWith (const std::string& str, const std::string& suffix)
     54 {
     55 	if (suffix.length() > str.length())
     56 		return false;
     57 	else
     58 		return str.substr(str.length() - suffix.length()) == suffix;
     59 }
     60 
     61 static int getTypeSize (glu::DataType type)
     62 {
     63 	if (type == glu::TYPE_FLOAT)
     64 		return 4;
     65 	else if (type == glu::TYPE_INT || type == glu::TYPE_UINT)
     66 		return 4;
     67 	else if (type == glu::TYPE_BOOL)
     68 		return 4; // uint
     69 
     70 	DE_ASSERT(false);
     71 	return 0;
     72 }
     73 
     74 static int getVarTypeSize (const glu::VarType& type)
     75 {
     76 	if (type.isBasicType())
     77 		return glu::getDataTypeScalarSize(type.getBasicType()) * getTypeSize(glu::getDataTypeScalarType(type.getBasicType()));
     78 	else if (type.isStructType())
     79 	{
     80 		int size = 0;
     81 		for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
     82 			size += getVarTypeSize(type.getStructPtr()->getMember(ndx).getType());
     83 		return size;
     84 	}
     85 	else if (type.isArrayType())
     86 	{
     87 		if (type.getArraySize() == glu::VarType::UNSIZED_ARRAY)
     88 			return getVarTypeSize(type.getElementType());
     89 		else
     90 			return type.getArraySize() * getVarTypeSize(type.getElementType());
     91 	}
     92 	else
     93 	{
     94 		DE_ASSERT(false);
     95 		return 0;
     96 	}
     97 }
     98 
     99 static std::string convertGLTypeNameToTestName (const char* glName)
    100 {
    101 	// vectors and matrices are fine as is
    102 	{
    103 		if (deStringBeginsWith(glName, "vec")  == DE_TRUE ||
    104 			deStringBeginsWith(glName, "ivec") == DE_TRUE ||
    105 			deStringBeginsWith(glName, "uvec") == DE_TRUE ||
    106 			deStringBeginsWith(glName, "bvec") == DE_TRUE ||
    107 			deStringBeginsWith(glName, "mat")  == DE_TRUE)
    108 			return std::string(glName);
    109 	}
    110 
    111 	// convert camel case to use underscore
    112 	{
    113 		std::ostringstream	buf;
    114 		std::istringstream	name					(glName);
    115 		bool				mergeNextToken			= false;
    116 		bool				previousTokenWasDigit	= false;
    117 
    118 		while (!name.eof())
    119 		{
    120 			std::ostringstream token;
    121 
    122 			while (name.peek() != EOF)
    123 			{
    124 				if ((de::isDigit((char)name.peek()) || de::isUpper((char)name.peek())) && token.tellp())
    125 					break;
    126 
    127 				token << de::toLower((char)name.get());
    128 			}
    129 
    130 			if (buf.str().empty() || mergeNextToken)
    131 				buf << token.str();
    132 			else
    133 				buf << '_' << token.str();
    134 
    135 			// Single char causes next char to be merged (don't split initialisms or acronyms) unless it is 'D' after a number (split to ..._2d_acronym_aa
    136 			mergeNextToken = false;
    137 			if (token.tellp() == (std::streamoff)1)
    138 			{
    139 				if (!previousTokenWasDigit || token.str()[0] != 'd')
    140 					mergeNextToken = true;
    141 
    142 				previousTokenWasDigit = de::isDigit(token.str()[0]);
    143 			}
    144 			else
    145 				previousTokenWasDigit = false;
    146 		}
    147 
    148 		return buf.str();
    149 	}
    150 }
    151 
    152 static glw::GLenum getProgramInterfaceGLEnum (ProgramInterface interface)
    153 {
    154 	static const glw::GLenum s_enums[] =
    155 	{
    156 		GL_UNIFORM,						// PROGRAMINTERFACE_UNIFORM
    157 		GL_UNIFORM_BLOCK,				// PROGRAMINTERFACE_UNIFORM_BLOCK
    158 		GL_ATOMIC_COUNTER_BUFFER,		// PROGRAMINTERFACE_ATOMIC_COUNTER_BUFFER
    159 		GL_PROGRAM_INPUT,				// PROGRAMINTERFACE_PROGRAM_INPUT
    160 		GL_PROGRAM_OUTPUT,				// PROGRAMINTERFACE_PROGRAM_OUTPUT
    161 		GL_TRANSFORM_FEEDBACK_VARYING,	// PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING
    162 		GL_BUFFER_VARIABLE,				// PROGRAMINTERFACE_BUFFER_VARIABLE
    163 		GL_SHADER_STORAGE_BLOCK,		// PROGRAMINTERFACE_SHADER_STORAGE_BLOCK
    164 	};
    165 
    166 	return de::getSizedArrayElement<PROGRAMINTERFACE_LAST>(s_enums, interface);
    167 
    168 }
    169 
    170 namespace ResourceDefinition
    171 {
    172 
    173 class Node
    174 {
    175 public:
    176 	enum NodeType
    177 	{
    178 		TYPE_PROGRAM = 0,
    179 		TYPE_SHADER,
    180 		TYPE_DEFAULT_BLOCK,
    181 		TYPE_VARIABLE,
    182 		TYPE_INTERFACE_BLOCK,
    183 		TYPE_ARRAY_ELEMENT,
    184 		TYPE_STRUCT_MEMBER,
    185 		TYPE_STORAGE_QUALIFIER,
    186 		TYPE_LAYOUT_QUALIFIER,
    187 		TYPE_SHADER_SET,
    188 		TYPE_INTERPOLATION_QUALIFIER,
    189 		TYPE_TRANSFORM_FEEDBACK_TARGET,
    190 
    191 		TYPE_LAST
    192 	};
    193 
    194 	typedef de::SharedPtr<const Node, de::DefaultDeleter<const Node>, false> SharedPtr;
    195 
    196 							Node				(NodeType type, const SharedPtr& enclosingNode) : m_type(type), m_enclosingNode(enclosingNode) { DE_ASSERT(type < TYPE_LAST); }
    197 	virtual					~Node				(void) { }
    198 
    199 	inline const Node*		getEnclosingNode	(void) const					{ return m_enclosingNode.get();	}
    200 	inline NodeType			getType				(void) const					{ return m_type;				}
    201 
    202 private:
    203 	const NodeType			m_type;
    204 	const SharedPtr			m_enclosingNode;
    205 };
    206 
    207 class Program : public Node
    208 {
    209 public:
    210 	Program (bool separable = false)
    211 		: Node			(TYPE_PROGRAM, SharedPtr())
    212 		, m_separable	(separable)
    213 	{
    214 	}
    215 
    216 	const bool m_separable;
    217 };
    218 
    219 class Shader : public Node
    220 {
    221 public:
    222 	Shader (const SharedPtr& enclosingNode, glu::ShaderType type, glu::GLSLVersion version)
    223 		: Node		(TYPE_SHADER, enclosingNode)
    224 		, m_type	(type)
    225 		, m_version	(version)
    226 	{
    227 		DE_ASSERT(enclosingNode->getType() == TYPE_PROGRAM);
    228 	}
    229 
    230 	const glu::ShaderType	m_type;
    231 	const glu::GLSLVersion	m_version;
    232 };
    233 
    234 class DefaultBlock : public Node
    235 {
    236 public:
    237 	DefaultBlock (const SharedPtr& enclosing)
    238 		: Node(TYPE_DEFAULT_BLOCK, enclosing)
    239 	{
    240 		// enclosed by the shader
    241 		DE_ASSERT(enclosing->getType() == TYPE_SHADER		||
    242 				  enclosing->getType() == TYPE_SHADER_SET);
    243 	}
    244 };
    245 
    246 class StorageQualifier : public Node
    247 {
    248 public:
    249 	StorageQualifier (const SharedPtr& enclosing, glu::Storage storage)
    250 		: Node		(TYPE_STORAGE_QUALIFIER, enclosing)
    251 		, m_storage	(storage)
    252 	{
    253 		// not a part of any block
    254 		DE_ASSERT(enclosing->getType() == TYPE_DEFAULT_BLOCK);
    255 	}
    256 
    257 	const glu::Storage	m_storage;
    258 };
    259 
    260 class Variable : public Node
    261 {
    262 public:
    263 	Variable (const SharedPtr& enclosing, glu::DataType dataType)
    264 		: Node			(TYPE_VARIABLE, enclosing)
    265 		, m_dataType	(dataType)
    266 	{
    267 		DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER		||
    268 				  enclosing->getType() == TYPE_LAYOUT_QUALIFIER			||
    269 				  enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER	||
    270 				  enclosing->getType() == TYPE_INTERFACE_BLOCK			||
    271 				  enclosing->getType() == TYPE_ARRAY_ELEMENT			||
    272 				  enclosing->getType() == TYPE_STRUCT_MEMBER			||
    273 				  enclosing->getType() == TYPE_TRANSFORM_FEEDBACK_TARGET);
    274 	}
    275 
    276 	const glu::DataType	m_dataType;
    277 };
    278 
    279 class InterfaceBlock : public Node
    280 {
    281 public:
    282 	InterfaceBlock (const SharedPtr& enclosing, bool named)
    283 		: Node		(TYPE_INTERFACE_BLOCK, enclosing)
    284 		, m_named	(named)
    285 	{
    286 		// Must be qualified
    287 		const Node* storageNode = enclosing.get();
    288 		while (storageNode->getType() == TYPE_ARRAY_ELEMENT || storageNode->getType() == TYPE_LAYOUT_QUALIFIER)
    289 			storageNode = storageNode->getEnclosingNode();
    290 
    291 		DE_ASSERT(storageNode->getType() == TYPE_STORAGE_QUALIFIER);
    292 		DE_UNREF(storageNode);
    293 	}
    294 
    295 	const bool	m_named;
    296 };
    297 
    298 class ArrayElement : public Node
    299 {
    300 public:
    301 	ArrayElement (const SharedPtr& enclosing, int arraySize = DEFAULT_SIZE)
    302 		: Node			(TYPE_ARRAY_ELEMENT, enclosing)
    303 		, m_arraySize	(arraySize)
    304 	{
    305 		DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER		||
    306 				  enclosing->getType() == TYPE_LAYOUT_QUALIFIER			||
    307 				  enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER	||
    308 				  enclosing->getType() == TYPE_INTERFACE_BLOCK			||
    309 				  enclosing->getType() == TYPE_ARRAY_ELEMENT			||
    310 				  enclosing->getType() == TYPE_STRUCT_MEMBER			||
    311 				  enclosing->getType() == TYPE_TRANSFORM_FEEDBACK_TARGET);
    312 	}
    313 
    314 	const int m_arraySize;
    315 
    316 	enum
    317 	{
    318 		DEFAULT_SIZE	= -1,
    319 		UNSIZED_ARRAY	= -2,
    320 	};
    321 };
    322 
    323 class StructMember : public Node
    324 {
    325 public:
    326 	StructMember (const SharedPtr& enclosing)
    327 		: Node(TYPE_STRUCT_MEMBER, enclosing)
    328 	{
    329 		DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER		||
    330 				  enclosing->getType() == TYPE_LAYOUT_QUALIFIER			||
    331 				  enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER	||
    332 				  enclosing->getType() == TYPE_INTERFACE_BLOCK			||
    333 				  enclosing->getType() == TYPE_ARRAY_ELEMENT			||
    334 				  enclosing->getType() == TYPE_STRUCT_MEMBER			||
    335 				  enclosing->getType() == TYPE_TRANSFORM_FEEDBACK_TARGET);
    336 	}
    337 };
    338 
    339 class LayoutQualifier : public Node
    340 {
    341 public:
    342 	LayoutQualifier (const SharedPtr& enclosing, const glu::Layout& layout)
    343 		: Node		(TYPE_LAYOUT_QUALIFIER, enclosing)
    344 		, m_layout	(layout)
    345 	{
    346 		DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER		||
    347 				  enclosing->getType() == TYPE_LAYOUT_QUALIFIER			||
    348 				  enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER	||
    349 				  enclosing->getType() == TYPE_DEFAULT_BLOCK			||
    350 				  enclosing->getType() == TYPE_INTERFACE_BLOCK);
    351 	}
    352 
    353 	const glu::Layout m_layout;
    354 };
    355 
    356 class InterpolationQualifier : public Node
    357 {
    358 public:
    359 	InterpolationQualifier (const SharedPtr& enclosing, const glu::Interpolation& interpolation)
    360 		: Node				(TYPE_INTERPOLATION_QUALIFIER, enclosing)
    361 		, m_interpolation	(interpolation)
    362 	{
    363 		DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER		||
    364 				  enclosing->getType() == TYPE_LAYOUT_QUALIFIER			||
    365 				  enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER	||
    366 				  enclosing->getType() == TYPE_DEFAULT_BLOCK			||
    367 				  enclosing->getType() == TYPE_INTERFACE_BLOCK);
    368 	}
    369 
    370 	const glu::Interpolation m_interpolation;
    371 };
    372 
    373 class ShaderSet : public Node
    374 {
    375 public:
    376 			ShaderSet			(const SharedPtr& enclosing, glu::GLSLVersion version);
    377 
    378 	void	setStage			(glu::ShaderType type, bool referencing);
    379 	bool	isStagePresent		(glu::ShaderType stage) const;
    380 	bool	isStageReferencing	(glu::ShaderType stage) const;
    381 
    382 	const glu::GLSLVersion	m_version;
    383 private:
    384 	bool					m_stagePresent[glu::SHADERTYPE_LAST];
    385 	bool					m_stageReferencing[glu::SHADERTYPE_LAST];
    386 };
    387 
    388 ShaderSet::ShaderSet (const SharedPtr& enclosing, glu::GLSLVersion version)
    389 	: Node		(TYPE_SHADER_SET, enclosing)
    390 	, m_version	(version)
    391 {
    392 	DE_ASSERT(enclosing->getType() == TYPE_PROGRAM);
    393 
    394 	deMemset(m_stagePresent, 0, sizeof(m_stagePresent));
    395 	deMemset(m_stageReferencing, 0, sizeof(m_stageReferencing));
    396 }
    397 
    398 void ShaderSet::setStage (glu::ShaderType type, bool referencing)
    399 {
    400 	m_stagePresent[type] = true;
    401 	m_stageReferencing[type] = referencing;
    402 }
    403 
    404 bool ShaderSet::isStagePresent (glu::ShaderType stage) const
    405 {
    406 	DE_ASSERT(stage < glu::SHADERTYPE_LAST);
    407 	return m_stagePresent[stage];
    408 }
    409 
    410 bool ShaderSet::isStageReferencing (glu::ShaderType stage) const
    411 {
    412 	DE_ASSERT(stage < glu::SHADERTYPE_LAST);
    413 	return m_stageReferencing[stage];
    414 }
    415 
    416 class TransformFeedbackTarget : public Node
    417 {
    418 public:
    419 	TransformFeedbackTarget (const SharedPtr& enclosing, const char* builtinVarName = DE_NULL)
    420 		: Node				(TYPE_TRANSFORM_FEEDBACK_TARGET, enclosing)
    421 		, m_builtinVarName	(builtinVarName)
    422 	{
    423 	}
    424 
    425 	const char* const m_builtinVarName;
    426 };
    427 
    428 } // ResourceDefinition
    429 
    430 static glu::Precision getDataTypeDefaultPrecision (const glu::DataType& type)
    431 {
    432 	if (glu::isDataTypeBoolOrBVec(type))
    433 		return glu::PRECISION_LAST;
    434 	else if (glu::isDataTypeScalarOrVector(type) || glu::isDataTypeMatrix(type))
    435 		return glu::PRECISION_HIGHP;
    436 	else if (glu::isDataTypeSampler(type))
    437 		return glu::PRECISION_HIGHP;
    438 	else if (glu::isDataTypeImage(type))
    439 		return glu::PRECISION_HIGHP;
    440 	else if (type == glu::TYPE_UINT_ATOMIC_COUNTER)
    441 		return glu::PRECISION_HIGHP;
    442 
    443 	DE_ASSERT(false);
    444 	return glu::PRECISION_LAST;
    445 }
    446 
    447 static de::MovePtr<ProgramInterfaceDefinition::Program>	generateProgramDefinitionFromResource (const ResourceDefinition::Node* resource)
    448 {
    449 	de::MovePtr<ProgramInterfaceDefinition::Program>	program	(new ProgramInterfaceDefinition::Program());
    450 	const ResourceDefinition::Node*						head	= resource;
    451 
    452 	if (head->getType() == ResourceDefinition::Node::TYPE_VARIABLE)
    453 	{
    454 		DE_ASSERT(dynamic_cast<const ResourceDefinition::Variable*>(resource));
    455 
    456 		enum BindingType
    457 		{
    458 			BINDING_VARIABLE,
    459 			BINDING_INTERFACE_BLOCK,
    460 			BINDING_DEFAULT_BLOCK
    461 		};
    462 
    463 		int											structNdx				= 0;
    464 		int											autoAssignArraySize		= 0;
    465 		const glu::DataType							basicType				= static_cast<const ResourceDefinition::Variable*>(resource)->m_dataType;
    466 		BindingType									boundObject				= BINDING_VARIABLE;
    467 		glu::VariableDeclaration					variable				(glu::VarType(basicType, getDataTypeDefaultPrecision(basicType)), "target");
    468 		glu::InterfaceBlock							interfaceBlock;
    469 		ProgramInterfaceDefinition::DefaultBlock	defaultBlock;
    470 		std::vector<std::string>					feedbackTargetVaryingPath;
    471 		bool										feedbackTargetSet		= false;
    472 
    473 		// image specific
    474 		if (glu::isDataTypeImage(basicType))
    475 		{
    476 			variable.memoryAccessQualifierBits |= glu::MEMORYACCESSQUALIFIER_READONLY_BIT;
    477 			variable.layout.binding = 1;
    478 
    479 			if (basicType >= glu::TYPE_IMAGE_2D && basicType <= glu::TYPE_IMAGE_3D)
    480 				variable.layout.format = glu::FORMATLAYOUT_RGBA8;
    481 			else if (basicType >= glu::TYPE_INT_IMAGE_2D && basicType <= glu::TYPE_INT_IMAGE_3D)
    482 				variable.layout.format = glu::FORMATLAYOUT_RGBA8I;
    483 			else if (basicType >= glu::TYPE_UINT_IMAGE_2D && basicType <= glu::TYPE_UINT_IMAGE_3D)
    484 				variable.layout.format = glu::FORMATLAYOUT_RGBA8UI;
    485 			else
    486 				DE_ASSERT(false);
    487 		}
    488 
    489 		// atomic counter specific
    490 		if (basicType == glu::TYPE_UINT_ATOMIC_COUNTER)
    491 			variable.layout.binding = 1;
    492 
    493 		for (head = head->getEnclosingNode(); head; head = head->getEnclosingNode())
    494 		{
    495 			if (head->getType() == ResourceDefinition::Node::TYPE_STORAGE_QUALIFIER)
    496 			{
    497 				const ResourceDefinition::StorageQualifier* qualifier = static_cast<const ResourceDefinition::StorageQualifier*>(head);
    498 
    499 				DE_ASSERT(dynamic_cast<const ResourceDefinition::StorageQualifier*>(head));
    500 
    501 				if (boundObject == BINDING_VARIABLE)
    502 				{
    503 					DE_ASSERT(variable.storage == glu::STORAGE_LAST);
    504 					variable.storage = qualifier->m_storage;
    505 				}
    506 				else if (boundObject == BINDING_INTERFACE_BLOCK)
    507 				{
    508 					DE_ASSERT(interfaceBlock.storage == glu::STORAGE_LAST);
    509 					interfaceBlock.storage = qualifier->m_storage;
    510 				}
    511 				else
    512 					DE_ASSERT(false);
    513 			}
    514 			else if (head->getType() == ResourceDefinition::Node::TYPE_LAYOUT_QUALIFIER)
    515 			{
    516 				const ResourceDefinition::LayoutQualifier*	qualifier		= static_cast<const ResourceDefinition::LayoutQualifier*>(head);
    517 				glu::Layout*								targetLayout	= DE_NULL;
    518 
    519 				DE_ASSERT(dynamic_cast<const ResourceDefinition::LayoutQualifier*>(head));
    520 
    521 				if (boundObject == BINDING_VARIABLE)
    522 					targetLayout = &variable.layout;
    523 				else if (boundObject == BINDING_INTERFACE_BLOCK)
    524 					targetLayout = &interfaceBlock.layout;
    525 				else
    526 					DE_ASSERT(false);
    527 
    528 				if (qualifier->m_layout.location != -1)
    529 					targetLayout->location = qualifier->m_layout.location;
    530 
    531 				if (qualifier->m_layout.binding != -1)
    532 					targetLayout->binding = qualifier->m_layout.binding;
    533 
    534 				if (qualifier->m_layout.offset != -1)
    535 					targetLayout->offset = qualifier->m_layout.offset;
    536 
    537 				if (qualifier->m_layout.format != glu::FORMATLAYOUT_LAST)
    538 					targetLayout->format = qualifier->m_layout.format;
    539 
    540 				if (qualifier->m_layout.matrixOrder != glu::MATRIXORDER_LAST)
    541 					targetLayout->matrixOrder = qualifier->m_layout.matrixOrder;
    542 			}
    543 			else if (head->getType() == ResourceDefinition::Node::TYPE_INTERPOLATION_QUALIFIER)
    544 			{
    545 				const ResourceDefinition::InterpolationQualifier* qualifier = static_cast<const ResourceDefinition::InterpolationQualifier*>(head);
    546 
    547 				DE_ASSERT(dynamic_cast<const ResourceDefinition::InterpolationQualifier*>(head));
    548 
    549 				if (boundObject == BINDING_VARIABLE)
    550 					variable.interpolation = qualifier->m_interpolation;
    551 				else
    552 					DE_ASSERT(false);
    553 			}
    554 			else if (head->getType() == ResourceDefinition::Node::TYPE_ARRAY_ELEMENT)
    555 			{
    556 				DE_ASSERT(dynamic_cast<const ResourceDefinition::ArrayElement*>(head));
    557 
    558 				const ResourceDefinition::ArrayElement*	arrayElement = static_cast<const ResourceDefinition::ArrayElement*>(head);
    559 				int										arraySize;
    560 
    561 				// Vary array size per level
    562 				if (arrayElement->m_arraySize == ResourceDefinition::ArrayElement::DEFAULT_SIZE)
    563 				{
    564 					if (--autoAssignArraySize <= 1)
    565 						autoAssignArraySize = 3;
    566 
    567 					arraySize = autoAssignArraySize;
    568 				}
    569 				else if (arrayElement->m_arraySize == ResourceDefinition::ArrayElement::UNSIZED_ARRAY)
    570 					arraySize = glu::VarType::UNSIZED_ARRAY;
    571 				else
    572 					arraySize = arrayElement->m_arraySize;
    573 
    574 				if (boundObject == BINDING_VARIABLE)
    575 					variable.varType = glu::VarType(variable.varType, arraySize);
    576 				else if (boundObject == BINDING_INTERFACE_BLOCK)
    577 					interfaceBlock.dimensions.push_back(arraySize);
    578 				else
    579 					DE_ASSERT(false);
    580 
    581 				if (feedbackTargetSet)
    582 					feedbackTargetVaryingPath.back().append("[0]");
    583 			}
    584 			else if (head->getType() == ResourceDefinition::Node::TYPE_STRUCT_MEMBER)
    585 			{
    586 				DE_ASSERT(dynamic_cast<const ResourceDefinition::StructMember*>(head));
    587 				DE_ASSERT(boundObject == BINDING_VARIABLE);
    588 
    589 				// Struct members cannot contain any qualifiers except precision
    590 				DE_ASSERT(variable.interpolation == glu::INTERPOLATION_LAST);
    591 				DE_ASSERT(variable.layout == glu::Layout());
    592 				DE_ASSERT(variable.memoryAccessQualifierBits == 0);
    593 				DE_ASSERT(variable.storage == glu::STORAGE_LAST);
    594 
    595 				{
    596 					glu::StructType* structPtr = new glu::StructType(("StructType" + de::toString(structNdx++)).c_str());
    597 					structPtr->addMember(variable.name.c_str(), variable.varType);
    598 
    599 					variable = glu::VariableDeclaration(glu::VarType(structPtr), "target");
    600 				}
    601 
    602 				if (feedbackTargetSet)
    603 					feedbackTargetVaryingPath.push_back("target");
    604 			}
    605 			else if (head->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK)
    606 			{
    607 				DE_ASSERT(dynamic_cast<const ResourceDefinition::InterfaceBlock*>(head));
    608 				DE_ASSERT(boundObject == BINDING_VARIABLE);
    609 
    610 				const bool named = static_cast<const ResourceDefinition::InterfaceBlock*>(head)->m_named;
    611 
    612 				boundObject = BINDING_INTERFACE_BLOCK;
    613 
    614 				interfaceBlock.interfaceName = "TargetInterface";
    615 				interfaceBlock.instanceName = (named) ? ("targetInstance") : ("");
    616 				interfaceBlock.variables.push_back(variable);
    617 
    618 				if (feedbackTargetSet && !interfaceBlock.instanceName.empty())
    619 					feedbackTargetVaryingPath.push_back(interfaceBlock.interfaceName);
    620 			}
    621 			else if (head->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK)
    622 			{
    623 				DE_ASSERT(dynamic_cast<const ResourceDefinition::DefaultBlock*>(head));
    624 				DE_ASSERT(boundObject == BINDING_VARIABLE || boundObject == BINDING_INTERFACE_BLOCK);
    625 
    626 				if (boundObject == BINDING_VARIABLE)
    627 					defaultBlock.variables.push_back(variable);
    628 				else if (boundObject == BINDING_INTERFACE_BLOCK)
    629 					defaultBlock.interfaceBlocks.push_back(interfaceBlock);
    630 				else
    631 					DE_ASSERT(false);
    632 
    633 				boundObject = BINDING_DEFAULT_BLOCK;
    634 			}
    635 			else if (head->getType() == ResourceDefinition::Node::TYPE_SHADER)
    636 			{
    637 				DE_ASSERT(dynamic_cast<const ResourceDefinition::Shader*>(head));
    638 
    639 				const ResourceDefinition::Shader*	shaderDef	= static_cast<const ResourceDefinition::Shader*>(head);
    640 				ProgramInterfaceDefinition::Shader* shader		= program->addShader(shaderDef->m_type, shaderDef->m_version);
    641 
    642 				shader->getDefaultBlock() = defaultBlock;
    643 			}
    644 			else if (head->getType() == ResourceDefinition::Node::TYPE_SHADER_SET)
    645 			{
    646 				DE_ASSERT(dynamic_cast<const ResourceDefinition::ShaderSet*>(head));
    647 
    648 				const ResourceDefinition::ShaderSet* shaderDef = static_cast<const ResourceDefinition::ShaderSet*>(head);
    649 
    650 				for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; ++shaderType)
    651 				{
    652 					if (shaderDef->isStagePresent((glu::ShaderType)shaderType))
    653 					{
    654 						ProgramInterfaceDefinition::Shader* shader = program->addShader((glu::ShaderType)shaderType, shaderDef->m_version);
    655 
    656 						if (shaderDef->isStageReferencing((glu::ShaderType)shaderType))
    657 							shader->getDefaultBlock() = defaultBlock;
    658 					}
    659 				}
    660 			}
    661 			else if (head->getType() == ResourceDefinition::Node::TYPE_PROGRAM)
    662 			{
    663 				DE_ASSERT(dynamic_cast<const ResourceDefinition::Program*>(head));
    664 
    665 				const ResourceDefinition::Program* programDef = static_cast<const ResourceDefinition::Program*>(head);
    666 
    667 				program->setSeparable(programDef->m_separable);
    668 
    669 				DE_ASSERT(feedbackTargetSet == !feedbackTargetVaryingPath.empty());
    670 				if (!feedbackTargetVaryingPath.empty())
    671 				{
    672 					std::ostringstream buf;
    673 
    674 					for (std::vector<std::string>::reverse_iterator it = feedbackTargetVaryingPath.rbegin(); it != feedbackTargetVaryingPath.rend(); ++it)
    675 					{
    676 						if (it != feedbackTargetVaryingPath.rbegin())
    677 							buf << ".";
    678 						buf << *it;
    679 					}
    680 
    681 					program->addTransformFeedbackVarying(buf.str());
    682 					program->setTransformFeedbackMode(GL_INTERLEAVED_ATTRIBS);
    683 				}
    684 				break;
    685 			}
    686 			else if (head->getType() == ResourceDefinition::Node::TYPE_TRANSFORM_FEEDBACK_TARGET)
    687 			{
    688 				DE_ASSERT(dynamic_cast<const ResourceDefinition::TransformFeedbackTarget*>(head));
    689 
    690 				const ResourceDefinition::TransformFeedbackTarget* feedbackTarget = static_cast<const ResourceDefinition::TransformFeedbackTarget*>(head);
    691 
    692 				DE_ASSERT(feedbackTarget->m_builtinVarName == DE_NULL);
    693 				DE_UNREF(feedbackTarget);
    694 
    695 				feedbackTargetSet = true;
    696 				feedbackTargetVaryingPath.push_back(variable.name);
    697 			}
    698 			else
    699 			{
    700 				DE_ASSERT(DE_FALSE);
    701 				break;
    702 			}
    703 		}
    704 	}
    705 	else if (head->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK ||
    706 			 head->getType() == ResourceDefinition::Node::TYPE_TRANSFORM_FEEDBACK_TARGET)
    707 	{
    708 		const char* feedbackTargetVaryingName = DE_NULL;
    709 
    710 		// empty default block
    711 
    712 		for (; head; head = head->getEnclosingNode())
    713 		{
    714 			if (head->getType() == ResourceDefinition::Node::TYPE_SHADER)
    715 			{
    716 				DE_ASSERT(dynamic_cast<const ResourceDefinition::Shader*>(head));
    717 
    718 				const ResourceDefinition::Shader* shaderDef = static_cast<const ResourceDefinition::Shader*>(head);
    719 
    720 				program->addShader(shaderDef->m_type, shaderDef->m_version);
    721 			}
    722 			else if (head->getType() == ResourceDefinition::Node::TYPE_SHADER_SET)
    723 			{
    724 				DE_ASSERT(dynamic_cast<const ResourceDefinition::ShaderSet*>(head));
    725 
    726 				const ResourceDefinition::ShaderSet* shaderDef = static_cast<const ResourceDefinition::ShaderSet*>(head);
    727 
    728 				for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; ++shaderType)
    729 					if (shaderDef->isStagePresent((glu::ShaderType)shaderType))
    730 						program->addShader((glu::ShaderType)shaderType, shaderDef->m_version);
    731 			}
    732 			else if (head->getType() == ResourceDefinition::Node::TYPE_PROGRAM)
    733 			{
    734 				DE_ASSERT(dynamic_cast<const ResourceDefinition::Program*>(head));
    735 
    736 				const ResourceDefinition::Program* programDef = static_cast<const ResourceDefinition::Program*>(head);
    737 
    738 				program->setSeparable(programDef->m_separable);
    739 				if (feedbackTargetVaryingName)
    740 				{
    741 					program->addTransformFeedbackVarying(std::string(feedbackTargetVaryingName));
    742 					program->setTransformFeedbackMode(GL_INTERLEAVED_ATTRIBS);
    743 				}
    744 				break;
    745 			}
    746 			else if (head->getType() == ResourceDefinition::Node::TYPE_TRANSFORM_FEEDBACK_TARGET)
    747 			{
    748 				DE_ASSERT(dynamic_cast<const ResourceDefinition::TransformFeedbackTarget*>(head));
    749 
    750 				const ResourceDefinition::TransformFeedbackTarget* feedbackTarget = static_cast<const ResourceDefinition::TransformFeedbackTarget*>(head);
    751 
    752 				DE_ASSERT(feedbackTarget->m_builtinVarName != DE_NULL);
    753 
    754 				feedbackTargetVaryingName = feedbackTarget->m_builtinVarName;
    755 			}
    756 			else if (head->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK)
    757 			{
    758 			}
    759 			else
    760 			{
    761 				DE_ASSERT(DE_FALSE);
    762 				break;
    763 			}
    764 		}
    765 	}
    766 
    767 	return program;
    768 }
    769 
    770 static void checkAndLogProgram (const glu::ShaderProgram& program, const ProgramInterfaceDefinition::Program* programDefinition, const glw::Functions& gl, tcu::TestLog& log)
    771 {
    772 	const tcu::ScopedLogSection section(log, "Program", "Program");
    773 
    774 	log << program;
    775 	if (!program.isOk())
    776 	{
    777 		log << tcu::TestLog::Message << "Program build failed, checking if program exceeded implementation limits" << tcu::TestLog::EndMessage;
    778 		checkProgramResourceUsage(programDefinition, gl, log);
    779 
    780 		// within limits
    781 		throw tcu::TestError("could not build program");
    782 	}
    783 }
    784 
    785 // Resource list query case
    786 
    787 class ResourceListTestCase : public TestCase
    788 {
    789 public:
    790 												ResourceListTestCase		(Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, const ProgramInterface& interface, const char* name = DE_NULL);
    791 												~ResourceListTestCase		(void);
    792 
    793 protected:
    794 	void										deinit						(void);
    795 	IterateResult								iterate						(void);
    796 
    797 	void										queryResourceList			(std::vector<std::string>& dst, glw::GLuint program);
    798 	bool										verifyResourceList			(const std::vector<std::string>& resourceList, const std::vector<std::string>& expectedResources);
    799 	bool										verifyResourceIndexQuery	(const std::vector<std::string>& resourceList, const std::vector<std::string>& referenceResources, glw::GLuint program);
    800 	bool										verifyMaxNameLength			(const std::vector<std::string>& referenceResourceList, glw::GLuint program);
    801 
    802 	static std::string							genTestCaseName				(const ResourceDefinition::Node*);
    803 
    804 	const ProgramInterface						m_programInterface;
    805 	ResourceDefinition::Node::SharedPtr			m_targetResource;
    806 };
    807 
    808 ResourceListTestCase::ResourceListTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, const ProgramInterface& interface, const char* name)
    809 	: TestCase				(context, (name == DE_NULL) ? (genTestCaseName(targetResource.get()).c_str()) : (name), "")
    810 	, m_programInterface	(interface)
    811 	, m_targetResource		(targetResource)
    812 {
    813 	// GL_ATOMIC_COUNTER_BUFFER: no resource names
    814 	DE_ASSERT(m_programInterface != PROGRAMINTERFACE_ATOMIC_COUNTER_BUFFER);
    815 }
    816 
    817 ResourceListTestCase::~ResourceListTestCase (void)
    818 {
    819 	deinit();
    820 }
    821 
    822 void ResourceListTestCase::deinit (void)
    823 {
    824 	m_targetResource.clear();
    825 }
    826 
    827 ResourceListTestCase::IterateResult ResourceListTestCase::iterate (void)
    828 {
    829 	const de::UniquePtr<ProgramInterfaceDefinition::Program>	programDefinition	(generateProgramDefinitionFromResource(m_targetResource.get()));
    830 	const glu::ShaderProgram									program				(m_context.getRenderContext(), generateProgramInterfaceProgramSources(programDefinition.get()));
    831 
    832 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    833 	checkAndLogProgram(program, programDefinition.get(), m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    834 
    835 	// Check resource list
    836 	{
    837 		const tcu::ScopedLogSection	section				(m_testCtx.getLog(), "ResourceList", "Resource list");
    838 		std::vector<std::string>	resourceList;
    839 		std::vector<std::string>	expectedResources;
    840 
    841 		queryResourceList(resourceList, program.getProgram());
    842 		expectedResources = getProgramInterfaceResourceList(programDefinition.get(), m_programInterface);
    843 
    844 		// verify the list and the expected list match
    845 
    846 		if (!verifyResourceList(resourceList, expectedResources))
    847 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid resource list");
    848 
    849 		// verify GetProgramResourceIndex() matches the indices of the list
    850 
    851 		if (!verifyResourceIndexQuery(resourceList, expectedResources, program.getProgram()))
    852 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "GetProgramResourceIndex returned unexpected values");
    853 
    854 		// Verify MAX_NAME_LENGTH
    855 		if (!verifyMaxNameLength(resourceList, program.getProgram()))
    856 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "MAX_NAME_LENGTH invalid");
    857 	}
    858 
    859 	return STOP;
    860 }
    861 
    862 void ResourceListTestCase::queryResourceList (std::vector<std::string>& dst, glw::GLuint program)
    863 {
    864 	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
    865 	const glw::GLenum		programInterface	= getProgramInterfaceGLEnum(m_programInterface);
    866 	glw::GLint				numActiveResources	= 0;
    867 	glw::GLint				maxNameLength		= 0;
    868 	std::vector<char>		buffer;
    869 
    870 	m_testCtx.getLog() << tcu::TestLog::Message << "Querying " << glu::getProgramInterfaceName(programInterface) << " interface:" << tcu::TestLog::EndMessage;
    871 
    872 	gl.getProgramInterfaceiv(program, programInterface, GL_ACTIVE_RESOURCES, &numActiveResources);
    873 	gl.getProgramInterfaceiv(program, programInterface, GL_MAX_NAME_LENGTH, &maxNameLength);
    874 	GLU_EXPECT_NO_ERROR(gl.getError(), "query interface");
    875 
    876 	m_testCtx.getLog()	<< tcu::TestLog::Message
    877 						<< "\tGL_ACTIVE_RESOURCES = " << numActiveResources << "\n"
    878 						<< "\tGL_MAX_NAME_LENGTH = " << maxNameLength
    879 						<< tcu::TestLog::EndMessage;
    880 
    881 	m_testCtx.getLog() << tcu::TestLog::Message << "Querying all active resources" << tcu::TestLog::EndMessage;
    882 
    883 	buffer.resize(maxNameLength+1, '\0');
    884 
    885 	for (int resourceNdx = 0; resourceNdx < numActiveResources; ++resourceNdx)
    886 	{
    887 		glw::GLint written = 0;
    888 
    889 		gl.getProgramResourceName(program, programInterface, resourceNdx, maxNameLength, &written, &buffer[0]);
    890 		GLU_EXPECT_NO_ERROR(gl.getError(), "query resource name");
    891 
    892 		dst.push_back(std::string(&buffer[0], written));
    893 	}
    894 }
    895 
    896 bool ResourceListTestCase::verifyResourceList (const std::vector<std::string>& resourceList, const std::vector<std::string>& expectedResources)
    897 {
    898 	bool error = false;
    899 
    900 	// Log and compare resource lists
    901 
    902 	m_testCtx.getLog() << tcu::TestLog::Message << "GL returned resources:" << tcu::TestLog::EndMessage;
    903 
    904 	for (int ndx = 0; ndx < (int)resourceList.size(); ++ndx)
    905 		m_testCtx.getLog() << tcu::TestLog::Message << "\t" << ndx << ": " << resourceList[ndx] << tcu::TestLog::EndMessage;
    906 
    907 	m_testCtx.getLog() << tcu::TestLog::Message << "Expected list of resources:" << tcu::TestLog::EndMessage;
    908 
    909 	for (int ndx = 0; ndx < (int)expectedResources.size(); ++ndx)
    910 		m_testCtx.getLog() << tcu::TestLog::Message << "\t" << ndx << ": " << expectedResources[ndx] << tcu::TestLog::EndMessage;
    911 
    912 	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying resource list contents." << tcu::TestLog::EndMessage;
    913 
    914 	for (int ndx = 0; ndx < (int)expectedResources.size(); ++ndx)
    915 	{
    916 		if (!de::contains(resourceList.begin(), resourceList.end(), expectedResources[ndx]))
    917 		{
    918 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, resource list did not contain active resource " << expectedResources[ndx] << tcu::TestLog::EndMessage;
    919 			error = true;
    920 		}
    921 	}
    922 
    923 	for (int ndx = 0; ndx < (int)resourceList.size(); ++ndx)
    924 	{
    925 		if (!de::contains(expectedResources.begin(), expectedResources.end(), resourceList[ndx]))
    926 		{
    927 			// Ignore all builtin variables, mismatch causes errors otherwise
    928 			if (deStringBeginsWith(resourceList[ndx].c_str(), "gl_") == DE_FALSE)
    929 			{
    930 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, resource list contains unexpected resource name " << resourceList[ndx] << tcu::TestLog::EndMessage;
    931 				error = true;
    932 			}
    933 			else
    934 				m_testCtx.getLog() << tcu::TestLog::Message << "Note, resource list contains unknown built-in " << resourceList[ndx] << ". This variable is ignored." << tcu::TestLog::EndMessage;
    935 		}
    936 	}
    937 
    938 	return !error;
    939 }
    940 
    941 bool ResourceListTestCase::verifyResourceIndexQuery (const std::vector<std::string>& resourceList, const std::vector<std::string>& referenceResources, glw::GLuint program)
    942 {
    943 	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
    944 	const glw::GLenum		programInterface	= getProgramInterfaceGLEnum(m_programInterface);
    945 	bool					error				= false;
    946 
    947 	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying GetProgramResourceIndex returns correct indices for resource names." << tcu::TestLog::EndMessage;
    948 
    949 	for (int ndx = 0; ndx < (int)referenceResources.size(); ++ndx)
    950 	{
    951 		const glw::GLuint index = gl.getProgramResourceIndex(program, programInterface, referenceResources[ndx].c_str());
    952 		GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
    953 
    954 		if (index == GL_INVALID_INDEX)
    955 		{
    956 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, for active resource " << referenceResources[ndx] << " got index GL_INVALID_INDEX." << tcu::TestLog::EndMessage;
    957 			error = true;
    958 		}
    959 		else if ((int)index >= (int)resourceList.size())
    960 		{
    961 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, for active resource " << referenceResources[ndx] << " got index " << index << " (larger or equal to GL_ACTIVE_RESOURCES)." << tcu::TestLog::EndMessage;
    962 			error = true;
    963 		}
    964 		else if (resourceList[index] != referenceResources[ndx])
    965 		{
    966 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, for active resource " << referenceResources[ndx] << " got index (index = " << index << ") of another resource (" << resourceList[index] << ")." << tcu::TestLog::EndMessage;
    967 			error = true;
    968 		}
    969 	}
    970 
    971 	// Query for "name" should match "name[0]"
    972 
    973 	for (int ndx = 0; ndx < (int)referenceResources.size(); ++ndx)
    974 	{
    975 		if (stringEndsWith(referenceResources[ndx], "[0]"))
    976 		{
    977 			const std::string	queryString	= referenceResources[ndx].substr(0, referenceResources[ndx].length()-3);
    978 			const glw::GLuint	index		= gl.getProgramResourceIndex(program, programInterface, queryString.c_str());
    979 			GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
    980 
    981 			if (index == GL_INVALID_INDEX)
    982 			{
    983 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for " << queryString << " resulted in index GL_INVALID_INDEX." << tcu::TestLog::EndMessage;
    984 				error = true;
    985 			}
    986 			else if ((int)index >= (int)resourceList.size())
    987 			{
    988 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for " << queryString << " resulted in index " << index << " (larger or equal to GL_ACTIVE_RESOURCES)." << tcu::TestLog::EndMessage;
    989 				error = true;
    990 			}
    991 			else if (resourceList[index] != queryString + "[0]")
    992 			{
    993 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for " << queryString << " got index (index = " << index << ") of another resource (" << resourceList[index] << ")." << tcu::TestLog::EndMessage;
    994 				error = true;
    995 			}
    996 		}
    997 	}
    998 
    999 	return !error;
   1000 }
   1001 
   1002 bool ResourceListTestCase::verifyMaxNameLength (const std::vector<std::string>& resourceList, glw::GLuint program)
   1003 {
   1004 	const glw::Functions&	gl						= m_context.getRenderContext().getFunctions();
   1005 	const glw::GLenum		programInterface		= getProgramInterfaceGLEnum(m_programInterface);
   1006 	glw::GLint				maxNameLength			= 0;
   1007 	glw::GLint				expectedMaxNameLength	= 0;
   1008 
   1009 	gl.getProgramInterfaceiv(program, programInterface, GL_MAX_NAME_LENGTH, &maxNameLength);
   1010 	GLU_EXPECT_NO_ERROR(gl.getError(), "query interface");
   1011 
   1012 	for (int ndx = 0; ndx < (int)resourceList.size(); ++ndx)
   1013 		expectedMaxNameLength = de::max(expectedMaxNameLength, (int)resourceList[ndx].size() + 1);
   1014 
   1015 	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying MAX_NAME_LENGTH, expecting " << expectedMaxNameLength << " (i.e. consistent with the queried resource list)" << tcu::TestLog::EndMessage;
   1016 
   1017 	if (expectedMaxNameLength != maxNameLength)
   1018 	{
   1019 		m_testCtx.getLog() << tcu::TestLog::Message << "Error, got " << maxNameLength << tcu::TestLog::EndMessage;
   1020 		return false;
   1021 	}
   1022 
   1023 	return true;
   1024 }
   1025 
   1026 std::string ResourceListTestCase::genTestCaseName (const ResourceDefinition::Node* root)
   1027 {
   1028 	std::ostringstream buf;
   1029 	buf << "var";
   1030 
   1031 	for (const ResourceDefinition::Node* node = root; node; node = node->getEnclosingNode())
   1032 	{
   1033 		if (node->getType() == ResourceDefinition::Node::TYPE_STRUCT_MEMBER)
   1034 			buf << "_struct";
   1035 		if (node->getType() == ResourceDefinition::Node::TYPE_ARRAY_ELEMENT)
   1036 			buf << "_array";
   1037 	}
   1038 
   1039 	return buf.str();
   1040 }
   1041 
   1042 // Resouce property query case
   1043 
   1044 class ResourceTestCase : public ProgramInterfaceQueryTestCase
   1045 {
   1046 public:
   1047 															ResourceTestCase			(Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, const ProgramResourceQueryTestTarget& queryTarget, const char* name = DE_NULL);
   1048 															~ResourceTestCase			(void);
   1049 
   1050 private:
   1051 	void													init						(void);
   1052 	void													deinit						(void);
   1053 	ProgramInterfaceDefinition::Program*					getProgramDefinition		(void);
   1054 	std::vector<std::string>								getQueryTargetResources		(void);
   1055 
   1056 	static std::string										genTestCaseName				(const ResourceDefinition::Node*);
   1057 	static std::string										genMultilineDescription		(const ResourceDefinition::Node*);
   1058 
   1059 	ResourceDefinition::Node::SharedPtr						m_targetResource;
   1060 	ProgramInterfaceDefinition::Program*					m_program;
   1061 	std::vector<std::string>								m_targetResources;
   1062 };
   1063 
   1064 ResourceTestCase::ResourceTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, const ProgramResourceQueryTestTarget& queryTarget, const char* name)
   1065 	: ProgramInterfaceQueryTestCase	(context, (name == DE_NULL) ? (genTestCaseName(targetResource.get()).c_str()) : (name), "", queryTarget)
   1066 	, m_targetResource				(targetResource)
   1067 	, m_program						(DE_NULL)
   1068 {
   1069 }
   1070 
   1071 ResourceTestCase::~ResourceTestCase (void)
   1072 {
   1073 	deinit();
   1074 }
   1075 
   1076 void ResourceTestCase::init (void)
   1077 {
   1078 	m_testCtx.getLog()
   1079 		<< tcu::TestLog::Message
   1080 		<< genMultilineDescription(m_targetResource.get())
   1081 		<< tcu::TestLog::EndMessage;
   1082 
   1083 	// Program
   1084 	{
   1085 		// Generate interface with target resource
   1086 		m_program = generateProgramDefinitionFromResource(m_targetResource.get()).release();
   1087 		m_targetResources = getProgramInterfaceResourceList(m_program, getTargetInterface());
   1088 	}
   1089 }
   1090 
   1091 void ResourceTestCase::deinit (void)
   1092 {
   1093 	m_targetResource.clear();
   1094 
   1095 	delete m_program;
   1096 	m_program = DE_NULL;
   1097 
   1098 	m_targetResources = std::vector<std::string>();
   1099 }
   1100 
   1101 ProgramInterfaceDefinition::Program* ResourceTestCase::getProgramDefinition (void)
   1102 {
   1103 	return m_program;
   1104 }
   1105 
   1106 std::vector<std::string> ResourceTestCase::getQueryTargetResources (void)
   1107 {
   1108 	return m_targetResources;
   1109 }
   1110 
   1111 std::string ResourceTestCase::genTestCaseName (const ResourceDefinition::Node* resource)
   1112 {
   1113 	if (resource->getType() == ResourceDefinition::Node::TYPE_VARIABLE)
   1114 	{
   1115 		DE_ASSERT(dynamic_cast<const ResourceDefinition::Variable*>(resource));
   1116 
   1117 		const ResourceDefinition::Variable* variable = static_cast<const ResourceDefinition::Variable*>(resource);
   1118 
   1119 		return convertGLTypeNameToTestName(glu::getDataTypeName(variable->m_dataType));
   1120 	}
   1121 
   1122 	DE_ASSERT(false);
   1123 	return "";
   1124 }
   1125 
   1126 std::string ResourceTestCase::genMultilineDescription (const ResourceDefinition::Node* resource)
   1127 {
   1128 	if (resource->getType() == ResourceDefinition::Node::TYPE_VARIABLE)
   1129 	{
   1130 		DE_ASSERT(dynamic_cast<const ResourceDefinition::Variable*>(resource));
   1131 
   1132 		const ResourceDefinition::Variable*	varDef				= static_cast<const ResourceDefinition::Variable*>(resource);
   1133 		std::ostringstream					buf;
   1134 		std::ostringstream					structureDescriptor;
   1135 		std::string							uniformType;
   1136 
   1137 		for (const ResourceDefinition::Node* node = resource; node; node = node->getEnclosingNode())
   1138 		{
   1139 			if (node->getType() == ResourceDefinition::Node::TYPE_STORAGE_QUALIFIER)
   1140 			{
   1141 				DE_ASSERT(dynamic_cast<const ResourceDefinition::StorageQualifier*>(node));
   1142 
   1143 				const ResourceDefinition::StorageQualifier*	storageDef = static_cast<const ResourceDefinition::StorageQualifier*>(node);
   1144 
   1145 				uniformType = std::string(" ") + glu::getStorageName(storageDef->m_storage);
   1146 				structureDescriptor << "\n\tdeclared as " << glu::getStorageName(storageDef->m_storage);
   1147 			}
   1148 
   1149 			if (node->getType() == ResourceDefinition::Node::TYPE_ARRAY_ELEMENT)
   1150 				structureDescriptor << "\n\tarray";
   1151 
   1152 			if (node->getType() == ResourceDefinition::Node::TYPE_STRUCT_MEMBER)
   1153 				structureDescriptor << "\n\tin a struct";
   1154 
   1155 			if (node->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK)
   1156 				structureDescriptor << "\n\tin the default block";
   1157 
   1158 			if (node->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK)
   1159 				structureDescriptor << "\n\tin an interface block";
   1160 		}
   1161 
   1162 		buf	<< "Querying properties of " << glu::getDataTypeName(varDef->m_dataType) << uniformType << " variable.\n"
   1163 			<< "Variable is:\n"
   1164 			<< "\t" << glu::getDataTypeName(varDef->m_dataType)
   1165 			<< structureDescriptor.str();
   1166 
   1167 		return buf.str();
   1168 	}
   1169 	else if (resource->getType() == ResourceDefinition::Node::TYPE_TRANSFORM_FEEDBACK_TARGET)
   1170 	{
   1171 		DE_ASSERT(dynamic_cast<const ResourceDefinition::TransformFeedbackTarget*>(resource));
   1172 
   1173 		const ResourceDefinition::TransformFeedbackTarget* xfbDef = static_cast<const ResourceDefinition::TransformFeedbackTarget*>(resource);
   1174 
   1175 		DE_ASSERT(xfbDef->m_builtinVarName);
   1176 
   1177 		return std::string("Querying properties of a builtin variable ") + xfbDef->m_builtinVarName;
   1178 	}
   1179 
   1180 	DE_ASSERT(false);
   1181 	return DE_NULL;
   1182 }
   1183 
   1184 class ResourceNameBufferLimitCase : public TestCase
   1185 {
   1186 public:
   1187 					ResourceNameBufferLimitCase		(Context& context, const char* name, const char* description);
   1188 					~ResourceNameBufferLimitCase	(void);
   1189 
   1190 private:
   1191 	IterateResult	iterate							(void);
   1192 };
   1193 
   1194 ResourceNameBufferLimitCase::ResourceNameBufferLimitCase (Context& context, const char* name, const char* description)
   1195 	: TestCase(context, name, description)
   1196 {
   1197 }
   1198 
   1199 ResourceNameBufferLimitCase::~ResourceNameBufferLimitCase (void)
   1200 {
   1201 }
   1202 
   1203 ResourceNameBufferLimitCase::IterateResult ResourceNameBufferLimitCase::iterate (void)
   1204 {
   1205 	static const char* const computeSource =	"#version 310 es\n"
   1206 												"layout(local_size_x = 1) in;\n"
   1207 												"uniform highp int u_uniformWithALongName;\n"
   1208 												"writeonly buffer OutputBufferBlock { highp int b_output_int; };\n"
   1209 												"void main ()\n"
   1210 												"{\n"
   1211 												"	b_output_int = u_uniformWithALongName;\n"
   1212 												"}\n";
   1213 
   1214 	const glw::Functions&		gl				= m_context.getRenderContext().getFunctions();
   1215 	const glu::ShaderProgram	program			(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(computeSource));
   1216 	glw::GLuint					uniformIndex;
   1217 
   1218 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1219 
   1220 	// Log program
   1221 	{
   1222 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Program", "Program");
   1223 
   1224 		m_testCtx.getLog() << program;
   1225 		if (!program.isOk())
   1226 			throw tcu::TestError("could not build program");
   1227 	}
   1228 
   1229 	uniformIndex = gl.getProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_uniformWithALongName");
   1230 	GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
   1231 
   1232 	if (uniformIndex == GL_INVALID_INDEX)
   1233 		throw tcu::TestError("Uniform u_uniformWithALongName resource index was GL_INVALID_INDEX");
   1234 
   1235 	// Query with different sized buffers, len("u_uniformWithALongName") == 22
   1236 
   1237 	{
   1238 		static const struct
   1239 		{
   1240 			const char*	description;
   1241 			int			querySize;
   1242 			bool		returnLength;
   1243 		} querySizes[] =
   1244 		{
   1245 			{ "Query to larger buffer",										24,		true	},
   1246 			{ "Query to buffer the same size",								23,		true	},
   1247 			{ "Query to one byte too small buffer",							22,		true	},
   1248 			{ "Query to one byte buffer",									1,		true	},
   1249 			{ "Query to zero sized buffer",									0,		true	},
   1250 			{ "Query to one byte too small buffer, null length argument",	22,		false	},
   1251 			{ "Query to one byte buffer, null length argument",				1,		false	},
   1252 			{ "Query to zero sized buffer, null length argument",			0,		false	},
   1253 		};
   1254 
   1255 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(querySizes); ++ndx)
   1256 		{
   1257 			const tcu::ScopedLogSection			section				(m_testCtx.getLog(), "Query", querySizes[ndx].description);
   1258 			const int							uniformNameLen		= 22;
   1259 			const int							expectedWriteLen	= (querySizes[ndx].querySize != 0) ? (de::min(uniformNameLen, (querySizes[ndx].querySize - 1))) : (0);
   1260 			char								buffer				[26];
   1261 			glw::GLsizei						written				= -1;
   1262 
   1263 			// One byte for guard
   1264 			DE_ASSERT((int)sizeof(buffer) > querySizes[ndx].querySize);
   1265 
   1266 			deMemset(buffer, 'x', sizeof(buffer));
   1267 
   1268 			if (querySizes[ndx].querySize)
   1269 				m_testCtx.getLog()
   1270 					<< tcu::TestLog::Message
   1271 					<< "Querying uniform name to a buffer of size " << querySizes[ndx].querySize
   1272 					<< ", expecting query to write " << expectedWriteLen << " bytes followed by a null terminator"
   1273 					<< tcu::TestLog::EndMessage;
   1274 			else
   1275 				m_testCtx.getLog()
   1276 					<< tcu::TestLog::Message
   1277 					<< "Querying uniform name to a buffer of size " << querySizes[ndx].querySize
   1278 					<< ", expecting query to write 0 bytes"
   1279 					<< tcu::TestLog::EndMessage;
   1280 
   1281 			gl.getProgramResourceName(program.getProgram(), GL_UNIFORM, uniformIndex, querySizes[ndx].querySize, (querySizes[ndx].returnLength) ? (&written) : (DE_NULL), buffer);
   1282 			GLU_EXPECT_NO_ERROR(gl.getError(), "query resource name");
   1283 
   1284 			if (querySizes[ndx].returnLength && written != expectedWriteLen)
   1285 			{
   1286 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected write length of " << expectedWriteLen << ", got " << written << tcu::TestLog::EndMessage;
   1287 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected write lenght");
   1288 			}
   1289 			else if (querySizes[ndx].querySize != 0 && buffer[expectedWriteLen] != 0)
   1290 			{
   1291 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected null terminator at " << expectedWriteLen << ", got dec=" << (int)buffer[expectedWriteLen] << tcu::TestLog::EndMessage;
   1292 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Missing null terminator");
   1293 			}
   1294 			else if (querySizes[ndx].querySize != 0 && buffer[expectedWriteLen+1] != 'x')
   1295 			{
   1296 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, guard at index " << (expectedWriteLen+1) << " was modified, got dec=" << (int)buffer[expectedWriteLen+1] << tcu::TestLog::EndMessage;
   1297 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Wrote over buffer size");
   1298 			}
   1299 			else if (querySizes[ndx].querySize == 0 && buffer[0] != 'x')
   1300 			{
   1301 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, buffer size was 0 but buffer contents were modified. At index 0 got dec=" << (int)buffer[0] << tcu::TestLog::EndMessage;
   1302 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer contents were modified");
   1303 			}
   1304 		}
   1305 	}
   1306 
   1307 	return STOP;
   1308 }
   1309 
   1310 class ResourceQueryBufferLimitCase : public TestCase
   1311 {
   1312 public:
   1313 					ResourceQueryBufferLimitCase	(Context& context, const char* name, const char* description);
   1314 					~ResourceQueryBufferLimitCase	(void);
   1315 
   1316 private:
   1317 	IterateResult	iterate							(void);
   1318 };
   1319 
   1320 ResourceQueryBufferLimitCase::ResourceQueryBufferLimitCase (Context& context, const char* name, const char* description)
   1321 	: TestCase(context, name, description)
   1322 {
   1323 }
   1324 
   1325 ResourceQueryBufferLimitCase::~ResourceQueryBufferLimitCase (void)
   1326 {
   1327 }
   1328 
   1329 ResourceQueryBufferLimitCase::IterateResult ResourceQueryBufferLimitCase::iterate (void)
   1330 {
   1331 	static const char* const computeSource =	"#version 310 es\n"
   1332 												"layout(local_size_x = 1) in;\n"
   1333 												"uniform highp int u_uniform;\n"
   1334 												"writeonly buffer OutputBufferBlock { highp int b_output_int; };\n"
   1335 												"void main ()\n"
   1336 												"{\n"
   1337 												"	b_output_int = u_uniform;\n"
   1338 												"}\n";
   1339 
   1340 	const glw::Functions&		gl				= m_context.getRenderContext().getFunctions();
   1341 	const glu::ShaderProgram	program			(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(computeSource));
   1342 	glw::GLuint					uniformIndex;
   1343 
   1344 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1345 
   1346 	// Log program
   1347 	{
   1348 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Program", "Program");
   1349 
   1350 		m_testCtx.getLog() << program;
   1351 		if (!program.isOk())
   1352 			throw tcu::TestError("could not build program");
   1353 	}
   1354 
   1355 	uniformIndex = gl.getProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_uniform");
   1356 	GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
   1357 
   1358 	if (uniformIndex == GL_INVALID_INDEX)
   1359 		throw tcu::TestError("Uniform u_uniform resource index was GL_INVALID_INDEX");
   1360 
   1361 	// Query uniform properties
   1362 
   1363 	{
   1364 		static const struct
   1365 		{
   1366 			const char*	description;
   1367 			int			numProps;
   1368 			int			bufferSize;
   1369 			bool		returnLength;
   1370 		} querySizes[] =
   1371 		{
   1372 			{ "Query to a larger buffer",							2, 3, true	},
   1373 			{ "Query to too small a buffer",						3, 2, true	},
   1374 			{ "Query to zero sized buffer",							3, 0, true	},
   1375 			{ "Query to a larger buffer, null length argument",		2, 3, false	},
   1376 			{ "Query to too small a buffer, null length argument",	3, 2, false	},
   1377 			{ "Query to zero sized buffer, null length argument",	3, 0, false	},
   1378 		};
   1379 
   1380 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(querySizes); ++ndx)
   1381 		{
   1382 			const tcu::ScopedLogSection		section				(m_testCtx.getLog(), "QueryToLarger", querySizes[ndx].description);
   1383 			const glw::GLenum				props[]				= { GL_LOCATION, GL_LOCATION, GL_LOCATION };
   1384 			const int						expectedWriteLen	= de::min(querySizes[ndx].bufferSize, querySizes[ndx].numProps);
   1385 			int								params[]			= { 255, 255, 255, 255 };
   1386 			glw::GLsizei					written				= -1;
   1387 
   1388 			DE_ASSERT(querySizes[ndx].numProps <= DE_LENGTH_OF_ARRAY(props));
   1389 			DE_ASSERT(querySizes[ndx].bufferSize < DE_LENGTH_OF_ARRAY(params)); // leave at least one element for overflow detection
   1390 
   1391 			m_testCtx.getLog()
   1392 				<< tcu::TestLog::Message
   1393 				<< "Querying " << querySizes[ndx].numProps << " uniform prop(s) to a buffer with size " << querySizes[ndx].bufferSize << ". Expecting query to return " << expectedWriteLen << " prop(s)"
   1394 				<< tcu::TestLog::EndMessage;
   1395 
   1396 			gl.getProgramResourceiv(program.getProgram(), GL_UNIFORM, uniformIndex, querySizes[ndx].numProps, props, querySizes[ndx].bufferSize, (querySizes[ndx].returnLength) ? (&written) : (DE_NULL), params);
   1397 			GLU_EXPECT_NO_ERROR(gl.getError(), "query program resources");
   1398 
   1399 			if (querySizes[ndx].returnLength && written != expectedWriteLen)
   1400 			{
   1401 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected write length of " << expectedWriteLen << ", got " << written << tcu::TestLog::EndMessage;
   1402 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected write lenght");
   1403 			}
   1404 			else if (params[expectedWriteLen] != 255)
   1405 			{
   1406 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, guard at index " << (expectedWriteLen) << " was modified. Was 255 before call, got dec=" << params[expectedWriteLen] << tcu::TestLog::EndMessage;
   1407 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Wrote over buffer size");
   1408 			}
   1409 		}
   1410 	}
   1411 
   1412 	return STOP;
   1413 }
   1414 
   1415 class InterfaceBlockBaseCase : public TestCase
   1416 {
   1417 public:
   1418 	enum CaseType
   1419 	{
   1420 		CASE_NAMED_BLOCK = 0,
   1421 		CASE_UNNAMED_BLOCK,
   1422 		CASE_BLOCK_ARRAY,
   1423 
   1424 		CASE_LAST
   1425 	};
   1426 
   1427 											InterfaceBlockBaseCase		(Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType);
   1428 											~InterfaceBlockBaseCase		(void);
   1429 
   1430 private:
   1431 	void									init						(void);
   1432 	void									deinit						(void);
   1433 
   1434 protected:
   1435 	const glu::Storage						m_storage;
   1436 	const CaseType							m_caseType;
   1437 	ProgramInterfaceDefinition::Program*	m_program;
   1438 };
   1439 
   1440 InterfaceBlockBaseCase::InterfaceBlockBaseCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType)
   1441 	: TestCase		(context, name, description)
   1442 	, m_storage		(storage)
   1443 	, m_caseType	(caseType)
   1444 	, m_program		(DE_NULL)
   1445 {
   1446 	DE_ASSERT(storage == glu::STORAGE_UNIFORM || storage == glu::STORAGE_BUFFER);
   1447 }
   1448 
   1449 InterfaceBlockBaseCase::~InterfaceBlockBaseCase (void)
   1450 {
   1451 	deinit();
   1452 }
   1453 
   1454 void InterfaceBlockBaseCase::init (void)
   1455 {
   1456 	ProgramInterfaceDefinition::Shader* shader;
   1457 
   1458 	m_program = new ProgramInterfaceDefinition::Program();
   1459 	shader = m_program->addShader(glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES);
   1460 
   1461 	// PrecedingInterface
   1462 	{
   1463 		glu::InterfaceBlock precedingInterfaceBlock;
   1464 
   1465 		precedingInterfaceBlock.interfaceName	= "PrecedingInterface";
   1466 		precedingInterfaceBlock.layout.binding	= 0;
   1467 		precedingInterfaceBlock.storage			= m_storage;
   1468 		precedingInterfaceBlock.instanceName	= "precedingInstance";
   1469 
   1470 		precedingInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "precedingMember"));
   1471 
   1472 		// Unsized array type
   1473 		if (m_storage == glu::STORAGE_BUFFER)
   1474 			precedingInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), glu::VarType::UNSIZED_ARRAY), "precedingMemberUnsizedArray"));
   1475 		else
   1476 			precedingInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), 2), "precedingMemberArray"));
   1477 
   1478 		shader->getDefaultBlock().interfaceBlocks.push_back(precedingInterfaceBlock);
   1479 	}
   1480 
   1481 	// TargetInterface
   1482 	{
   1483 		glu::InterfaceBlock targetInterfaceBlock;
   1484 
   1485 		targetInterfaceBlock.interfaceName	= "TargetInterface";
   1486 		targetInterfaceBlock.layout.binding	= 1;
   1487 		targetInterfaceBlock.storage		= m_storage;
   1488 
   1489 		if (m_caseType == CASE_UNNAMED_BLOCK)
   1490 			targetInterfaceBlock.instanceName = "";
   1491 		else
   1492 			targetInterfaceBlock.instanceName = "targetInstance";
   1493 
   1494 		if (m_caseType == CASE_BLOCK_ARRAY)
   1495 			targetInterfaceBlock.dimensions.push_back(2);
   1496 
   1497 		// Basic type
   1498 		{
   1499 			targetInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "blockMemberBasic"));
   1500 		}
   1501 
   1502 		// Array type
   1503 		{
   1504 			targetInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), 3), "blockMemberArray"));
   1505 		}
   1506 
   1507 		// Struct type
   1508 		{
   1509 			glu::StructType* structPtr = new glu::StructType("StructType");
   1510 			structPtr->addMember("structMemberBasic", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP));
   1511 			structPtr->addMember("structMemberArray", glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), 2));
   1512 
   1513 			targetInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(structPtr), 2), "blockMemberStruct"));
   1514 		}
   1515 
   1516 		// Unsized array type
   1517 		if (m_storage == glu::STORAGE_BUFFER)
   1518 			targetInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), glu::VarType::UNSIZED_ARRAY), "blockMemberUnsizedArray"));
   1519 
   1520 		shader->getDefaultBlock().interfaceBlocks.push_back(targetInterfaceBlock);
   1521 	}
   1522 
   1523 	// TrailingInterface
   1524 	{
   1525 		glu::InterfaceBlock trailingInterfaceBlock;
   1526 
   1527 		trailingInterfaceBlock.interfaceName	= "TrailingInterface";
   1528 		trailingInterfaceBlock.layout.binding	= 3;
   1529 		trailingInterfaceBlock.storage			= m_storage;
   1530 		trailingInterfaceBlock.instanceName		= "trailingInstance";
   1531 		trailingInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "trailingMember"));
   1532 
   1533 		shader->getDefaultBlock().interfaceBlocks.push_back(trailingInterfaceBlock);
   1534 	}
   1535 
   1536 	DE_ASSERT(m_program->isValid());
   1537 }
   1538 
   1539 void InterfaceBlockBaseCase::deinit (void)
   1540 {
   1541 	delete m_program;
   1542 	m_program = DE_NULL;
   1543 }
   1544 
   1545 class InterfaceBlockActiveVariablesTestCase : public InterfaceBlockBaseCase
   1546 {
   1547 public:
   1548 											InterfaceBlockActiveVariablesTestCase	(Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType);
   1549 
   1550 private:
   1551 	IterateResult							iterate									(void);
   1552 };
   1553 
   1554 InterfaceBlockActiveVariablesTestCase::InterfaceBlockActiveVariablesTestCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType)
   1555 	: InterfaceBlockBaseCase(context, name, description, storage, caseType)
   1556 {
   1557 }
   1558 
   1559 InterfaceBlockActiveVariablesTestCase::IterateResult InterfaceBlockActiveVariablesTestCase::iterate (void)
   1560 {
   1561 	const ProgramInterface			programInterface				= (m_storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) :
   1562 																	  (m_storage == glu::STORAGE_BUFFER) ? (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK) :
   1563 																	  (PROGRAMINTERFACE_LAST);
   1564 	const glw::GLenum				programGLInterfaceValue			= getProgramInterfaceGLEnum(programInterface);
   1565 	const glw::GLenum				programMemberInterfaceValue		= (m_storage == glu::STORAGE_UNIFORM) ? (GL_UNIFORM) :
   1566 																	  (m_storage == glu::STORAGE_BUFFER) ? (GL_BUFFER_VARIABLE) :
   1567 																	  (0);
   1568 	const std::vector<std::string>	blockNames						= getProgramInterfaceResourceList(m_program, programInterface);
   1569 	glu::ShaderProgram				program							(m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
   1570 	int								expectedMaxNumActiveVariables	= 0;
   1571 
   1572 	DE_ASSERT(programInterface != PROGRAMINTERFACE_LAST);
   1573 
   1574 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1575 	checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
   1576 
   1577 	// Verify all blocks
   1578 
   1579 	for (int blockNdx = 0; blockNdx < (int)blockNames.size(); ++blockNdx)
   1580 	{
   1581 		const tcu::ScopedLogSection section				(m_testCtx.getLog(), "Block", "Block \"" + blockNames[blockNdx] + "\"");
   1582 		const glw::Functions&		gl					= m_context.getRenderContext().getFunctions();
   1583 		const glw::GLuint			resourceNdx			= gl.getProgramResourceIndex(program.getProgram(), programGLInterfaceValue, blockNames[blockNdx].c_str());
   1584 		glw::GLint					numActiveResources;
   1585 		std::vector<std::string>	activeResourceNames;
   1586 
   1587 		GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
   1588 
   1589 		if (resourceNdx == GL_INVALID_INDEX)
   1590 		{
   1591 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, getProgramResourceIndex returned GL_INVALID_INDEX for \"" << blockNames[blockNdx] << "\"" << tcu::TestLog::EndMessage;
   1592 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Resource not found");
   1593 			continue;
   1594 		}
   1595 
   1596 		// query block information
   1597 
   1598 		{
   1599 			const glw::GLenum	props[]			= { GL_NUM_ACTIVE_VARIABLES };
   1600 			glw::GLint			retBuffer[2]	= { -1, -1 };
   1601 			glw::GLint			written			= -1;
   1602 
   1603 			gl.getProgramResourceiv(program.getProgram(), programGLInterfaceValue, resourceNdx, DE_LENGTH_OF_ARRAY(props), props, 1, &written, retBuffer);
   1604 			GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_NUM_ACTIVE_VARIABLES");
   1605 
   1606 			numActiveResources = retBuffer[0];
   1607 			expectedMaxNumActiveVariables = de::max(expectedMaxNumActiveVariables, numActiveResources);
   1608 			m_testCtx.getLog() << tcu::TestLog::Message << "NUM_ACTIVE_VARIABLES = " << numActiveResources << tcu::TestLog::EndMessage;
   1609 
   1610 			if (written == -1 || retBuffer[0] == -1)
   1611 			{
   1612 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, Query for NUM_ACTIVE_VARIABLES did not return a value" << tcu::TestLog::EndMessage;
   1613 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for NUM_ACTIVE_VARIABLES failed");
   1614 				continue;
   1615 			}
   1616 			else if (retBuffer[1] != -1)
   1617 			{
   1618 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, Query for NUM_ACTIVE_VARIABLES returned too many values" << tcu::TestLog::EndMessage;
   1619 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for NUM_ACTIVE_VARIABLES returned too many values");
   1620 				continue;
   1621 			}
   1622 			else if (retBuffer[0] < 0)
   1623 			{
   1624 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, NUM_ACTIVE_VARIABLES < 0" << tcu::TestLog::EndMessage;
   1625 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "NUM_ACTIVE_VARIABLES < 0");
   1626 				continue;
   1627 			}
   1628 		}
   1629 
   1630 		// query block variable information
   1631 
   1632 		{
   1633 			const glw::GLenum			props[]					= { GL_ACTIVE_VARIABLES };
   1634 			std::vector<glw::GLint>		activeVariableIndices	(numActiveResources + 1, -1);	// Allocate one extra trailing to detect wrong write lengths
   1635 			glw::GLint					written					= -1;
   1636 
   1637 			gl.getProgramResourceiv(program.getProgram(), programGLInterfaceValue, resourceNdx, DE_LENGTH_OF_ARRAY(props), props, (glw::GLsizei)activeVariableIndices.size(), &written, &activeVariableIndices[0]);
   1638 			GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_ACTIVE_VARIABLES");
   1639 
   1640 			if (written == -1)
   1641 			{
   1642 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, Query for GL_ACTIVE_VARIABLES did not return any values" << tcu::TestLog::EndMessage;
   1643 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for GL_ACTIVE_VARIABLES failed");
   1644 				continue;
   1645 			}
   1646 			else if (written != numActiveResources)
   1647 			{
   1648 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, Query for GL_ACTIVE_VARIABLES did not return NUM_ACTIVE_VARIABLES values" << tcu::TestLog::EndMessage;
   1649 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for GL_ACTIVE_VARIABLES returned invalid number of values");
   1650 				continue;
   1651 			}
   1652 			else if (activeVariableIndices.back() != -1)
   1653 			{
   1654 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, GL_ACTIVE_VARIABLES query return buffer trailing guard value was modified, getProgramResourceiv returned more than NUM_ACTIVE_VARIABLES values" << tcu::TestLog::EndMessage;
   1655 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for GL_ACTIVE_VARIABLES returned too many values");
   1656 				continue;
   1657 			}
   1658 
   1659 			// log indices
   1660 			{
   1661 				tcu::MessageBuilder builder(&m_testCtx.getLog());
   1662 
   1663 				builder << "Active variable indices: {";
   1664 				for (int varNdx = 0; varNdx < numActiveResources; ++varNdx)
   1665 				{
   1666 					if (varNdx)
   1667 						builder << ", ";
   1668 					builder << activeVariableIndices[varNdx];
   1669 				}
   1670 				builder << "}" << tcu::TestLog::EndMessage;
   1671 			}
   1672 
   1673 			// collect names
   1674 
   1675 			activeResourceNames.resize(numActiveResources);
   1676 
   1677 			for (int varNdx = 0; varNdx < numActiveResources; ++varNdx)
   1678 			{
   1679 				const glw::GLenum	nameProp	= GL_NAME_LENGTH;
   1680 				glw::GLint			nameLength	= -1;
   1681 				std::vector<char>	nameBuffer;
   1682 
   1683 				written = -1;
   1684 				gl.getProgramResourceiv(program.getProgram(), programMemberInterfaceValue, activeVariableIndices[varNdx], 1, &nameProp, 1, &written, &nameLength);
   1685 				GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_NAME_LENGTH");
   1686 
   1687 				if (nameLength <= 0 || written <= 0)
   1688 				{
   1689 					m_testCtx.getLog() << tcu::TestLog::Message << "Error, GL_NAME_LENGTH query failed" << tcu::TestLog::EndMessage;
   1690 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "GL_NAME_LENGTH query failed");
   1691 					continue;
   1692 				}
   1693 
   1694 				nameBuffer.resize(nameLength + 2, 'X'); // allocate more than required
   1695 				written = -1;
   1696 				gl.getProgramResourceName(program.getProgram(), programMemberInterfaceValue, activeVariableIndices[varNdx], nameLength+1, &written, &nameBuffer[0]);
   1697 				GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceName");
   1698 
   1699 				if (written <= 0)
   1700 				{
   1701 					m_testCtx.getLog() << tcu::TestLog::Message << "Error, name query failed, no data written" << tcu::TestLog::EndMessage;
   1702 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "name query failed");
   1703 					continue;
   1704 				}
   1705 				else if (written > nameLength)
   1706 				{
   1707 					m_testCtx.getLog() << tcu::TestLog::Message << "Error, name query failed, query returned too much data" << tcu::TestLog::EndMessage;
   1708 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "name query failed");
   1709 					continue;
   1710 				}
   1711 
   1712 				activeResourceNames[varNdx] = std::string(&nameBuffer[0], written);
   1713 			}
   1714 
   1715 			// log collected names
   1716 			{
   1717 				tcu::MessageBuilder builder(&m_testCtx.getLog());
   1718 
   1719 				builder << "Active variables:\n";
   1720 				for (int varNdx = 0; varNdx < numActiveResources; ++varNdx)
   1721 					builder << "\t" << activeResourceNames[varNdx] << "\n";
   1722 				builder << tcu::TestLog::EndMessage;
   1723 			}
   1724 		}
   1725 
   1726 		// verify names
   1727 		{
   1728 			glu::InterfaceBlock*		block		= DE_NULL;
   1729 			const std::string			blockName	= glu::parseVariableName(blockNames[blockNdx].c_str());
   1730 			std::vector<std::string>	referenceList;
   1731 
   1732 			for (int interfaceNdx = 0; interfaceNdx < (int)m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
   1733 			{
   1734 				if (m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx].interfaceName == blockName)
   1735 				{
   1736 					block = &m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx];
   1737 					break;
   1738 				}
   1739 			}
   1740 
   1741 			if (!block)
   1742 				throw tcu::InternalError("could not find block referenced in the reference resource list");
   1743 
   1744 			// generate reference list
   1745 
   1746 			referenceList = getProgramInterfaceBlockMemberResourceList(*block);
   1747 			{
   1748 				tcu::MessageBuilder builder(&m_testCtx.getLog());
   1749 
   1750 				builder << "Expected variable names:\n";
   1751 				for (int varNdx = 0; varNdx < (int)referenceList.size(); ++varNdx)
   1752 					builder << "\t" << referenceList[varNdx] << "\n";
   1753 				builder << tcu::TestLog::EndMessage;
   1754 			}
   1755 
   1756 			// compare lists
   1757 			{
   1758 				bool listsIdentical = true;
   1759 
   1760 				for (int ndx = 0; ndx < (int)referenceList.size(); ++ndx)
   1761 				{
   1762 					if (!de::contains(activeResourceNames.begin(), activeResourceNames.end(), referenceList[ndx]))
   1763 					{
   1764 						m_testCtx.getLog() << tcu::TestLog::Message << "Error, variable name list did not contain active variable " << referenceList[ndx] << tcu::TestLog::EndMessage;
   1765 						listsIdentical = false;
   1766 					}
   1767 				}
   1768 
   1769 				for (int ndx = 0; ndx < (int)activeResourceNames.size(); ++ndx)
   1770 				{
   1771 					if (!de::contains(referenceList.begin(), referenceList.end(), activeResourceNames[ndx]))
   1772 					{
   1773 						m_testCtx.getLog() << tcu::TestLog::Message << "Error, variable name list contains unexpected resource \"" << activeResourceNames[ndx] << "\"" << tcu::TestLog::EndMessage;
   1774 						listsIdentical = false;
   1775 					}
   1776 				}
   1777 
   1778 				if (listsIdentical)
   1779 					m_testCtx.getLog() << tcu::TestLog::Message << "Lists identical" << tcu::TestLog::EndMessage;
   1780 				else
   1781 				{
   1782 					m_testCtx.getLog() << tcu::TestLog::Message << "Error, invalid active variable list" << tcu::TestLog::EndMessage;
   1783 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid active variable list");
   1784 					continue;
   1785 				}
   1786 			}
   1787 		}
   1788 	}
   1789 
   1790 	// Max num active variables
   1791 	{
   1792 		const tcu::ScopedLogSection	section					(m_testCtx.getLog(), "MaxNumActiveVariables", "MAX_NUM_ACTIVE_VARIABLES");
   1793 		const glw::Functions&		gl						= m_context.getRenderContext().getFunctions();
   1794 		glw::GLint					maxNumActiveVariables	= -1;
   1795 
   1796 		gl.getProgramInterfaceiv(program.getProgram(), programGLInterfaceValue, GL_MAX_NUM_ACTIVE_VARIABLES, &maxNumActiveVariables);
   1797 		GLU_EXPECT_NO_ERROR(gl.getError(), "query MAX_NUM_ACTIVE_VARIABLES");
   1798 
   1799 		m_testCtx.getLog() << tcu::TestLog::Message << "MAX_NUM_ACTIVE_VARIABLES = " << maxNumActiveVariables << tcu::TestLog::EndMessage;
   1800 
   1801 		if (expectedMaxNumActiveVariables != maxNumActiveVariables)
   1802 		{
   1803 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected MAX_NUM_ACTIVE_VARIABLES" << tcu::TestLog::EndMessage;
   1804 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "unexpected MAX_NUM_ACTIVE_VARIABLES");
   1805 		}
   1806 		else
   1807 			m_testCtx.getLog() << tcu::TestLog::Message << "MAX_NUM_ACTIVE_VARIABLES valid" << tcu::TestLog::EndMessage;
   1808 	}
   1809 
   1810 	return STOP;
   1811 }
   1812 
   1813 class InterfaceBlockDataSizeTestCase : public InterfaceBlockBaseCase
   1814 {
   1815 public:
   1816 											InterfaceBlockDataSizeTestCase	(Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType);
   1817 
   1818 private:
   1819 	IterateResult							iterate							(void);
   1820 	int										getBlockMinDataSize				(const std::string& blockName) const;
   1821 	int										getBlockMinDataSize				(const glu::InterfaceBlock& block) const;
   1822 };
   1823 
   1824 InterfaceBlockDataSizeTestCase::InterfaceBlockDataSizeTestCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType)
   1825 	: InterfaceBlockBaseCase(context, name, description, storage, caseType)
   1826 {
   1827 }
   1828 
   1829 InterfaceBlockDataSizeTestCase::IterateResult InterfaceBlockDataSizeTestCase::iterate (void)
   1830 {
   1831 	const ProgramInterface			programInterface		= (m_storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) :
   1832 															  (m_storage == glu::STORAGE_BUFFER) ? (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK) :
   1833 															  (PROGRAMINTERFACE_LAST);
   1834 	const glw::GLenum				programGLInterfaceValue	= getProgramInterfaceGLEnum(programInterface);
   1835 	const std::vector<std::string>	blockNames				= getProgramInterfaceResourceList(m_program, programInterface);
   1836 	glu::ShaderProgram				program					(m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
   1837 
   1838 	DE_ASSERT(programInterface != PROGRAMINTERFACE_LAST);
   1839 
   1840 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1841 	checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
   1842 
   1843 	// Verify all blocks
   1844 	for (int blockNdx = 0; blockNdx < (int)blockNames.size(); ++blockNdx)
   1845 	{
   1846 		const tcu::ScopedLogSection section				(m_testCtx.getLog(), "Block", "Block \"" + blockNames[blockNdx] + "\"");
   1847 		const glw::Functions&		gl					= m_context.getRenderContext().getFunctions();
   1848 		const glw::GLuint			resourceNdx			= gl.getProgramResourceIndex(program.getProgram(), programGLInterfaceValue, blockNames[blockNdx].c_str());
   1849 		const int					expectedMinDataSize	= getBlockMinDataSize(blockNames[blockNdx]);
   1850 		glw::GLint					queryDataSize		= -1;
   1851 
   1852 		GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
   1853 
   1854 		if (resourceNdx == GL_INVALID_INDEX)
   1855 		{
   1856 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, getProgramResourceIndex returned GL_INVALID_INDEX for \"" << blockNames[blockNdx] << "\"" << tcu::TestLog::EndMessage;
   1857 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Resource not found");
   1858 			continue;
   1859 		}
   1860 
   1861 		// query
   1862 		{
   1863 			const glw::GLenum prop = GL_BUFFER_DATA_SIZE;
   1864 
   1865 			gl.getProgramResourceiv(program.getProgram(), programGLInterfaceValue, resourceNdx, 1, &prop, 1, DE_NULL, &queryDataSize);
   1866 			GLU_EXPECT_NO_ERROR(gl.getError(), "query resource BUFFER_DATA_SIZE");
   1867 		}
   1868 
   1869 		m_testCtx.getLog()
   1870 			<< tcu::TestLog::Message
   1871 			<< "BUFFER_DATA_SIZE = " << queryDataSize << "\n"
   1872 			<< "Buffer data size with tight packing: " << expectedMinDataSize
   1873 			<< tcu::TestLog::EndMessage;
   1874 
   1875 		if (queryDataSize < expectedMinDataSize)
   1876 		{
   1877 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, buffer size was less than minimum buffer data size" << tcu::TestLog::EndMessage;
   1878 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer data size invalid");
   1879 			continue;
   1880 		}
   1881 		else
   1882 			m_testCtx.getLog() << tcu::TestLog::Message << "Buffer size valid" << tcu::TestLog::EndMessage;
   1883 	}
   1884 
   1885 	return STOP;
   1886 }
   1887 
   1888 int InterfaceBlockDataSizeTestCase::getBlockMinDataSize (const std::string& blockFullName) const
   1889 {
   1890 	const std::string blockName = glu::parseVariableName(blockFullName.c_str());
   1891 
   1892 	for (int interfaceNdx = 0; interfaceNdx < (int)m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
   1893 	{
   1894 		if (m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx].interfaceName == blockName &&
   1895 			m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx].storage == m_storage)
   1896 			return getBlockMinDataSize(m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx]);
   1897 	}
   1898 
   1899 	DE_ASSERT(false);
   1900 	return -1;
   1901 }
   1902 
   1903 class AtomicCounterCase : public TestCase
   1904 {
   1905 public:
   1906 											AtomicCounterCase			(Context& context, const char* name, const char* description);
   1907 											~AtomicCounterCase			(void);
   1908 
   1909 private:
   1910 	void									init						(void);
   1911 	void									deinit						(void);
   1912 
   1913 protected:
   1914 	int										getNumAtomicCounterBuffers	(void) const;
   1915 	int										getMaxNumActiveVariables	(void) const;
   1916 	int										getBufferVariableCount		(int binding) const;
   1917 	int										getBufferMinimumDataSize	(int binding) const;
   1918 
   1919 	ProgramInterfaceDefinition::Program*	m_program;
   1920 };
   1921 
   1922 AtomicCounterCase::AtomicCounterCase (Context& context, const char* name, const char* description)
   1923 	: TestCase	(context, name, description)
   1924 	, m_program	(DE_NULL)
   1925 {
   1926 }
   1927 
   1928 AtomicCounterCase::~AtomicCounterCase (void)
   1929 {
   1930 	deinit();
   1931 }
   1932 
   1933 void AtomicCounterCase::init (void)
   1934 {
   1935 	ProgramInterfaceDefinition::Shader* shader;
   1936 
   1937 	m_program = new ProgramInterfaceDefinition::Program();
   1938 	shader = m_program->addShader(glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES);
   1939 
   1940 	{
   1941 		glu::VariableDeclaration decl(glu::VarType(glu::TYPE_UINT_ATOMIC_COUNTER, glu::PRECISION_LAST), "binding1_counter1", glu::STORAGE_UNIFORM);
   1942 		decl.layout.binding = 1;
   1943 		shader->getDefaultBlock().variables.push_back(decl);
   1944 	}
   1945 	{
   1946 		glu::VariableDeclaration decl(glu::VarType(glu::TYPE_UINT_ATOMIC_COUNTER, glu::PRECISION_LAST), "binding1_counter2", glu::STORAGE_UNIFORM);
   1947 		decl.layout.binding = 1;
   1948 		decl.layout.offset = 8;
   1949 
   1950 		shader->getDefaultBlock().variables.push_back(decl);
   1951 	}
   1952 	{
   1953 		glu::VariableDeclaration decl(glu::VarType(glu::TYPE_UINT_ATOMIC_COUNTER, glu::PRECISION_LAST), "binding2_counter1", glu::STORAGE_UNIFORM);
   1954 		decl.layout.binding = 2;
   1955 		shader->getDefaultBlock().variables.push_back(decl);
   1956 	}
   1957 
   1958 	DE_ASSERT(m_program->isValid());
   1959 }
   1960 
   1961 void AtomicCounterCase::deinit (void)
   1962 {
   1963 	delete m_program;
   1964 	m_program = DE_NULL;
   1965 }
   1966 
   1967 int AtomicCounterCase::getNumAtomicCounterBuffers (void) const
   1968 {
   1969 	std::set<int> buffers;
   1970 
   1971 	for (int ndx = 0; ndx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++ndx)
   1972 	{
   1973 		if (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.isBasicType() &&
   1974 			glu::isDataTypeAtomicCounter(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.getBasicType()))
   1975 		{
   1976 			buffers.insert(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.binding);
   1977 		}
   1978 	}
   1979 
   1980 	return (int)buffers.size();
   1981 }
   1982 
   1983 int AtomicCounterCase::getMaxNumActiveVariables (void) const
   1984 {
   1985 	int					maxVars			= 0;
   1986 	std::map<int,int>	numBufferVars;
   1987 
   1988 	for (int ndx = 0; ndx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++ndx)
   1989 	{
   1990 		if (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.isBasicType() &&
   1991 			glu::isDataTypeAtomicCounter(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.getBasicType()))
   1992 		{
   1993 			const int binding = m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.binding;
   1994 
   1995 			if (numBufferVars.find(binding) == numBufferVars.end())
   1996 				numBufferVars[binding] = 1;
   1997 			else
   1998 				++numBufferVars[binding];
   1999 		}
   2000 	}
   2001 
   2002 	for (std::map<int,int>::const_iterator it = numBufferVars.begin(); it != numBufferVars.end(); ++it)
   2003 		maxVars = de::max(maxVars, it->second);
   2004 
   2005 	return maxVars;
   2006 }
   2007 
   2008 int AtomicCounterCase::getBufferVariableCount (int binding) const
   2009 {
   2010 	int numVars = 0;
   2011 
   2012 	for (int ndx = 0; ndx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++ndx)
   2013 	{
   2014 		if (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.isBasicType() &&
   2015 			glu::isDataTypeAtomicCounter(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.getBasicType()) &&
   2016 			m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.binding == binding)
   2017 			++numVars;
   2018 	}
   2019 
   2020 	return numVars;
   2021 }
   2022 
   2023 int AtomicCounterCase::getBufferMinimumDataSize (int binding) const
   2024 {
   2025 	int minSize			= -1;
   2026 	int currentOffset	= 0;
   2027 
   2028 	for (int ndx = 0; ndx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++ndx)
   2029 	{
   2030 		if (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.isBasicType() &&
   2031 			glu::isDataTypeAtomicCounter(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.getBasicType()) &&
   2032 			m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.binding == binding)
   2033 		{
   2034 			const int thisOffset = (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.offset != -1) ? (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.offset) : (currentOffset);
   2035 			currentOffset = thisOffset + 4;
   2036 
   2037 			minSize = de::max(minSize, thisOffset + 4);
   2038 		}
   2039 	}
   2040 
   2041 	return minSize;
   2042 }
   2043 
   2044 class AtomicCounterResourceListCase : public AtomicCounterCase
   2045 {
   2046 public:
   2047 						AtomicCounterResourceListCase	(Context& context, const char* name, const char* description);
   2048 
   2049 private:
   2050 	IterateResult		iterate							(void);
   2051 };
   2052 
   2053 AtomicCounterResourceListCase::AtomicCounterResourceListCase (Context& context, const char* name, const char* description)
   2054 	: AtomicCounterCase(context, name, description)
   2055 {
   2056 }
   2057 
   2058 AtomicCounterResourceListCase::IterateResult AtomicCounterResourceListCase::iterate (void)
   2059 {
   2060 	const glu::ShaderProgram program(m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
   2061 
   2062 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2063 	checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
   2064 
   2065 	{
   2066 		const tcu::ScopedLogSection		section						(m_testCtx.getLog(), "ActiveResources", "ACTIVE_RESOURCES");
   2067 		const glw::Functions&			gl							= m_context.getRenderContext().getFunctions();
   2068 		glw::GLint						numActiveResources			= -1;
   2069 		const int						numExpectedActiveResources	= 2; // 2 buffer bindings
   2070 
   2071 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying ACTIVE_RESOURCES, expecting " << numExpectedActiveResources << tcu::TestLog::EndMessage;
   2072 
   2073 		gl.getProgramInterfaceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &numActiveResources);
   2074 		GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_ACTIVE_RESOURCES");
   2075 
   2076 		m_testCtx.getLog() << tcu::TestLog::Message << "ACTIVE_RESOURCES = " << numActiveResources << tcu::TestLog::EndMessage;
   2077 
   2078 		if (numActiveResources != numExpectedActiveResources)
   2079 		{
   2080 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected ACTIVE_RESOURCES" << tcu::TestLog::EndMessage;
   2081 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected ACTIVE_RESOURCES");
   2082 		}
   2083 		else
   2084 			m_testCtx.getLog() << tcu::TestLog::Message << "ACTIVE_RESOURCES valid" << tcu::TestLog::EndMessage;
   2085 	}
   2086 
   2087 	return STOP;
   2088 }
   2089 
   2090 class AtomicCounterActiveVariablesCase : public AtomicCounterCase
   2091 {
   2092 public:
   2093 					AtomicCounterActiveVariablesCase	(Context& context, const char* name, const char* description);
   2094 
   2095 private:
   2096 	IterateResult	iterate								(void);
   2097 };
   2098 
   2099 AtomicCounterActiveVariablesCase::AtomicCounterActiveVariablesCase (Context& context, const char* name, const char* description)
   2100 	: AtomicCounterCase(context, name, description)
   2101 {
   2102 }
   2103 
   2104 AtomicCounterActiveVariablesCase::IterateResult AtomicCounterActiveVariablesCase::iterate (void)
   2105 {
   2106 	const glw::Functions&		gl								= m_context.getRenderContext().getFunctions();
   2107 	const glu::ShaderProgram	program							(m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
   2108 	const int					numAtomicBuffers				= getNumAtomicCounterBuffers();
   2109 	const int					expectedMaxNumActiveVariables	= getMaxNumActiveVariables();
   2110 
   2111 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2112 	checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
   2113 
   2114 	// check active variables
   2115 	{
   2116 		const tcu::ScopedLogSection	section						(m_testCtx.getLog(), "Interface", "ATOMIC_COUNTER_BUFFER interface");
   2117 		glw::GLint					queryActiveResources		= -1;
   2118 		glw::GLint					queryMaxNumActiveVariables	= -1;
   2119 
   2120 		gl.getProgramInterfaceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &queryActiveResources);
   2121 		gl.getProgramInterfaceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NUM_ACTIVE_VARIABLES, &queryMaxNumActiveVariables);
   2122 		GLU_EXPECT_NO_ERROR(gl.getError(), "query interface");
   2123 
   2124 		m_testCtx.getLog()
   2125 			<< tcu::TestLog::Message
   2126 			<< "GL_ACTIVE_RESOURCES = " << queryActiveResources << "\n"
   2127 			<< "GL_MAX_NUM_ACTIVE_VARIABLES = " << queryMaxNumActiveVariables << "\n"
   2128 			<< tcu::TestLog::EndMessage;
   2129 
   2130 		if (queryActiveResources != numAtomicBuffers)
   2131 		{
   2132 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected GL_ACTIVE_RESOURCES, expected " << numAtomicBuffers << tcu::TestLog::EndMessage;
   2133 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected GL_ACTIVE_RESOURCES");
   2134 		}
   2135 
   2136 		if (queryMaxNumActiveVariables != expectedMaxNumActiveVariables)
   2137 		{
   2138 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected GL_MAX_NUM_ACTIVE_VARIABLES, expected " << expectedMaxNumActiveVariables << tcu::TestLog::EndMessage;
   2139 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected GL_MAX_NUM_ACTIVE_VARIABLES");
   2140 		}
   2141 	}
   2142 
   2143 	// Check each buffer
   2144 	for (int bufferNdx = 0; bufferNdx < numAtomicBuffers; ++bufferNdx)
   2145 	{
   2146 		const tcu::ScopedLogSection	section				(m_testCtx.getLog(), "Resource", "Resource index " + de::toString(bufferNdx));
   2147 		std::vector<glw::GLint>		activeVariables;
   2148 		std::vector<std::string>	memberNames;
   2149 
   2150 		// Find active variables
   2151 		{
   2152 			const glw::GLenum	numActiveVariablesProp	= GL_NUM_ACTIVE_VARIABLES;
   2153 			const glw::GLenum	activeVariablesProp		= GL_ACTIVE_VARIABLES;
   2154 			glw::GLint			numActiveVariables		= -2;
   2155 			glw::GLint			written					= -1;
   2156 
   2157 			gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, bufferNdx, 1, &numActiveVariablesProp, 1, &written, &numActiveVariables);
   2158 			GLU_EXPECT_NO_ERROR(gl.getError(), "query num active variables");
   2159 
   2160 			if (numActiveVariables <= 0)
   2161 			{
   2162 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected NUM_ACTIVE_VARIABLES: " << numActiveVariables  << tcu::TestLog::EndMessage;
   2163 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected NUM_ACTIVE_VARIABLES");
   2164 				continue;
   2165 			}
   2166 
   2167 			if (written <= 0)
   2168 			{
   2169 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for NUM_ACTIVE_VARIABLES returned no values" << tcu::TestLog::EndMessage;
   2170 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "NUM_ACTIVE_VARIABLES query failed");
   2171 				continue;
   2172 			}
   2173 
   2174 			m_testCtx.getLog() << tcu::TestLog::Message << "GL_NUM_ACTIVE_VARIABLES = " << numActiveVariables << tcu::TestLog::EndMessage;
   2175 
   2176 			written = -1;
   2177 			activeVariables.resize(numActiveVariables + 1, -2);
   2178 
   2179 			gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, bufferNdx, 1, &activeVariablesProp, numActiveVariables, &written, &activeVariables[0]);
   2180 			GLU_EXPECT_NO_ERROR(gl.getError(), "query active variables");
   2181 
   2182 			if (written != numActiveVariables)
   2183 			{
   2184 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, unexpected number of ACTIVE_VARIABLES, NUM_ACTIVE_VARIABLES = " << numActiveVariables << ", query returned " << written << " values" << tcu::TestLog::EndMessage;
   2185 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected ACTIVE_VARIABLES");
   2186 				continue;
   2187 			}
   2188 
   2189 			if (activeVariables.back() != -2)
   2190 			{
   2191 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for ACTIVE_VARIABLES wrote over target buffer bounds" << tcu::TestLog::EndMessage;
   2192 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "ACTIVE_VARIABLES query failed");
   2193 				continue;
   2194 			}
   2195 
   2196 			activeVariables.pop_back();
   2197 		}
   2198 
   2199 		// log indices
   2200 		{
   2201 			tcu::MessageBuilder builder(&m_testCtx.getLog());
   2202 
   2203 			builder << "Active variable indices: {";
   2204 			for (int varNdx = 0; varNdx < (int)activeVariables.size(); ++varNdx)
   2205 			{
   2206 				if (varNdx)
   2207 					builder << ", ";
   2208 				builder << activeVariables[varNdx];
   2209 			}
   2210 			builder << "}" << tcu::TestLog::EndMessage;
   2211 		}
   2212 
   2213 		// collect member names
   2214 		for (int ndx = 0; ndx < (int)activeVariables.size(); ++ndx)
   2215 		{
   2216 			const glw::GLenum	nameLengthProp	= GL_NAME_LENGTH;
   2217 			glw::GLint			nameLength		= -1;
   2218 			glw::GLint			written			= -1;
   2219 			std::vector<char>	nameBuf;
   2220 
   2221 			gl.getProgramResourceiv(program.getProgram(), GL_UNIFORM, activeVariables[ndx], 1, &nameLengthProp, 1, &written, &nameLength);
   2222 			GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer variable name length");
   2223 
   2224 			if (written <= 0 || nameLength == -1)
   2225 			{
   2226 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for GL_NAME_LENGTH returned no values" << tcu::TestLog::EndMessage;
   2227 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "GL_NAME_LENGTH query failed");
   2228 				continue;
   2229 			}
   2230 
   2231 			nameBuf.resize(nameLength + 2, 'X'); // +2 to tolerate potential off-by-ones in some implementations, name queries will check these cases better
   2232 			written = -1;
   2233 
   2234 			gl.getProgramResourceName(program.getProgram(), GL_UNIFORM, activeVariables[ndx], (int)nameBuf.size(), &written, &nameBuf[0]);
   2235 			GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer variable name");
   2236 
   2237 			if (written <= 0)
   2238 			{
   2239 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for resource name returned no name" << tcu::TestLog::EndMessage;
   2240 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Name query failed");
   2241 				continue;
   2242 			}
   2243 
   2244 			memberNames.push_back(std::string(&nameBuf[0], written));
   2245 		}
   2246 
   2247 		// log names
   2248 		{
   2249 			tcu::MessageBuilder builder(&m_testCtx.getLog());
   2250 
   2251 			builder << "Active variables:\n";
   2252 			for (int varNdx = 0; varNdx < (int)memberNames.size(); ++varNdx)
   2253 			{
   2254 				builder << "\t" << memberNames[varNdx] << "\n";
   2255 			}
   2256 			builder << tcu::TestLog::EndMessage;
   2257 		}
   2258 
   2259 		// check names are all in the same buffer
   2260 		{
   2261 			bool bindingsValid = true;
   2262 
   2263 			m_testCtx.getLog() << tcu::TestLog::Message << "Verifying names" << tcu::TestLog::EndMessage;
   2264 
   2265 			for (int nameNdx = 0; nameNdx < (int)memberNames.size(); ++nameNdx)
   2266 			{
   2267 				int prevBinding = -1;
   2268 
   2269 				for (int varNdx = 0; varNdx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++varNdx)
   2270 				{
   2271 					if (m_program->getShaders()[0]->getDefaultBlock().variables[varNdx].name == memberNames[nameNdx])
   2272 					{
   2273 						const int varBinding = m_program->getShaders()[0]->getDefaultBlock().variables[varNdx].layout.binding;
   2274 
   2275 						if (prevBinding == -1 || prevBinding == varBinding)
   2276 							prevBinding = varBinding;
   2277 						else
   2278 							bindingsValid = false;
   2279 					}
   2280 				}
   2281 
   2282 				if (prevBinding == -1)
   2283 				{
   2284 					m_testCtx.getLog() << tcu::TestLog::Message << "Error, could not find variable with name \"" << memberNames[nameNdx] << "\"" << tcu::TestLog::EndMessage;
   2285 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Variable name invalid");
   2286 				}
   2287 				else if (getBufferVariableCount(prevBinding) != (int)memberNames.size())
   2288 				{
   2289 					m_testCtx.getLog()
   2290 						<< tcu::TestLog::Message
   2291 						<< "Error, unexpected variable count for binding " << prevBinding
   2292 						<< ". Expected " << getBufferVariableCount(prevBinding) << ", got " << (int)memberNames.size()
   2293 						<< tcu::TestLog::EndMessage;
   2294 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Variable names invalid");
   2295 				}
   2296 			}
   2297 
   2298 			if (!bindingsValid)
   2299 			{
   2300 				m_testCtx.getLog() << tcu::TestLog::Message << "Error, all resource do not share the same buffer" << tcu::TestLog::EndMessage;
   2301 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Active variables invalid");
   2302 				continue;
   2303 			}
   2304 		}
   2305 	}
   2306 
   2307 	return STOP;
   2308 }
   2309 
   2310 class AtomicCounterBufferBindingCase : public AtomicCounterCase
   2311 {
   2312 public:
   2313 					AtomicCounterBufferBindingCase		(Context& context, const char* name, const char* description);
   2314 
   2315 private:
   2316 	IterateResult	iterate								(void);
   2317 };
   2318 
   2319 AtomicCounterBufferBindingCase::AtomicCounterBufferBindingCase (Context& context, const char* name, const char* description)
   2320 	: AtomicCounterCase(context, name, description)
   2321 {
   2322 }
   2323 
   2324 AtomicCounterBufferBindingCase::IterateResult AtomicCounterBufferBindingCase::iterate (void)
   2325 {
   2326 	const glw::Functions&		gl								= m_context.getRenderContext().getFunctions();
   2327 	const glu::ShaderProgram	program							(m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
   2328 	const int					numAtomicBuffers				= getNumAtomicCounterBuffers();
   2329 
   2330 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2331 	checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
   2332 
   2333 	// check every buffer
   2334 	for (int bufferNdx = 0; bufferNdx < numAtomicBuffers; ++bufferNdx)
   2335 	{
   2336 		const tcu::ScopedLogSection	section				(m_testCtx.getLog(), "Resource", "Resource index " + de::toString(bufferNdx));
   2337 		const glw::GLenum			bufferBindingProp	= GL_BUFFER_BINDING;
   2338 		glw::GLint					bufferBinding		= -1;
   2339 		glw::GLint					written				= -1;
   2340 
   2341 		gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, bufferNdx, 1, &bufferBindingProp, 1, &written, &bufferBinding);
   2342 		GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer binding");
   2343 
   2344 		if (written <= 0)
   2345 		{
   2346 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for BUFFER_BINDING returned no values." << tcu::TestLog::EndMessage;
   2347 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "BUFFER_BINDING query failed");
   2348 		}
   2349 
   2350 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_BUFFER_BINDING = " << bufferBinding << tcu::TestLog::EndMessage;
   2351 
   2352 		// no such buffer binding?
   2353 		if (getBufferVariableCount(bufferBinding) == 0)
   2354 		{
   2355 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, got buffer with BUFFER_BINDING = " << bufferBinding << ", but such buffer does not exist." << tcu::TestLog::EndMessage;
   2356 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected BUFFER_BINDING");
   2357 		}
   2358 	}
   2359 
   2360 	return STOP;
   2361 }
   2362 
   2363 class AtomicCounterBufferDataSizeCase : public AtomicCounterCase
   2364 {
   2365 public:
   2366 					AtomicCounterBufferDataSizeCase		(Context& context, const char* name, const char* description);
   2367 
   2368 private:
   2369 	IterateResult	iterate								(void);
   2370 };
   2371 
   2372 AtomicCounterBufferDataSizeCase::AtomicCounterBufferDataSizeCase (Context& context, const char* name, const char* description)
   2373 	: AtomicCounterCase(context, name, description)
   2374 {
   2375 }
   2376 
   2377 AtomicCounterBufferDataSizeCase::IterateResult AtomicCounterBufferDataSizeCase::iterate (void)
   2378 {
   2379 	const glw::Functions&		gl								= m_context.getRenderContext().getFunctions();
   2380 	const glu::ShaderProgram	program							(m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
   2381 	const int					numAtomicBuffers				= getNumAtomicCounterBuffers();
   2382 
   2383 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2384 	checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
   2385 
   2386 	// check every buffer
   2387 	for (int bufferNdx = 0; bufferNdx < numAtomicBuffers; ++bufferNdx)
   2388 	{
   2389 		const tcu::ScopedLogSection	section				(m_testCtx.getLog(), "Resource", "Resource index " + de::toString(bufferNdx));
   2390 		const glw::GLenum			props[]				= { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE };
   2391 		glw::GLint					values[]			= { -1, -1 };
   2392 		glw::GLint					written				= -1;
   2393 		int							bufferMinDataSize;
   2394 
   2395 		gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, bufferNdx, DE_LENGTH_OF_ARRAY(props), props, DE_LENGTH_OF_ARRAY(values), &written, values);
   2396 		GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer binding");
   2397 
   2398 		if (written != 2)
   2399 		{
   2400 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for (BUFFER_BINDING, BUFFER_DATA_SIZE) returned " << written << " value(s)." << tcu::TestLog::EndMessage;
   2401 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "property query failed");
   2402 			continue;
   2403 		}
   2404 
   2405 		m_testCtx.getLog()
   2406 			<< tcu::TestLog::Message
   2407 			<< "GL_BUFFER_BINDING = " << values[0] << "\n"
   2408 			<< "GL_BUFFER_DATA_SIZE = " << values[1]
   2409 			<< tcu::TestLog::EndMessage;
   2410 
   2411 		bufferMinDataSize = getBufferMinimumDataSize(values[0]);
   2412 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying data size, expected greater than or equal to " << bufferMinDataSize << tcu::TestLog::EndMessage;
   2413 
   2414 		// no such buffer binding?
   2415 		if (bufferMinDataSize == -1)
   2416 		{
   2417 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, got buffer with BUFFER_BINDING = " << values[0] << ", but such buffer does not exist." << tcu::TestLog::EndMessage;
   2418 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected BUFFER_BINDING");
   2419 		}
   2420 		else if (values[1] < bufferMinDataSize)
   2421 		{
   2422 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, got buffer with BUFFER_DATA_SIZE = " << values[1] << ", expected greater than or equal to " << bufferMinDataSize << tcu::TestLog::EndMessage;
   2423 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected BUFFER_BINDING");
   2424 		}
   2425 		else
   2426 			m_testCtx.getLog() << tcu::TestLog::Message << "Data size valid" << tcu::TestLog::EndMessage;
   2427 	}
   2428 
   2429 	return STOP;
   2430 }
   2431 
   2432 class AtomicCounterReferencedByCase : public TestCase
   2433 {
   2434 public:
   2435 											AtomicCounterReferencedByCase	(Context& context, const char* name, const char* description, deUint32 presentStagesMask, deUint32 activeStagesMask);
   2436 											~AtomicCounterReferencedByCase	(void);
   2437 
   2438 private:
   2439 	void									init							(void);
   2440 	void									deinit							(void);
   2441 	IterateResult							iterate							(void);
   2442 
   2443 	const deUint32							m_presentStagesMask;
   2444 	const deUint32							m_activeStagesMask;
   2445 	ProgramInterfaceDefinition::Program*	m_program;
   2446 };
   2447 
   2448 AtomicCounterReferencedByCase::AtomicCounterReferencedByCase (Context& context, const char* name, const char* description, deUint32 presentStagesMask, deUint32 activeStagesMask)
   2449 	: TestCase				(context, name, description)
   2450 	, m_presentStagesMask	(presentStagesMask)
   2451 	, m_activeStagesMask	(activeStagesMask)
   2452 	, m_program				(DE_NULL)
   2453 {
   2454 	DE_ASSERT((activeStagesMask & presentStagesMask) == activeStagesMask);
   2455 }
   2456 
   2457 AtomicCounterReferencedByCase::~AtomicCounterReferencedByCase (void)
   2458 {
   2459 	deinit();
   2460 }
   2461 
   2462 void AtomicCounterReferencedByCase::init (void)
   2463 {
   2464 	glu::VariableDeclaration atomicVar(glu::VarType(glu::TYPE_UINT_ATOMIC_COUNTER, glu::PRECISION_LAST), "targetCounter", glu::STORAGE_UNIFORM);
   2465 
   2466 	atomicVar.layout.binding = 1;
   2467 
   2468 	m_program = new ProgramInterfaceDefinition::Program();
   2469 	m_program->setSeparable(((m_presentStagesMask & (1 << glu::SHADERTYPE_VERTEX)) != 0) != ((m_presentStagesMask & (1 << glu::SHADERTYPE_FRAGMENT)) != 0));
   2470 
   2471 	for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; ++shaderType)
   2472 	{
   2473 		if (m_activeStagesMask & (1 << shaderType))
   2474 			m_program->addShader((glu::ShaderType)shaderType, glu::GLSL_VERSION_310_ES)->getDefaultBlock().variables.push_back(atomicVar);
   2475 		else if (m_presentStagesMask & (1 << shaderType))
   2476 			m_program->addShader((glu::ShaderType)shaderType, glu::GLSL_VERSION_310_ES);
   2477 	}
   2478 
   2479 	DE_ASSERT(m_program->isValid());
   2480 }
   2481 
   2482 void AtomicCounterReferencedByCase::deinit (void)
   2483 {
   2484 	delete m_program;
   2485 	m_program = DE_NULL;
   2486 }
   2487 
   2488 AtomicCounterReferencedByCase::IterateResult AtomicCounterReferencedByCase::iterate (void)
   2489 {
   2490 	static const struct
   2491 	{
   2492 		glw::GLenum		propName;
   2493 		glu::ShaderType	shaderType;
   2494 	} targetProps[] =
   2495 	{
   2496 		{ GL_REFERENCED_BY_VERTEX_SHADER,	glu::SHADERTYPE_VERTEX		},
   2497 		{ GL_REFERENCED_BY_FRAGMENT_SHADER,	glu::SHADERTYPE_FRAGMENT	},
   2498 		{ GL_REFERENCED_BY_COMPUTE_SHADER,	glu::SHADERTYPE_COMPUTE		},
   2499 	};
   2500 
   2501 	const glw::Functions&		gl								= m_context.getRenderContext().getFunctions();
   2502 	const glu::ShaderProgram	program							(m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
   2503 
   2504 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2505 	checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
   2506 
   2507 	// check props
   2508 	for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(targetProps); ++propNdx)
   2509 	{
   2510 		const glw::GLenum	prop		= targetProps[propNdx].propName;
   2511 		const glw::GLint	expected	= ((m_activeStagesMask & (1 << targetProps[propNdx].shaderType)) != 0) ? (GL_TRUE) : (GL_FALSE);
   2512 		glw::GLint			value		= -1;
   2513 		glw::GLint			written		= -1;
   2514 
   2515 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying " << glu::getProgramResourcePropertyName(prop) << ", expecting " << glu::getBooleanName(expected) << tcu::TestLog::EndMessage;
   2516 
   2517 		gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, 0, 1, &prop, 1, &written, &value);
   2518 		GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer binding");
   2519 
   2520 		if (written != 1)
   2521 		{
   2522 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for referenced_by_* returned invalid number of values." << tcu::TestLog::EndMessage;
   2523 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "property query failed");
   2524 			continue;
   2525 		}
   2526 
   2527 		m_testCtx.getLog() << tcu::TestLog::Message << glu::getProgramResourcePropertyName(prop) << " = " << glu::getBooleanStr(value) << tcu::TestLog::EndMessage;
   2528 
   2529 		if (value != expected)
   2530 		{
   2531 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected value" << tcu::TestLog::EndMessage;
   2532 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "unexpected property value");
   2533 			continue;
   2534 		}
   2535 	}
   2536 
   2537 	return STOP;
   2538 }
   2539 
   2540 class ProgramInputOutputReferencedByCase : public TestCase
   2541 {
   2542 public:
   2543 	enum CaseType
   2544 	{
   2545 		CASE_VERTEX_FRAGMENT = 0,
   2546 		CASE_SEPARABLE_VERTEX,
   2547 		CASE_SEPARABLE_FRAGMENT,
   2548 
   2549 		CASE_LAST
   2550 	};
   2551 											ProgramInputOutputReferencedByCase	(Context& context, const char* name, const char* description, glu::Storage targetStorage, CaseType caseType);
   2552 											~ProgramInputOutputReferencedByCase	(void);
   2553 
   2554 private:
   2555 	void									init								(void);
   2556 	void									deinit								(void);
   2557 	IterateResult							iterate								(void);
   2558 
   2559 	const CaseType							m_caseType;
   2560 	const glu::Storage						m_targetStorage;
   2561 	ProgramInterfaceDefinition::Program*	m_program;
   2562 };
   2563 
   2564 ProgramInputOutputReferencedByCase::ProgramInputOutputReferencedByCase (Context& context, const char* name, const char* description, glu::Storage targetStorage, CaseType caseType)
   2565 	: TestCase				(context, name, description)
   2566 	, m_caseType			(caseType)
   2567 	, m_targetStorage		(targetStorage)
   2568 	, m_program				(DE_NULL)
   2569 {
   2570 	DE_ASSERT(caseType < CASE_LAST);
   2571 }
   2572 
   2573 ProgramInputOutputReferencedByCase::~ProgramInputOutputReferencedByCase (void)
   2574 {
   2575 	deinit();
   2576 }
   2577 
   2578 void ProgramInputOutputReferencedByCase::init (void)
   2579 {
   2580 	m_program = new ProgramInterfaceDefinition::Program();
   2581 
   2582 	if (m_caseType == CASE_SEPARABLE_VERTEX || m_caseType == CASE_SEPARABLE_FRAGMENT)
   2583 	{
   2584 		const std::string				varName		= (m_targetStorage == glu::STORAGE_IN) ? ("shaderInput") : ("shaderOutput");
   2585 		const glu::VariableDeclaration	targetDecl	(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), varName, m_targetStorage);
   2586 
   2587 		m_program->setSeparable(true);
   2588 		m_program->addShader((m_caseType == CASE_SEPARABLE_VERTEX) ? (glu::SHADERTYPE_VERTEX) : (glu::SHADERTYPE_FRAGMENT), glu::GLSL_VERSION_310_ES)->getDefaultBlock().variables.push_back(targetDecl);
   2589 	}
   2590 	else if (m_caseType == CASE_VERTEX_FRAGMENT)
   2591 	{
   2592 		ProgramInterfaceDefinition::Shader*	vertex		= m_program->addShader(glu::SHADERTYPE_VERTEX, glu::GLSL_VERSION_310_ES);
   2593 		ProgramInterfaceDefinition::Shader*	fragment	= m_program->addShader(glu::SHADERTYPE_FRAGMENT, glu::GLSL_VERSION_310_ES);
   2594 
   2595 		m_program->setSeparable(false);
   2596 
   2597 		vertex->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "shaderInput", glu::STORAGE_IN));
   2598 		vertex->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "shaderOutput", glu::STORAGE_OUT, glu::INTERPOLATION_LAST, glu::Layout(1)));
   2599 
   2600 		fragment->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "shaderInput", glu::STORAGE_IN, glu::INTERPOLATION_LAST, glu::Layout(1)));
   2601 		fragment->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "shaderOutput", glu::STORAGE_OUT, glu::INTERPOLATION_LAST, glu::Layout(0)));
   2602 	}
   2603 	else
   2604 		DE_ASSERT(false);
   2605 
   2606 	DE_ASSERT(m_program->isValid());
   2607 }
   2608 
   2609 void ProgramInputOutputReferencedByCase::deinit (void)
   2610 {
   2611 	delete m_program;
   2612 	m_program = DE_NULL;
   2613 }
   2614 
   2615 ProgramInputOutputReferencedByCase::IterateResult ProgramInputOutputReferencedByCase::iterate (void)
   2616 {
   2617 	static const struct
   2618 	{
   2619 		glw::GLenum		propName;
   2620 		glu::ShaderType	shaderType;
   2621 	} targetProps[] =
   2622 	{
   2623 		{ GL_REFERENCED_BY_VERTEX_SHADER,	glu::SHADERTYPE_VERTEX		},
   2624 		{ GL_REFERENCED_BY_FRAGMENT_SHADER,	glu::SHADERTYPE_FRAGMENT	},
   2625 		{ GL_REFERENCED_BY_COMPUTE_SHADER,	glu::SHADERTYPE_COMPUTE		},
   2626 	};
   2627 
   2628 	const glw::Functions&		gl								= m_context.getRenderContext().getFunctions();
   2629 	const glu::ShaderProgram	program							(m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
   2630 	const std::string			targetResourceName				= (m_targetStorage == glu::STORAGE_IN) ? ("shaderInput") : ("shaderOutput");
   2631 	const glw::GLenum			programGLInterface				= (m_targetStorage == glu::STORAGE_IN) ? (GL_PROGRAM_INPUT) : (GL_PROGRAM_OUTPUT);
   2632 	glw::GLuint					resourceIndex;
   2633 
   2634 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2635 	checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
   2636 
   2637 	// find target resource index
   2638 
   2639 	resourceIndex = gl.getProgramResourceIndex(program.getProgram(), programGLInterface, targetResourceName.c_str());
   2640 	GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
   2641 
   2642 	if (resourceIndex == GL_INVALID_INDEX)
   2643 	{
   2644 		m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for resource \"" << targetResourceName << "\" index returned invalid index." << tcu::TestLog::EndMessage;
   2645 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "could not find target resource");
   2646 		return STOP;
   2647 	}
   2648 
   2649 	// check props
   2650 	for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(targetProps); ++propNdx)
   2651 	{
   2652 		const glw::GLenum	prop			= targetProps[propNdx].propName;
   2653 		const bool			vertexPresent	= (m_caseType == CASE_VERTEX_FRAGMENT) || (m_caseType == CASE_SEPARABLE_VERTEX);
   2654 		const bool			fragmentPresent	= (m_caseType == CASE_VERTEX_FRAGMENT) || (m_caseType == CASE_SEPARABLE_FRAGMENT);
   2655 		const bool			expected		= (m_targetStorage == glu::STORAGE_IN) ?
   2656 												((vertexPresent) ? (targetProps[propNdx].shaderType == glu::SHADERTYPE_VERTEX) : (targetProps[propNdx].shaderType == glu::SHADERTYPE_FRAGMENT)) :
   2657 												((fragmentPresent) ? (targetProps[propNdx].shaderType == glu::SHADERTYPE_FRAGMENT) : (targetProps[propNdx].shaderType == glu::SHADERTYPE_VERTEX));
   2658 		glw::GLint			value			= -1;
   2659 		glw::GLint			written			= -1;
   2660 
   2661 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying " << glu::getProgramResourcePropertyName(prop) << ", expecting " << ((expected) ? ("TRUE") : ("FALSE")) << tcu::TestLog::EndMessage;
   2662 
   2663 		gl.getProgramResourceiv(program.getProgram(), programGLInterface, resourceIndex, 1, &prop, 1, &written, &value);
   2664 		GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer binding");
   2665 
   2666 		if (written != 1)
   2667 		{
   2668 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for referenced_by_* returned invalid number of values." << tcu::TestLog::EndMessage;
   2669 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "property query failed");
   2670 			continue;
   2671 		}
   2672 
   2673 		m_testCtx.getLog() << tcu::TestLog::Message << glu::getProgramResourcePropertyName(prop) << " = " << glu::getBooleanStr(value) << tcu::TestLog::EndMessage;
   2674 
   2675 		if (value != ((expected) ? (GL_TRUE) : (GL_FALSE)))
   2676 		{
   2677 			m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected value" << tcu::TestLog::EndMessage;
   2678 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "unexpected property value");
   2679 			continue;
   2680 		}
   2681 	}
   2682 
   2683 	return STOP;
   2684 }
   2685 
   2686 class FeedbackResourceListTestCase : public ResourceListTestCase
   2687 {
   2688 public:
   2689 											FeedbackResourceListTestCase	(Context& context, const ResourceDefinition::Node::SharedPtr& resource, const char* name);
   2690 											~FeedbackResourceListTestCase	(void);
   2691 
   2692 private:
   2693 	IterateResult							iterate							(void);
   2694 };
   2695 
   2696 FeedbackResourceListTestCase::FeedbackResourceListTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& resource, const char* name)
   2697 	: ResourceListTestCase(context, resource, PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, name)
   2698 {
   2699 }
   2700 
   2701 FeedbackResourceListTestCase::~FeedbackResourceListTestCase (void)
   2702 {
   2703 	deinit();
   2704 }
   2705 
   2706 FeedbackResourceListTestCase::IterateResult FeedbackResourceListTestCase::iterate (void)
   2707 {
   2708 	const de::UniquePtr<ProgramInterfaceDefinition::Program>	programDefinition	(generateProgramDefinitionFromResource(m_targetResource.get()));
   2709 	const glu::ShaderProgram									program				(m_context.getRenderContext(), generateProgramInterfaceProgramSources(programDefinition.get()));
   2710 
   2711 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2712 
   2713 	// Feedback varyings
   2714 	{
   2715 		tcu::MessageBuilder builder(&m_testCtx.getLog());
   2716 		builder << "Transform feedback varyings: {";
   2717 		for (int ndx = 0; ndx < (int)programDefinition->getTransformFeedbackVaryings().size(); ++ndx)
   2718 		{
   2719 			if (ndx)
   2720 				builder << ", ";
   2721 			builder << "\"" << programDefinition->getTransformFeedbackVaryings()[ndx] << "\"";
   2722 		}
   2723 		builder << "}" << tcu::TestLog::EndMessage;
   2724 	}
   2725 
   2726 	checkAndLogProgram(program, programDefinition.get(), m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
   2727 
   2728 	// Check resource list
   2729 	{
   2730 		const tcu::ScopedLogSection	section				(m_testCtx.getLog(), "ResourceList", "Resource list");
   2731 		std::vector<std::string>	resourceList;
   2732 		std::vector<std::string>	expectedResources;
   2733 
   2734 		queryResourceList(resourceList, program.getProgram());
   2735 		expectedResources = getProgramInterfaceResourceList(programDefinition.get(), m_programInterface);
   2736 
   2737 		// verify the list and the expected list match
   2738 
   2739 		if (!verifyResourceList(resourceList, expectedResources))
   2740 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid resource list");
   2741 
   2742 		// verify GetProgramResourceIndex() matches the indices of the list
   2743 
   2744 		if (!verifyResourceIndexQuery(resourceList, expectedResources, program.getProgram()))
   2745 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "GetProgramResourceIndex returned unexpected values");
   2746 
   2747 		// Verify MAX_NAME_LENGTH
   2748 		if (!verifyMaxNameLength(resourceList, program.getProgram()))
   2749 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "MAX_NAME_LENGTH invalid");
   2750 	}
   2751 
   2752 	return STOP;
   2753 }
   2754 
   2755 int InterfaceBlockDataSizeTestCase::getBlockMinDataSize (const glu::InterfaceBlock& block) const
   2756 {
   2757 	int dataSize = 0;
   2758 
   2759 	for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
   2760 		dataSize += getVarTypeSize(block.variables[ndx].varType);
   2761 
   2762 	return dataSize;
   2763 }
   2764 
   2765 static bool isDataTypeLayoutQualified (glu::DataType type)
   2766 {
   2767 	return glu::isDataTypeImage(type) || glu::isDataTypeAtomicCounter(type);
   2768 }
   2769 
   2770 static void generateVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel = 3, bool createTestGroup = true)
   2771 {
   2772 	static const struct
   2773 	{
   2774 		int				level;
   2775 		glu::DataType	dataType;
   2776 	} variableTypes[] =
   2777 	{
   2778 		{ 0,	glu::TYPE_FLOAT			},
   2779 		{ 1,	glu::TYPE_INT			},
   2780 		{ 1,	glu::TYPE_UINT			},
   2781 		{ 1,	glu::TYPE_BOOL			},
   2782 
   2783 		{ 3,	glu::TYPE_FLOAT_VEC2	},
   2784 		{ 1,	glu::TYPE_FLOAT_VEC3	},
   2785 		{ 1,	glu::TYPE_FLOAT_VEC4	},
   2786 
   2787 		{ 3,	glu::TYPE_INT_VEC2		},
   2788 		{ 2,	glu::TYPE_INT_VEC3		},
   2789 		{ 3,	glu::TYPE_INT_VEC4		},
   2790 
   2791 		{ 3,	glu::TYPE_UINT_VEC2		},
   2792 		{ 2,	glu::TYPE_UINT_VEC3		},
   2793 		{ 3,	glu::TYPE_UINT_VEC4		},
   2794 
   2795 		{ 3,	glu::TYPE_BOOL_VEC2		},
   2796 		{ 2,	glu::TYPE_BOOL_VEC3		},
   2797 		{ 3,	glu::TYPE_BOOL_VEC4		},
   2798 
   2799 		{ 2,	glu::TYPE_FLOAT_MAT2	},
   2800 		{ 3,	glu::TYPE_FLOAT_MAT2X3	},
   2801 		{ 3,	glu::TYPE_FLOAT_MAT2X4	},
   2802 		{ 2,	glu::TYPE_FLOAT_MAT3X2	},
   2803 		{ 2,	glu::TYPE_FLOAT_MAT3	},
   2804 		{ 3,	glu::TYPE_FLOAT_MAT3X4	},
   2805 		{ 2,	glu::TYPE_FLOAT_MAT4X2	},
   2806 		{ 3,	glu::TYPE_FLOAT_MAT4X3	},
   2807 		{ 2,	glu::TYPE_FLOAT_MAT4	},
   2808 	};
   2809 
   2810 	tcu::TestCaseGroup* group;
   2811 
   2812 	if (createTestGroup)
   2813 	{
   2814 		group = new tcu::TestCaseGroup(context.getTestContext(), "basic_type", "Basic variable");
   2815 		targetGroup->addChild(group);
   2816 	}
   2817 	else
   2818 		group = targetGroup;
   2819 
   2820 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
   2821 	{
   2822 		if (variableTypes[ndx].level <= expandLevel)
   2823 		{
   2824 			const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].dataType));
   2825 			group->addChild(new ResourceTestCase(context, variable, queryTarget));
   2826 		}
   2827 	}
   2828 }
   2829 
   2830 static void generateOpaqueTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel = 3, bool createTestGroup = true)
   2831 {
   2832 	static const struct
   2833 	{
   2834 		int				level;
   2835 		glu::DataType	dataType;
   2836 	} variableTypes[] =
   2837 	{
   2838 		{ 0,	glu::TYPE_SAMPLER_2D					},
   2839 		{ 2,	glu::TYPE_SAMPLER_CUBE					},
   2840 		{ 1,	glu::TYPE_SAMPLER_2D_ARRAY				},
   2841 		{ 1,	glu::TYPE_SAMPLER_3D					},
   2842 		{ 2,	glu::TYPE_SAMPLER_2D_SHADOW				},
   2843 		{ 3,	glu::TYPE_SAMPLER_CUBE_SHADOW			},
   2844 		{ 3,	glu::TYPE_SAMPLER_2D_ARRAY_SHADOW		},
   2845 		{ 1,	glu::TYPE_INT_SAMPLER_2D				},
   2846 		{ 3,	glu::TYPE_INT_SAMPLER_CUBE				},
   2847 		{ 3,	glu::TYPE_INT_SAMPLER_2D_ARRAY			},
   2848 		{ 3,	glu::TYPE_INT_SAMPLER_3D				},
   2849 		{ 2,	glu::TYPE_UINT_SAMPLER_2D				},
   2850 		{ 3,	glu::TYPE_UINT_SAMPLER_CUBE				},
   2851 		{ 3,	glu::TYPE_UINT_SAMPLER_2D_ARRAY			},
   2852 		{ 3,	glu::TYPE_UINT_SAMPLER_3D				},
   2853 		{ 2,	glu::TYPE_SAMPLER_2D_MULTISAMPLE		},
   2854 		{ 2,	glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE	},
   2855 		{ 3,	glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE	},
   2856 		{ 1,	glu::TYPE_IMAGE_2D						},
   2857 		{ 3,	glu::TYPE_IMAGE_CUBE					},
   2858 		{ 3,	glu::TYPE_IMAGE_2D_ARRAY				},
   2859 		{ 3,	glu::TYPE_IMAGE_3D						},
   2860 		{ 3,	glu::TYPE_INT_IMAGE_2D					},
   2861 		{ 3,	glu::TYPE_INT_IMAGE_CUBE				},
   2862 		{ 1,	glu::TYPE_INT_IMAGE_2D_ARRAY			},
   2863 		{ 3,	glu::TYPE_INT_IMAGE_3D					},
   2864 		{ 2,	glu::TYPE_UINT_IMAGE_2D					},
   2865 		{ 3,	glu::TYPE_UINT_IMAGE_CUBE				},
   2866 		{ 3,	glu::TYPE_UINT_IMAGE_2D_ARRAY			},
   2867 		{ 3,	glu::TYPE_UINT_IMAGE_3D					},
   2868 		{ 1,	glu::TYPE_UINT_ATOMIC_COUNTER			},
   2869 	};
   2870 
   2871 	bool isStructMember = false;
   2872 
   2873 	// Requirements
   2874 	for (const ResourceDefinition::Node* node = parentStructure.get(); node; node = node->getEnclosingNode())
   2875 	{
   2876 		// Don't insert inside a interface block
   2877 		if (node->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK)
   2878 			return;
   2879 
   2880 		isStructMember |= (node->getType() == ResourceDefinition::Node::TYPE_STRUCT_MEMBER);
   2881 	}
   2882 
   2883 	// Add cases
   2884 	{
   2885 		tcu::TestCaseGroup* group;
   2886 
   2887 		if (createTestGroup)
   2888 		{
   2889 			group = new tcu::TestCaseGroup(context.getTestContext(), "opaque_type", "Opaque types");
   2890 			targetGroup->addChild(group);
   2891 		}
   2892 		else
   2893 			group = targetGroup;
   2894 
   2895 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
   2896 		{
   2897 			if (variableTypes[ndx].level > expandLevel)
   2898 				continue;
   2899 
   2900 			// Layout qualifiers are not allowed on struct members
   2901 			if (isDataTypeLayoutQualified(variableTypes[ndx].dataType) && isStructMember)
   2902 				continue;
   2903 
   2904 			{
   2905 				const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].dataType));
   2906 				group->addChild(new ResourceTestCase(context, variable, queryTarget));
   2907 			}
   2908 		}
   2909 	}
   2910 }
   2911 
   2912 static void generateCompoundVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel = 3);
   2913 
   2914 static void generateVariableArrayCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel = 3)
   2915 {
   2916 	if (expandLevel > 0)
   2917 	{
   2918 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(parentStructure));
   2919 		tcu::TestCaseGroup* const					blockGroup		= new tcu::TestCaseGroup(context.getTestContext(), "array", "Arrays");
   2920 
   2921 		targetGroup->addChild(blockGroup);
   2922 
   2923 		// Arrays of basic variables
   2924 		generateVariableCases(context, arrayElement, blockGroup, queryTarget, expandLevel, expandLevel != 1);
   2925 
   2926 		// Arrays of opaque types
   2927 		generateOpaqueTypeCases(context, arrayElement, blockGroup, queryTarget, expandLevel, expandLevel != 1);
   2928 
   2929 		// Arrays of arrays
   2930 		generateVariableArrayCases(context, arrayElement, blockGroup, queryTarget, expandLevel-1);
   2931 
   2932 		// Arrays of structs
   2933 		generateCompoundVariableCases(context, arrayElement, blockGroup, queryTarget, expandLevel-1);
   2934 	}
   2935 }
   2936 
   2937 static void generateCompoundVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel)
   2938 {
   2939 	if (expandLevel > 0)
   2940 	{
   2941 		const ResourceDefinition::Node::SharedPtr	structMember	(new ResourceDefinition::StructMember(parentStructure));
   2942 		tcu::TestCaseGroup* const					blockGroup		= new tcu::TestCaseGroup(context.getTestContext(), "struct", "Structs");
   2943 
   2944 		targetGroup->addChild(blockGroup);
   2945 
   2946 		// Struct containing basic variable
   2947 		generateVariableCases(context, structMember, blockGroup, queryTarget, expandLevel, expandLevel != 1);
   2948 
   2949 		// Struct containing opaque types
   2950 		generateOpaqueTypeCases(context, structMember, blockGroup, queryTarget, expandLevel, expandLevel != 1);
   2951 
   2952 		// Struct containing arrays
   2953 		generateVariableArrayCases(context, structMember, blockGroup, queryTarget, expandLevel-1);
   2954 
   2955 		// Struct containing struct
   2956 		generateCompoundVariableCases(context, structMember, blockGroup, queryTarget, expandLevel-1);
   2957 	}
   2958 }
   2959 
   2960 // Resource list cases
   2961 
   2962 enum BlockFlags
   2963 {
   2964 	BLOCKFLAG_DEFAULT	= 0x01,
   2965 	BLOCKFLAG_NAMED		= 0x02,
   2966 	BLOCKFLAG_UNNAMED	= 0x04,
   2967 	BLOCKFLAG_ARRAY		= 0x08,
   2968 
   2969 	BLOCKFLAG_ALL		= 0x0F
   2970 };
   2971 
   2972 static void generateUniformCaseBlocks (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, deUint32 blockFlags, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup* const))
   2973 {
   2974 	const ResourceDefinition::Node::SharedPtr defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   2975 	const ResourceDefinition::Node::SharedPtr uniform		(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM));
   2976 
   2977 	// .default_block
   2978 	if (blockFlags & BLOCKFLAG_DEFAULT)
   2979 	{
   2980 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "default_block", "Default block");
   2981 		targetGroup->addChild(blockGroup);
   2982 
   2983 		blockContentGenerator(context, uniform, blockGroup);
   2984 	}
   2985 
   2986 	// .named_block
   2987 	if (blockFlags & BLOCKFLAG_NAMED)
   2988 	{
   2989 		const ResourceDefinition::Node::SharedPtr block(new ResourceDefinition::InterfaceBlock(uniform, true));
   2990 
   2991 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "named_block", "Named uniform block");
   2992 		targetGroup->addChild(blockGroup);
   2993 
   2994 		blockContentGenerator(context, block, blockGroup);
   2995 	}
   2996 
   2997 	// .unnamed_block
   2998 	if (blockFlags & BLOCKFLAG_UNNAMED)
   2999 	{
   3000 		const ResourceDefinition::Node::SharedPtr block(new ResourceDefinition::InterfaceBlock(uniform, false));
   3001 
   3002 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "unnamed_block", "Unnamed uniform block");
   3003 		targetGroup->addChild(blockGroup);
   3004 
   3005 		blockContentGenerator(context, block, blockGroup);
   3006 	}
   3007 
   3008 	// .block_array
   3009 	if (blockFlags & BLOCKFLAG_ARRAY)
   3010 	{
   3011 		const ResourceDefinition::Node::SharedPtr arrayElement	(new ResourceDefinition::ArrayElement(uniform));
   3012 		const ResourceDefinition::Node::SharedPtr block			(new ResourceDefinition::InterfaceBlock(arrayElement, true));
   3013 
   3014 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "block_array", "Uniform block array");
   3015 		targetGroup->addChild(blockGroup);
   3016 
   3017 		blockContentGenerator(context, block, blockGroup);
   3018 	}
   3019 }
   3020 
   3021 static void generateBufferBackedResourceListBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, int depth)
   3022 {
   3023 	// variable
   3024 	{
   3025 		const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, glu::TYPE_FLOAT_VEC4));
   3026 		targetGroup->addChild(new ResourceListTestCase(context, variable, interface));
   3027 	}
   3028 
   3029 	// struct
   3030 	if (depth > 0)
   3031 	{
   3032 		const ResourceDefinition::Node::SharedPtr structMember(new ResourceDefinition::StructMember(parentStructure));
   3033 		generateBufferBackedResourceListBlockContentCases(context, structMember, targetGroup, interface, depth - 1);
   3034 	}
   3035 
   3036 	// array
   3037 	if (depth > 0)
   3038 	{
   3039 		const ResourceDefinition::Node::SharedPtr arrayElement(new ResourceDefinition::ArrayElement(parentStructure));
   3040 		generateBufferBackedResourceListBlockContentCases(context, arrayElement, targetGroup, interface, depth - 1);
   3041 	}
   3042 }
   3043 
   3044 static void generateBufferBackedVariableAggregateTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, ProgramResourcePropFlags targetProp, glu::DataType dataType, const std::string& nameSuffix, int depth)
   3045 {
   3046 	// variable
   3047 	{
   3048 		const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, dataType));
   3049 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(interface, targetProp), ("var" + nameSuffix).c_str()));
   3050 	}
   3051 
   3052 	// struct
   3053 	if (depth > 0)
   3054 	{
   3055 		const ResourceDefinition::Node::SharedPtr structMember(new ResourceDefinition::StructMember(parentStructure));
   3056 		generateBufferBackedVariableAggregateTypeCases(context, structMember, targetGroup, interface, targetProp, dataType, "_struct" + nameSuffix, depth - 1);
   3057 	}
   3058 
   3059 	// array
   3060 	if (depth > 0)
   3061 	{
   3062 		const ResourceDefinition::Node::SharedPtr arrayElement(new ResourceDefinition::ArrayElement(parentStructure));
   3063 		generateBufferBackedVariableAggregateTypeCases(context, arrayElement, targetGroup, interface, targetProp, dataType, "_array" + nameSuffix, depth - 1);
   3064 	}
   3065 }
   3066 
   3067 static void generateUniformResourceListBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
   3068 {
   3069 	generateBufferBackedResourceListBlockContentCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_UNIFORM, 4);
   3070 }
   3071 
   3072 static void generateUniformBlockArraySizeContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
   3073 {
   3074 	const ProgramResourceQueryTestTarget	queryTarget			(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_ARRAY_SIZE);
   3075 	const bool								isInterfaceBlock	= (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
   3076 	const bool								namedNonArrayBlock	= isInterfaceBlock																					&&
   3077 																  static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named			&&
   3078 																  parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT;
   3079 
   3080 	if (!isInterfaceBlock || namedNonArrayBlock)
   3081 	{
   3082 		// .types
   3083 		{
   3084 			tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types");
   3085 			targetGroup->addChild(blockGroup);
   3086 
   3087 			generateVariableCases(context, parentStructure, blockGroup, queryTarget, 2, false);
   3088 			generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 2, false);
   3089 		}
   3090 
   3091 		// aggregates
   3092 		{
   3093 			tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types");
   3094 			targetGroup->addChild(blockGroup);
   3095 
   3096 			generateBufferBackedVariableAggregateTypeCases(context, parentStructure, blockGroup, queryTarget.interface, PROGRAMRESOURCEPROP_ARRAY_SIZE, glu::TYPE_FLOAT, "", 3);
   3097 		}
   3098 	}
   3099 	else
   3100 	{
   3101 		// aggregates
   3102 		generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, queryTarget.interface, PROGRAMRESOURCEPROP_ARRAY_SIZE, glu::TYPE_FLOAT, "", 2);
   3103 	}
   3104 }
   3105 
   3106 static void generateBufferBackedArrayStrideTypeAggregateSubCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const std::string& namePrefix, ProgramInterface interface, glu::DataType type, int expandLevel)
   3107 {
   3108 	// case
   3109 	{
   3110 		const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, type));
   3111 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(interface, PROGRAMRESOURCEPROP_ARRAY_STRIDE), namePrefix.c_str()));
   3112 	}
   3113 
   3114 	if (expandLevel > 0)
   3115 	{
   3116 		const ResourceDefinition::Node::SharedPtr	structMember	(new ResourceDefinition::StructMember(parentStructure));
   3117 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(parentStructure));
   3118 
   3119 		// _struct
   3120 		generateBufferBackedArrayStrideTypeAggregateSubCases(context, structMember, targetGroup, namePrefix + "_struct", interface, type, expandLevel - 1);
   3121 
   3122 		// _array
   3123 		generateBufferBackedArrayStrideTypeAggregateSubCases(context, arrayElement, targetGroup, namePrefix + "_array", interface, type, expandLevel - 1);
   3124 	}
   3125 }
   3126 
   3127 static void generateBufferBackedArrayStrideTypeAggregateCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, glu::DataType type, int expandLevel, bool includeBaseCase)
   3128 {
   3129 	const ResourceDefinition::Node::SharedPtr	structMember	(new ResourceDefinition::StructMember(parentStructure));
   3130 	const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(parentStructure));
   3131 	const std::string							namePrefix		= glu::getDataTypeName(type);
   3132 
   3133 	if (expandLevel == 0 || includeBaseCase)
   3134 	{
   3135 		const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, type));
   3136 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(interface, PROGRAMRESOURCEPROP_ARRAY_STRIDE), namePrefix.c_str()));
   3137 	}
   3138 	if (expandLevel >= 1)
   3139 	{
   3140 		// _struct
   3141 		if (!glu::isDataTypeAtomicCounter(type))
   3142 			generateBufferBackedArrayStrideTypeAggregateSubCases(context, structMember, targetGroup, namePrefix + "_struct", interface, type, expandLevel - 1);
   3143 
   3144 		// _array
   3145 		generateBufferBackedArrayStrideTypeAggregateSubCases(context, arrayElement, targetGroup, namePrefix + "_array", interface, type, expandLevel - 1);
   3146 	}
   3147 }
   3148 
   3149 static void generateUniformBlockArrayStrideContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
   3150 {
   3151 	const ProgramResourceQueryTestTarget	queryTarget			(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_ARRAY_STRIDE);
   3152 	const bool								isInterfaceBlock	= (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
   3153 	const bool								namedNonArrayBlock	= isInterfaceBlock																					&&
   3154 																  static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named			&&
   3155 																  parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT;
   3156 
   3157 	if (!isInterfaceBlock || namedNonArrayBlock)
   3158 	{
   3159 		// .types
   3160 		{
   3161 			tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types");
   3162 			targetGroup->addChild(blockGroup);
   3163 
   3164 			generateVariableCases(context, parentStructure, blockGroup, queryTarget, 2, false);
   3165 			generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 2, false);
   3166 		}
   3167 
   3168 		// .aggregates
   3169 		{
   3170 			tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types");
   3171 			targetGroup->addChild(blockGroup);
   3172 
   3173 			// .sampler_2d_*
   3174 			if (!isInterfaceBlock)
   3175 				generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_SAMPLER_2D, 1, false);
   3176 
   3177 			// .atomic_counter_*
   3178 			if (!isInterfaceBlock)
   3179 			{
   3180 				const ResourceDefinition::Node::SharedPtr layout(new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, 0)));
   3181 				generateBufferBackedArrayStrideTypeAggregateCases(context, layout, blockGroup, queryTarget.interface, glu::TYPE_UINT_ATOMIC_COUNTER, 1, false);
   3182 			}
   3183 
   3184 			// .float_*
   3185 			generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_FLOAT, 2, false);
   3186 
   3187 			// .bool_*
   3188 			generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_BOOL, 1, false);
   3189 
   3190 			// .bvec3_*
   3191 			generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_BOOL_VEC3, 2, false);
   3192 
   3193 			// .vec3_*
   3194 			generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_FLOAT_VEC3, 2, false);
   3195 
   3196 			// .ivec2_*
   3197 			generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_INT_VEC3, 2, false);
   3198 		}
   3199 	}
   3200 	else
   3201 	{
   3202 		generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
   3203 		generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 1);
   3204 		generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
   3205 	}
   3206 }
   3207 
   3208 static void generateUniformBlockLocationContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
   3209 {
   3210 	const ProgramResourceQueryTestTarget	queryTarget			(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_LOCATION);
   3211 	const bool								isInterfaceBlock	= (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
   3212 
   3213 	if (!isInterfaceBlock)
   3214 	{
   3215 		generateVariableCases(context, parentStructure, targetGroup, queryTarget, 3);
   3216 		generateOpaqueTypeCases(context, parentStructure, targetGroup, queryTarget, 3);
   3217 		generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 2);
   3218 		generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 2);
   3219 	}
   3220 	else
   3221 		generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1, false);
   3222 }
   3223 
   3224 static void generateUniformBlockBlockIndexContents (Context& context, tcu::TestCaseGroup* const targetGroup)
   3225 {
   3226 	const ResourceDefinition::Node::SharedPtr	program			(new ResourceDefinition::Program());
   3227 	const ResourceDefinition::Node::SharedPtr	shader			(new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES));
   3228 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(shader));
   3229 	const ResourceDefinition::Node::SharedPtr	uniform			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM));
   3230 	const ResourceDefinition::Node::SharedPtr	binding			(new ResourceDefinition::LayoutQualifier(uniform, glu::Layout(-1, 0)));
   3231 
   3232 	// .default_block
   3233 	{
   3234 		const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(uniform, glu::TYPE_FLOAT_VEC4));
   3235 
   3236 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_BLOCK_INDEX), "default_block"));
   3237 	}
   3238 
   3239 	// .named_block
   3240 	{
   3241 		const ResourceDefinition::Node::SharedPtr	buffer		(new ResourceDefinition::InterfaceBlock(binding, true));
   3242 		const ResourceDefinition::Node::SharedPtr	variable	(new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4));
   3243 
   3244 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_BLOCK_INDEX), "named_block"));
   3245 	}
   3246 
   3247 	// .unnamed_block
   3248 	{
   3249 		const ResourceDefinition::Node::SharedPtr	buffer		(new ResourceDefinition::InterfaceBlock(binding, false));
   3250 		const ResourceDefinition::Node::SharedPtr	variable	(new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4));
   3251 
   3252 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_BLOCK_INDEX), "unnamed_block"));
   3253 	}
   3254 
   3255 	// .block_array
   3256 	{
   3257 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(binding));
   3258 		const ResourceDefinition::Node::SharedPtr	buffer			(new ResourceDefinition::InterfaceBlock(arrayElement, true));
   3259 		const ResourceDefinition::Node::SharedPtr	variable		(new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4));
   3260 
   3261 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_BLOCK_INDEX), "block_array"));
   3262 	}
   3263 }
   3264 
   3265 static void generateUniformBlockAtomicCounterBufferIndexContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
   3266 {
   3267 	const ProgramResourceQueryTestTarget	queryTarget			(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_ATOMIC_COUNTER_BUFFER_INDEX);
   3268 	const bool								isInterfaceBlock	= (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
   3269 
   3270 	if (!isInterfaceBlock)
   3271 	{
   3272 		generateVariableCases(context, parentStructure, targetGroup, queryTarget, 3);
   3273 		generateOpaqueTypeCases(context, parentStructure, targetGroup, queryTarget, 3);
   3274 
   3275 		// .array
   3276 		{
   3277 			const ResourceDefinition::Node::SharedPtr	arrayElement		(new ResourceDefinition::ArrayElement(parentStructure));
   3278 			const ResourceDefinition::Node::SharedPtr	arrayArrayElement	(new ResourceDefinition::ArrayElement(arrayElement));
   3279 			const ResourceDefinition::Node::SharedPtr	variable			(new ResourceDefinition::Variable(arrayElement, glu::TYPE_UINT_ATOMIC_COUNTER));
   3280 			const ResourceDefinition::Node::SharedPtr	elementvariable		(new ResourceDefinition::Variable(arrayArrayElement, glu::TYPE_UINT_ATOMIC_COUNTER));
   3281 			tcu::TestCaseGroup* const					blockGroup			= new tcu::TestCaseGroup(context.getTestContext(), "array", "Arrays");
   3282 
   3283 			targetGroup->addChild(blockGroup);
   3284 
   3285 			blockGroup->addChild(new ResourceTestCase(context, variable, queryTarget, "var_array"));
   3286 			blockGroup->addChild(new ResourceTestCase(context, elementvariable, queryTarget, "var_array_array"));
   3287 		}
   3288 	}
   3289 	else
   3290 		generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1, false);
   3291 }
   3292 
   3293 static void generateUniformBlockNameLengthContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
   3294 {
   3295 	const bool	isInterfaceBlock	= (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
   3296 	const bool	namedNonArrayBlock	= isInterfaceBlock																					&&
   3297 									  static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named			&&
   3298 									  parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT;
   3299 
   3300 	if (!isInterfaceBlock || namedNonArrayBlock)
   3301 		generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_NAME_LENGTH, glu::TYPE_FLOAT, "", 2);
   3302 	else
   3303 		generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_NAME_LENGTH, glu::TYPE_FLOAT, "", 1);
   3304 }
   3305 
   3306 static void generateUniformBlockTypeContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
   3307 {
   3308 	const ProgramResourceQueryTestTarget	queryTarget			(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_TYPE);
   3309 	const bool								isInterfaceBlock	= (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
   3310 	const bool								namedNonArrayBlock	= isInterfaceBlock																					&&
   3311 																  static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named			&&
   3312 																  parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT;
   3313 
   3314 	if (!isInterfaceBlock || namedNonArrayBlock)
   3315 	{
   3316 		// .types
   3317 		{
   3318 			tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types");
   3319 			targetGroup->addChild(blockGroup);
   3320 
   3321 			generateVariableCases(context, parentStructure, blockGroup, queryTarget, 3, false);
   3322 			generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 3, false);
   3323 		}
   3324 
   3325 		generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 1);
   3326 		generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
   3327 
   3328 	}
   3329 	else
   3330 	{
   3331 		generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
   3332 		generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 1);
   3333 		generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
   3334 	}
   3335 }
   3336 
   3337 static void generateUniformBlockOffsetContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
   3338 {
   3339 	const ProgramResourceQueryTestTarget	queryTarget			(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_OFFSET);
   3340 	const bool								isInterfaceBlock	= (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
   3341 	const bool								namedNonArrayBlock	= isInterfaceBlock																					&&
   3342 																  static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named			&&
   3343 																  parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT;
   3344 
   3345 	if (!isInterfaceBlock)
   3346 	{
   3347 		// .types
   3348 		{
   3349 			tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types");
   3350 			targetGroup->addChild(blockGroup);
   3351 
   3352 			generateVariableCases(context, parentStructure, blockGroup, queryTarget, 3, false);
   3353 			generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 3, false);
   3354 		}
   3355 
   3356 		// .aggregates
   3357 		{
   3358 			tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types");
   3359 			targetGroup->addChild(blockGroup);
   3360 
   3361 			// .atomic_uint_struct
   3362 			// .atomic_uint_array
   3363 			{
   3364 				const ResourceDefinition::Node::SharedPtr offset			(new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, -1, 4)));
   3365 				const ResourceDefinition::Node::SharedPtr arrayElement		(new ResourceDefinition::ArrayElement(offset));
   3366 				const ResourceDefinition::Node::SharedPtr elementVariable	(new ResourceDefinition::Variable(arrayElement, glu::TYPE_UINT_ATOMIC_COUNTER));
   3367 
   3368 				blockGroup->addChild(new ResourceTestCase(context, elementVariable, queryTarget, "atomic_uint_array"));
   3369 			}
   3370 
   3371 			// .float_array
   3372 			// .float_struct
   3373 			{
   3374 				const ResourceDefinition::Node::SharedPtr structMember		(new ResourceDefinition::StructMember(parentStructure));
   3375 				const ResourceDefinition::Node::SharedPtr arrayElement		(new ResourceDefinition::ArrayElement(parentStructure));
   3376 				const ResourceDefinition::Node::SharedPtr memberVariable	(new ResourceDefinition::Variable(structMember, glu::TYPE_FLOAT));
   3377 				const ResourceDefinition::Node::SharedPtr elementVariable	(new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT));
   3378 
   3379 				blockGroup->addChild(new ResourceTestCase(context, memberVariable, queryTarget, "float_struct"));
   3380 				blockGroup->addChild(new ResourceTestCase(context, elementVariable, queryTarget, "float_array"));
   3381 			}
   3382 		}
   3383 	}
   3384 	else if (namedNonArrayBlock)
   3385 	{
   3386 		// .types
   3387 		{
   3388 			tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types");
   3389 			targetGroup->addChild(blockGroup);
   3390 
   3391 			generateVariableCases(context, parentStructure, blockGroup, queryTarget, 3, false);
   3392 			generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 3, false);
   3393 		}
   3394 
   3395 		// .aggregates
   3396 		{
   3397 			tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types");
   3398 			targetGroup->addChild(blockGroup);
   3399 
   3400 			// .float_array
   3401 			// .float_struct
   3402 			{
   3403 				const ResourceDefinition::Node::SharedPtr structMember		(new ResourceDefinition::StructMember(parentStructure));
   3404 				const ResourceDefinition::Node::SharedPtr arrayElement		(new ResourceDefinition::StructMember(parentStructure));
   3405 				const ResourceDefinition::Node::SharedPtr memberVariable	(new ResourceDefinition::Variable(structMember, glu::TYPE_FLOAT));
   3406 				const ResourceDefinition::Node::SharedPtr elementVariable	(new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT));
   3407 
   3408 				blockGroup->addChild(new ResourceTestCase(context, memberVariable, queryTarget, "float_struct"));
   3409 				blockGroup->addChild(new ResourceTestCase(context, elementVariable, queryTarget, "float_array"));
   3410 			}
   3411 		}
   3412 	}
   3413 	else
   3414 	{
   3415 		generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
   3416 		generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 1);
   3417 		generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
   3418 	}
   3419 }
   3420 
   3421 static void generateMatrixVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, bool createTestGroup = true, int expandLevel = 2)
   3422 {
   3423 	static const struct
   3424 	{
   3425 		int				priority;
   3426 		glu::DataType	type;
   3427 	} variableTypes[] =
   3428 	{
   3429 		{ 0,	glu::TYPE_FLOAT_MAT2	},
   3430 		{ 1,	glu::TYPE_FLOAT_MAT2X3	},
   3431 		{ 2,	glu::TYPE_FLOAT_MAT2X4	},
   3432 		{ 2,	glu::TYPE_FLOAT_MAT3X2	},
   3433 		{ 1,	glu::TYPE_FLOAT_MAT3	},
   3434 		{ 0,	glu::TYPE_FLOAT_MAT3X4	},
   3435 		{ 2,	glu::TYPE_FLOAT_MAT4X2	},
   3436 		{ 1,	glu::TYPE_FLOAT_MAT4X3	},
   3437 		{ 0,	glu::TYPE_FLOAT_MAT4	},
   3438 	};
   3439 
   3440 	tcu::TestCaseGroup* group;
   3441 
   3442 	if (createTestGroup)
   3443 	{
   3444 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "matrix", "Basic matrix type");
   3445 		targetGroup->addChild(blockGroup);
   3446 		group = blockGroup;
   3447 	}
   3448 	else
   3449 		group = targetGroup;
   3450 
   3451 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
   3452 	{
   3453 		if (variableTypes[ndx].priority < expandLevel)
   3454 		{
   3455 			const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].type));
   3456 			group->addChild(new ResourceTestCase(context, variable, queryTarget));
   3457 		}
   3458 	}
   3459 }
   3460 
   3461 static void generateMatrixStructCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel);
   3462 
   3463 static void generateMatrixArrayCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel)
   3464 {
   3465 	if (expandLevel > 0)
   3466 	{
   3467 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(parentStructure));
   3468 		tcu::TestCaseGroup* const					blockGroup		= new tcu::TestCaseGroup(context.getTestContext(), "array", "Arrays");
   3469 
   3470 		targetGroup->addChild(blockGroup);
   3471 
   3472 		// Arrays of basic variables
   3473 		generateMatrixVariableCases(context, arrayElement, blockGroup, queryTarget, expandLevel != 1, expandLevel);
   3474 
   3475 		// Arrays of arrays
   3476 		generateMatrixArrayCases(context, arrayElement, blockGroup, queryTarget, expandLevel-1);
   3477 
   3478 		// Arrays of structs
   3479 		generateMatrixStructCases(context, arrayElement, blockGroup, queryTarget, expandLevel-1);
   3480 	}
   3481 }
   3482 
   3483 static void generateMatrixStructCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel)
   3484 {
   3485 	if (expandLevel > 0)
   3486 	{
   3487 		const ResourceDefinition::Node::SharedPtr	structMember	(new ResourceDefinition::StructMember(parentStructure));
   3488 		tcu::TestCaseGroup* const					blockGroup		= new tcu::TestCaseGroup(context.getTestContext(), "struct", "Structs");
   3489 
   3490 		targetGroup->addChild(blockGroup);
   3491 
   3492 		// Struct containing basic variable
   3493 		generateMatrixVariableCases(context, structMember, blockGroup, queryTarget, expandLevel != 1, expandLevel);
   3494 
   3495 		// Struct containing arrays
   3496 		generateMatrixArrayCases(context, structMember, blockGroup, queryTarget, expandLevel-1);
   3497 
   3498 		// Struct containing struct
   3499 		generateMatrixStructCases(context, structMember, blockGroup, queryTarget, expandLevel-1);
   3500 	}
   3501 }
   3502 
   3503 static void generateUniformMatrixOrderCaseBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, bool extendedBasicTypeCases, bool opaqueCases)
   3504 {
   3505 	static const struct
   3506 	{
   3507 		const char*			name;
   3508 		glu::MatrixOrder	order;
   3509 	} qualifiers[] =
   3510 	{
   3511 		{ "no_qualifier",	glu::MATRIXORDER_LAST			},
   3512 		{ "row_major",		glu::MATRIXORDER_ROW_MAJOR		},
   3513 		{ "column_major",	glu::MATRIXORDER_COLUMN_MAJOR	},
   3514 	};
   3515 
   3516 	const ProgramResourceQueryTestTarget queryTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR);
   3517 
   3518 	for (int qualifierNdx = 0; qualifierNdx < DE_LENGTH_OF_ARRAY(qualifiers); ++qualifierNdx)
   3519 	{
   3520 		// Add layout qualifiers only for block members
   3521 		if (qualifiers[qualifierNdx].order == glu::MATRIXORDER_LAST || parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK)
   3522 		{
   3523 			ResourceDefinition::Node::SharedPtr	subStructure	= parentStructure;
   3524 			tcu::TestCaseGroup* const			qualifierGroup	= new tcu::TestCaseGroup(context.getTestContext(), qualifiers[qualifierNdx].name, "");
   3525 
   3526 			targetGroup->addChild(qualifierGroup);
   3527 
   3528 			if (qualifiers[qualifierNdx].order != glu::MATRIXORDER_LAST)
   3529 			{
   3530 				glu::Layout layout;
   3531 				layout.matrixOrder = qualifiers[qualifierNdx].order;
   3532 				subStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(subStructure, layout));
   3533 			}
   3534 
   3535 			if (extendedBasicTypeCases && qualifiers[qualifierNdx].order == glu::MATRIXORDER_LAST)
   3536 			{
   3537 				// .types
   3538 				{
   3539 					tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "");
   3540 					qualifierGroup->addChild(blockGroup);
   3541 
   3542 					generateVariableCases(context, subStructure, blockGroup, queryTarget, 1, false);
   3543 					generateMatrixVariableCases(context, subStructure, blockGroup, queryTarget, false);
   3544 					if (opaqueCases)
   3545 						generateOpaqueTypeCases(context, subStructure, blockGroup, queryTarget, 2, false);
   3546 				}
   3547 
   3548 				// .aggregates
   3549 				{
   3550 					tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "");
   3551 					qualifierGroup->addChild(blockGroup);
   3552 
   3553 					generateBufferBackedVariableAggregateTypeCases(context, subStructure, blockGroup, queryTarget.interface, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, glu::TYPE_FLOAT_MAT3X2, "", 1);
   3554 				}
   3555 			}
   3556 			else
   3557 			{
   3558 				generateBufferBackedVariableAggregateTypeCases(context, subStructure, qualifierGroup, queryTarget.interface, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, glu::TYPE_FLOAT_MAT3X2, "", 1);
   3559 			}
   3560 		}
   3561 	}
   3562 }
   3563 
   3564 static void generateUniformMatrixStrideCaseBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, bool extendedBasicTypeCases, bool opaqueCases)
   3565 {
   3566 	static const struct
   3567 	{
   3568 		const char*			name;
   3569 		glu::MatrixOrder	order;
   3570 	} qualifiers[] =
   3571 	{
   3572 		{ "no_qualifier",	glu::MATRIXORDER_LAST			},
   3573 		{ "row_major",		glu::MATRIXORDER_ROW_MAJOR		},
   3574 		{ "column_major",	glu::MATRIXORDER_COLUMN_MAJOR	},
   3575 	};
   3576 
   3577 	const ProgramResourceQueryTestTarget queryTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_MATRIX_STRIDE);
   3578 
   3579 	for (int qualifierNdx = 0; qualifierNdx < DE_LENGTH_OF_ARRAY(qualifiers); ++qualifierNdx)
   3580 	{
   3581 		// Add layout qualifiers only for block members
   3582 		if (qualifiers[qualifierNdx].order == glu::MATRIXORDER_LAST || parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK)
   3583 		{
   3584 			ResourceDefinition::Node::SharedPtr	subStructure	= parentStructure;
   3585 			tcu::TestCaseGroup* const			qualifierGroup	= new tcu::TestCaseGroup(context.getTestContext(), qualifiers[qualifierNdx].name, "");
   3586 
   3587 			targetGroup->addChild(qualifierGroup);
   3588 
   3589 			if (qualifiers[qualifierNdx].order != glu::MATRIXORDER_LAST)
   3590 			{
   3591 				glu::Layout layout;
   3592 				layout.matrixOrder = qualifiers[qualifierNdx].order;
   3593 				subStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(subStructure, layout));
   3594 			}
   3595 
   3596 			if (extendedBasicTypeCases)
   3597 			{
   3598 				// .types
   3599 				// .matrix
   3600 				if (qualifiers[qualifierNdx].order == glu::MATRIXORDER_LAST)
   3601 				{
   3602 					tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "");
   3603 					qualifierGroup->addChild(blockGroup);
   3604 
   3605 					generateVariableCases(context, subStructure, blockGroup, queryTarget, 1, false);
   3606 					generateMatrixVariableCases(context, subStructure, blockGroup, queryTarget, false);
   3607 					if (opaqueCases)
   3608 						generateOpaqueTypeCases(context, subStructure, blockGroup, queryTarget, 2, false);
   3609 				}
   3610 				else
   3611 					generateMatrixVariableCases(context, subStructure, qualifierGroup, queryTarget);
   3612 
   3613 				// .aggregates
   3614 				{
   3615 					tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "");
   3616 					qualifierGroup->addChild(blockGroup);
   3617 
   3618 					generateBufferBackedVariableAggregateTypeCases(context, subStructure, blockGroup, queryTarget.interface, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, glu::TYPE_FLOAT_MAT3X2, "", 1);
   3619 				}
   3620 			}
   3621 			else
   3622 				generateBufferBackedVariableAggregateTypeCases(context, subStructure, qualifierGroup, queryTarget.interface, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, glu::TYPE_FLOAT_MAT3X2, "", 1);
   3623 		}
   3624 	}
   3625 }
   3626 
   3627 static void generateUniformMatrixCaseBlocks (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup* const, bool, bool))
   3628 {
   3629 	static const struct
   3630 	{
   3631 		const char*			name;
   3632 		const char*			description;
   3633 		bool				block;
   3634 		bool				namedBlock;
   3635 		bool				extendedBasicTypeCases;
   3636 		glu::MatrixOrder	order;
   3637 	} children[] =
   3638 	{
   3639 		{ "default_block",				"Default block",			false,	true,	true,	glu::MATRIXORDER_LAST			},
   3640 		{ "named_block",				"Named uniform block",		true,	true,	true,	glu::MATRIXORDER_LAST			},
   3641 		{ "named_block_row_major",		"Named uniform block",		true,	true,	false,	glu::MATRIXORDER_ROW_MAJOR		},
   3642 		{ "named_block_col_major",		"Named uniform block",		true,	true,	false,	glu::MATRIXORDER_COLUMN_MAJOR	},
   3643 		{ "unnamed_block",				"Unnamed uniform block",	true,	false,	false,	glu::MATRIXORDER_LAST			},
   3644 		{ "unnamed_block_row_major",	"Unnamed uniform block",	true,	false,	false,	glu::MATRIXORDER_ROW_MAJOR		},
   3645 		{ "unnamed_block_col_major",	"Unnamed uniform block",	true,	false,	false,	glu::MATRIXORDER_COLUMN_MAJOR	},
   3646 	};
   3647 
   3648 	const ResourceDefinition::Node::SharedPtr defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   3649 	const ResourceDefinition::Node::SharedPtr uniform		(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM));
   3650 
   3651 	for (int childNdx = 0; childNdx < (int)DE_LENGTH_OF_ARRAY(children); ++childNdx)
   3652 	{
   3653 		ResourceDefinition::Node::SharedPtr	subStructure	= uniform;
   3654 		tcu::TestCaseGroup* const			blockGroup		= new tcu::TestCaseGroup(context.getTestContext(), children[childNdx].name, children[childNdx].description);
   3655 		const bool							addOpaqueCases	= children[childNdx].extendedBasicTypeCases && !children[childNdx].block;
   3656 
   3657 		targetGroup->addChild(blockGroup);
   3658 
   3659 		if (children[childNdx].order != glu::MATRIXORDER_LAST)
   3660 		{
   3661 			glu::Layout layout;
   3662 			layout.matrixOrder = children[childNdx].order;
   3663 			subStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(subStructure, layout));
   3664 		}
   3665 
   3666 		if (children[childNdx].block)
   3667 			subStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::InterfaceBlock(subStructure, children[childNdx].namedBlock));
   3668 
   3669 		blockContentGenerator(context, subStructure, blockGroup, children[childNdx].extendedBasicTypeCases, addOpaqueCases);
   3670 	}
   3671 }
   3672 
   3673 static void generateBufferReferencedByShaderInterfaceBlockCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, bool extendedCases)
   3674 {
   3675 	const bool isDefaultBlock = (parentStructure->getType() != ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
   3676 
   3677 	// .float
   3678 	// .float_array
   3679 	// .float_struct
   3680 	{
   3681 		const ResourceDefinition::Node::SharedPtr	variable		(new ResourceDefinition::Variable(parentStructure, glu::TYPE_FLOAT));
   3682 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(parentStructure));
   3683 		const ResourceDefinition::Node::SharedPtr	structMember	(new ResourceDefinition::StructMember(parentStructure));
   3684 		const ResourceDefinition::Node::SharedPtr	variableArray	(new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT));
   3685 		const ResourceDefinition::Node::SharedPtr	variableStruct	(new ResourceDefinition::Variable(structMember, glu::TYPE_FLOAT));
   3686 
   3687 		targetGroup->addChild(new ResourceTestCase(context, variable, queryTarget, "float"));
   3688 		targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "float_array"));
   3689 		targetGroup->addChild(new ResourceTestCase(context, variableStruct, queryTarget, "float_struct"));
   3690 	}
   3691 
   3692 	// .sampler
   3693 	// .sampler_array
   3694 	// .sampler_struct
   3695 	if (isDefaultBlock)
   3696 	{
   3697 		const ResourceDefinition::Node::SharedPtr	layout			(new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, 0)));
   3698 		const ResourceDefinition::Node::SharedPtr	variable		(new ResourceDefinition::Variable(layout, glu::TYPE_SAMPLER_2D));
   3699 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(layout));
   3700 		const ResourceDefinition::Node::SharedPtr	structMember	(new ResourceDefinition::StructMember(parentStructure));
   3701 		const ResourceDefinition::Node::SharedPtr	variableArray	(new ResourceDefinition::Variable(arrayElement, glu::TYPE_SAMPLER_2D));
   3702 		const ResourceDefinition::Node::SharedPtr	variableStruct	(new ResourceDefinition::Variable(structMember, glu::TYPE_SAMPLER_2D));
   3703 
   3704 		targetGroup->addChild(new ResourceTestCase(context, variable, queryTarget, "sampler"));
   3705 		targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "sampler_array"));
   3706 		targetGroup->addChild(new ResourceTestCase(context, variableStruct, queryTarget, "sampler_struct"));
   3707 	}
   3708 
   3709 	// .atomic_uint
   3710 	// .atomic_uint_array
   3711 	if (isDefaultBlock)
   3712 	{
   3713 		const ResourceDefinition::Node::SharedPtr	layout			(new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, 0)));
   3714 		const ResourceDefinition::Node::SharedPtr	variable		(new ResourceDefinition::Variable(layout, glu::TYPE_UINT_ATOMIC_COUNTER));
   3715 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(layout));
   3716 		const ResourceDefinition::Node::SharedPtr	variableArray	(new ResourceDefinition::Variable(arrayElement, glu::TYPE_UINT_ATOMIC_COUNTER));
   3717 
   3718 		targetGroup->addChild(new ResourceTestCase(context, variable, queryTarget, "atomic_uint"));
   3719 		targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "atomic_uint_array"));
   3720 	}
   3721 
   3722 	if (extendedCases)
   3723 	{
   3724 		// .float_array_struct
   3725 		{
   3726 			const ResourceDefinition::Node::SharedPtr	structMember		(new ResourceDefinition::StructMember(parentStructure));
   3727 			const ResourceDefinition::Node::SharedPtr	arrayElement		(new ResourceDefinition::ArrayElement(structMember));
   3728 			const ResourceDefinition::Node::SharedPtr	variableArrayStruct	(new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT));
   3729 
   3730 			targetGroup->addChild(new ResourceTestCase(context, variableArrayStruct, queryTarget, "float_array_struct"));
   3731 		}
   3732 
   3733 		// .float_struct_array
   3734 		{
   3735 			const ResourceDefinition::Node::SharedPtr	arrayElement		(new ResourceDefinition::ArrayElement(parentStructure));
   3736 			const ResourceDefinition::Node::SharedPtr	arrayStructMember	(new ResourceDefinition::StructMember(arrayElement));
   3737 			const ResourceDefinition::Node::SharedPtr	variableArrayStruct	(new ResourceDefinition::Variable(arrayStructMember, glu::TYPE_FLOAT));
   3738 
   3739 			targetGroup->addChild(new ResourceTestCase(context, variableArrayStruct, queryTarget, "float_struct_array"));
   3740 		}
   3741 
   3742 		// .float_array_array
   3743 		{
   3744 			const ResourceDefinition::Node::SharedPtr	arrayElement		(new ResourceDefinition::ArrayElement(parentStructure));
   3745 			const ResourceDefinition::Node::SharedPtr	subArrayElement		(new ResourceDefinition::ArrayElement(arrayElement));
   3746 			const ResourceDefinition::Node::SharedPtr	variableArrayStruct	(new ResourceDefinition::Variable(subArrayElement, glu::TYPE_FLOAT));
   3747 
   3748 			targetGroup->addChild(new ResourceTestCase(context, variableArrayStruct, queryTarget, "float_array_array"));
   3749 		}
   3750 
   3751 		// .float_struct_struct
   3752 		{
   3753 			const ResourceDefinition::Node::SharedPtr	structMember		(new ResourceDefinition::StructMember(parentStructure));
   3754 			const ResourceDefinition::Node::SharedPtr	subStructMember		(new ResourceDefinition::StructMember(structMember));
   3755 			const ResourceDefinition::Node::SharedPtr	variableArrayStruct	(new ResourceDefinition::Variable(subStructMember, glu::TYPE_FLOAT));
   3756 
   3757 			targetGroup->addChild(new ResourceTestCase(context, variableArrayStruct, queryTarget, "float_struct_struct"));
   3758 		}
   3759 
   3760 		if (queryTarget.interface == PROGRAMINTERFACE_BUFFER_VARIABLE)
   3761 		{
   3762 			const ResourceDefinition::Node::SharedPtr arrayElement(new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
   3763 
   3764 			// .float_unsized_array
   3765 			{
   3766 				const ResourceDefinition::Node::SharedPtr	variableArray	(new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT));
   3767 
   3768 				targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "float_unsized_array"));
   3769 			}
   3770 
   3771 			// .float_unsized_struct_array
   3772 			{
   3773 				const ResourceDefinition::Node::SharedPtr	structMember	(new ResourceDefinition::StructMember(arrayElement));
   3774 				const ResourceDefinition::Node::SharedPtr	variableArray	(new ResourceDefinition::Variable(structMember, glu::TYPE_FLOAT));
   3775 
   3776 				targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "float_unsized_struct_array"));
   3777 			}
   3778 		}
   3779 	}
   3780 }
   3781 
   3782 static void generateUniformReferencedByShaderSingleBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, int expandLevel)
   3783 {
   3784 	DE_UNREF(expandLevel);
   3785 
   3786 	const ResourceDefinition::Node::SharedPtr	defaultBlock		(new ResourceDefinition::DefaultBlock(parentStructure));
   3787 	const ResourceDefinition::Node::SharedPtr	uniform				(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM));
   3788 	const ProgramResourceQueryTestTarget		queryTarget			(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER);
   3789 	const bool									singleShaderCase	= parentStructure->getType() == ResourceDefinition::Node::TYPE_SHADER;
   3790 
   3791 	// .default_block
   3792 	{
   3793 		TestCaseGroup* const blockGroup = new TestCaseGroup(context, "default_block", "");
   3794 		targetGroup->addChild(blockGroup);
   3795 
   3796 		generateBufferReferencedByShaderInterfaceBlockCases(context, uniform, blockGroup, queryTarget, singleShaderCase);
   3797 	}
   3798 
   3799 	// .named_block
   3800 	{
   3801 		const ResourceDefinition::Node::SharedPtr	block		(new ResourceDefinition::InterfaceBlock(uniform, true));
   3802 		TestCaseGroup* const						blockGroup	= new TestCaseGroup(context, "uniform_block", "");
   3803 
   3804 		targetGroup->addChild(blockGroup);
   3805 
   3806 		generateBufferReferencedByShaderInterfaceBlockCases(context, block, blockGroup, queryTarget, singleShaderCase);
   3807 	}
   3808 
   3809 	// .unnamed_block
   3810 	{
   3811 		const ResourceDefinition::Node::SharedPtr	block		(new ResourceDefinition::InterfaceBlock(uniform, false));
   3812 		TestCaseGroup* const						blockGroup	= new TestCaseGroup(context, "unnamed_block", "");
   3813 
   3814 		targetGroup->addChild(blockGroup);
   3815 
   3816 		generateBufferReferencedByShaderInterfaceBlockCases(context, block, blockGroup, queryTarget, false);
   3817 	}
   3818 
   3819 	// .block_array
   3820 	{
   3821 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(uniform));
   3822 		const ResourceDefinition::Node::SharedPtr	block			(new ResourceDefinition::InterfaceBlock(arrayElement, true));
   3823 		TestCaseGroup* const						blockGroup		= new TestCaseGroup(context, "block_array", "");
   3824 
   3825 		targetGroup->addChild(blockGroup);
   3826 
   3827 		generateBufferReferencedByShaderInterfaceBlockCases(context, block, blockGroup, queryTarget, false);
   3828 	}
   3829 }
   3830 
   3831 static void generateReferencedByShaderCaseBlocks (Context& context, tcu::TestCaseGroup* const targetGroup, void (*generateBlockContent)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*, int expandLevel))
   3832 {
   3833 	static const struct
   3834 	{
   3835 		const char*		name;
   3836 		glu::ShaderType	stage;
   3837 		int				expandLevel;
   3838 	} singleStageCases[] =
   3839 	{
   3840 		{ "compute",			glu::SHADERTYPE_COMPUTE,	3	},
   3841 		{ "separable_vertex",	glu::SHADERTYPE_VERTEX,		2	},
   3842 		{ "separable_fragment",	glu::SHADERTYPE_FRAGMENT,	2	},
   3843 	};
   3844 
   3845 	static const struct
   3846 	{
   3847 		const char*		name;
   3848 		deUint32		stagesPresent;
   3849 		deUint32		stagesReferencing;
   3850 		int				expandLevel;
   3851 	} multiStageCases[] =
   3852 	{
   3853 		{ "vertex_fragment",				(1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT),	(1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT),	3	},
   3854 		{ "vertex_fragment_only_fragment",	(1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT),									(1 << glu::SHADERTYPE_FRAGMENT),	2	},
   3855 		{ "vertex_fragment_only_vertex",	(1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT),	(1 << glu::SHADERTYPE_VERTEX),										2	},
   3856 	};
   3857 
   3858 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(singleStageCases); ++ndx)
   3859 	{
   3860 		TestCaseGroup* const						blockGroup			= new TestCaseGroup(context, singleStageCases[ndx].name, "");
   3861 		const bool									programSeparable	= (singleStageCases[ndx].stage != glu::SHADERTYPE_COMPUTE);
   3862 		const ResourceDefinition::Node::SharedPtr	program				(new ResourceDefinition::Program(programSeparable));
   3863 		const ResourceDefinition::Node::SharedPtr	stage				(new ResourceDefinition::Shader(program, singleStageCases[ndx].stage, glu::GLSL_VERSION_310_ES));
   3864 
   3865 		targetGroup->addChild(blockGroup);
   3866 
   3867 		generateBlockContent(context, stage, blockGroup, singleStageCases[ndx].expandLevel);
   3868 	}
   3869 
   3870 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(multiStageCases); ++ndx)
   3871 	{
   3872 		TestCaseGroup* const						blockGroup			= new TestCaseGroup(context, multiStageCases[ndx].name, "");
   3873 		const ResourceDefinition::Node::SharedPtr	program				(new ResourceDefinition::Program());
   3874 		ResourceDefinition::ShaderSet*				shaderSet			= new ResourceDefinition::ShaderSet(program, glu::GLSL_VERSION_310_ES);
   3875 
   3876 		targetGroup->addChild(blockGroup);
   3877 
   3878 		for (int shaderBit = 0; shaderBit < glu::SHADERTYPE_LAST; ++shaderBit)
   3879 		{
   3880 			const int	stageMask			= (1 << shaderBit);
   3881 			const bool	stagePresent		= (multiStageCases[ndx].stagesPresent & stageMask) != 0;
   3882 			const bool	stageReferencing	= (multiStageCases[ndx].stagesReferencing & stageMask) != 0;
   3883 
   3884 			DE_ASSERT(stagePresent || !stageReferencing);
   3885 
   3886 			if (stagePresent)
   3887 				shaderSet->setStage((glu::ShaderType)shaderBit, stageReferencing);
   3888 		}
   3889 
   3890 		{
   3891 			const ResourceDefinition::Node::SharedPtr shaders(shaderSet);
   3892 
   3893 			generateBlockContent(context, shaders, blockGroup, multiStageCases[ndx].expandLevel);
   3894 		}
   3895 	}
   3896 }
   3897 
   3898 static glu::DataType generateRandomDataType (de::Random& rnd, bool excludeOpaqueTypes)
   3899 {
   3900 	static const glu::DataType s_types[] =
   3901 	{
   3902 		glu::TYPE_FLOAT,
   3903 		glu::TYPE_INT,
   3904 		glu::TYPE_UINT,
   3905 		glu::TYPE_BOOL,
   3906 		glu::TYPE_FLOAT_VEC2,
   3907 		glu::TYPE_FLOAT_VEC3,
   3908 		glu::TYPE_FLOAT_VEC4,
   3909 		glu::TYPE_INT_VEC2,
   3910 		glu::TYPE_INT_VEC3,
   3911 		glu::TYPE_INT_VEC4,
   3912 		glu::TYPE_UINT_VEC2,
   3913 		glu::TYPE_UINT_VEC3,
   3914 		glu::TYPE_UINT_VEC4,
   3915 		glu::TYPE_BOOL_VEC2,
   3916 		glu::TYPE_BOOL_VEC3,
   3917 		glu::TYPE_BOOL_VEC4,
   3918 		glu::TYPE_FLOAT_MAT2,
   3919 		glu::TYPE_FLOAT_MAT2X3,
   3920 		glu::TYPE_FLOAT_MAT2X4,
   3921 		glu::TYPE_FLOAT_MAT3X2,
   3922 		glu::TYPE_FLOAT_MAT3,
   3923 		glu::TYPE_FLOAT_MAT3X4,
   3924 		glu::TYPE_FLOAT_MAT4X2,
   3925 		glu::TYPE_FLOAT_MAT4X3,
   3926 		glu::TYPE_FLOAT_MAT4,
   3927 
   3928 		glu::TYPE_SAMPLER_2D,
   3929 		glu::TYPE_SAMPLER_CUBE,
   3930 		glu::TYPE_SAMPLER_2D_ARRAY,
   3931 		glu::TYPE_SAMPLER_3D,
   3932 		glu::TYPE_SAMPLER_2D_SHADOW,
   3933 		glu::TYPE_SAMPLER_CUBE_SHADOW,
   3934 		glu::TYPE_SAMPLER_2D_ARRAY_SHADOW,
   3935 		glu::TYPE_INT_SAMPLER_2D,
   3936 		glu::TYPE_INT_SAMPLER_CUBE,
   3937 		glu::TYPE_INT_SAMPLER_2D_ARRAY,
   3938 		glu::TYPE_INT_SAMPLER_3D,
   3939 		glu::TYPE_UINT_SAMPLER_2D,
   3940 		glu::TYPE_UINT_SAMPLER_CUBE,
   3941 		glu::TYPE_UINT_SAMPLER_2D_ARRAY,
   3942 		glu::TYPE_UINT_SAMPLER_3D,
   3943 		glu::TYPE_SAMPLER_2D_MULTISAMPLE,
   3944 		glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE,
   3945 		glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE,
   3946 		glu::TYPE_IMAGE_2D,
   3947 		glu::TYPE_IMAGE_CUBE,
   3948 		glu::TYPE_IMAGE_2D_ARRAY,
   3949 		glu::TYPE_IMAGE_3D,
   3950 		glu::TYPE_INT_IMAGE_2D,
   3951 		glu::TYPE_INT_IMAGE_CUBE,
   3952 		glu::TYPE_INT_IMAGE_2D_ARRAY,
   3953 		glu::TYPE_INT_IMAGE_3D,
   3954 		glu::TYPE_UINT_IMAGE_2D,
   3955 		glu::TYPE_UINT_IMAGE_CUBE,
   3956 		glu::TYPE_UINT_IMAGE_2D_ARRAY,
   3957 		glu::TYPE_UINT_IMAGE_3D,
   3958 		glu::TYPE_UINT_ATOMIC_COUNTER
   3959 	};
   3960 
   3961 	for (;;)
   3962 	{
   3963 		const glu::DataType type = s_types[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_types)-1)];
   3964 
   3965 		if (!excludeOpaqueTypes					||
   3966 			glu::isDataTypeScalarOrVector(type)	||
   3967 			glu::isDataTypeMatrix(type))
   3968 			return type;
   3969 	}
   3970 }
   3971 
   3972 static ResourceDefinition::Node::SharedPtr generateRandomVariableDefinition (de::Random& rnd, const ResourceDefinition::Node::SharedPtr& parentStructure, glu::DataType baseType, const glu::Layout& layout, bool allowUnsized)
   3973 {
   3974 	const int							maxNesting			= 4;
   3975 	ResourceDefinition::Node::SharedPtr	currentStructure	= parentStructure;
   3976 	const bool							canBeInsideAStruct	= layout.binding == -1 && !isDataTypeLayoutQualified(baseType);
   3977 
   3978 	for (int nestNdx = 0; nestNdx < maxNesting; ++nestNdx)
   3979 	{
   3980 		if (allowUnsized && nestNdx == 0 && rnd.getFloat() < 0.2)
   3981 			currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::ArrayElement(currentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
   3982 		else if (rnd.getFloat() < 0.3 && canBeInsideAStruct)
   3983 			currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::StructMember(currentStructure));
   3984 		else if (rnd.getFloat() < 0.3)
   3985 			currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::ArrayElement(currentStructure));
   3986 		else
   3987 			break;
   3988 	}
   3989 
   3990 	return ResourceDefinition::Node::SharedPtr(new ResourceDefinition::Variable(currentStructure, baseType));
   3991 }
   3992 
   3993 static ResourceDefinition::Node::SharedPtr generateRandomShaderSet (de::Random& rnd)
   3994 {
   3995 	if (rnd.getFloat() < 0.5f)
   3996 	{
   3997 		// compute only
   3998 		const ResourceDefinition::Node::SharedPtr program(new ResourceDefinition::Program());
   3999 		return ResourceDefinition::Node::SharedPtr(new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES));
   4000 	}
   4001 	else if (rnd.getFloat() < 0.5f)
   4002 	{
   4003 		// vertex and fragment
   4004 		const ResourceDefinition::Node::SharedPtr	program		(new ResourceDefinition::Program());
   4005 		ResourceDefinition::ShaderSet*				shaderSet	= new ResourceDefinition::ShaderSet(program, glu::GLSL_VERSION_310_ES);
   4006 
   4007 		if (rnd.getBool())
   4008 		{
   4009 			shaderSet->setStage(glu::SHADERTYPE_VERTEX, true);
   4010 			shaderSet->setStage(glu::SHADERTYPE_FRAGMENT, rnd.getBool());
   4011 		}
   4012 		else
   4013 		{
   4014 			shaderSet->setStage(glu::SHADERTYPE_VERTEX, rnd.getBool());
   4015 			shaderSet->setStage(glu::SHADERTYPE_FRAGMENT, true);
   4016 		}
   4017 
   4018 		return ResourceDefinition::Node::SharedPtr(shaderSet);
   4019 	}
   4020 	else
   4021 	{
   4022 		// separate vertex or fragment
   4023 		const ResourceDefinition::Node::SharedPtr	program		(new ResourceDefinition::Program(true));
   4024 		const glu::ShaderType						shaderType	= (rnd.getBool()) ? (glu::SHADERTYPE_VERTEX) : (glu::SHADERTYPE_FRAGMENT);
   4025 
   4026 		return ResourceDefinition::Node::SharedPtr(new ResourceDefinition::Shader(program, shaderType, glu::GLSL_VERSION_310_ES));
   4027 	}
   4028 }
   4029 
   4030 static glu::Layout generateRandomUniformBlockLayout (de::Random& rnd)
   4031 {
   4032 	glu::Layout layout;
   4033 
   4034 	if (rnd.getBool())
   4035 		layout.binding = rnd.getInt(0, 5);
   4036 
   4037 	if (rnd.getBool())
   4038 		layout.matrixOrder = (rnd.getBool()) ? (glu::MATRIXORDER_COLUMN_MAJOR) : (glu::MATRIXORDER_ROW_MAJOR);
   4039 
   4040 	return layout;
   4041 }
   4042 
   4043 static glu::Layout generateRandomBufferBlockLayout (de::Random& rnd)
   4044 {
   4045 	return generateRandomUniformBlockLayout(rnd);
   4046 }
   4047 
   4048 static glu::Layout generateRandomVariableLayout (de::Random& rnd, glu::DataType type, bool interfaceBlockMember)
   4049 {
   4050 	glu::Layout layout;
   4051 
   4052 	if ((glu::isDataTypeAtomicCounter(type) || glu::isDataTypeImage(type) || glu::isDataTypeSampler(type)) && rnd.getBool())
   4053 		layout.binding = rnd.getInt(0, 5);
   4054 
   4055 	if (glu::isDataTypeAtomicCounter(type) && rnd.getBool())
   4056 		layout.offset = rnd.getInt(0, 3) * 4;
   4057 
   4058 	if (glu::isDataTypeMatrix(type) && interfaceBlockMember && rnd.getBool())
   4059 		layout.matrixOrder = (rnd.getBool()) ? (glu::MATRIXORDER_COLUMN_MAJOR) : (glu::MATRIXORDER_ROW_MAJOR);
   4060 
   4061 	return layout;
   4062 }
   4063 
   4064 static void generateUniformRandomCase (Context& context, tcu::TestCaseGroup* const targetGroup, int index)
   4065 {
   4066 	de::Random									rnd					(index * 0x12345);
   4067 	const ResourceDefinition::Node::SharedPtr	shader				= generateRandomShaderSet(rnd);
   4068 	const bool									interfaceBlock		= rnd.getBool();
   4069 	const glu::DataType							type				= generateRandomDataType(rnd, interfaceBlock);
   4070 	const glu::Layout							layout				= generateRandomVariableLayout(rnd, type, interfaceBlock);
   4071 	const ResourceDefinition::Node::SharedPtr	defaultBlock		(new ResourceDefinition::DefaultBlock(shader));
   4072 	const ResourceDefinition::Node::SharedPtr	uniform				(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM));
   4073 	ResourceDefinition::Node::SharedPtr			currentStructure	= uniform;
   4074 
   4075 	if (interfaceBlock)
   4076 	{
   4077 		const bool namedBlock = rnd.getBool();
   4078 
   4079 		currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(currentStructure, generateRandomUniformBlockLayout(rnd)));
   4080 
   4081 		if (namedBlock && rnd.getBool())
   4082 			currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::ArrayElement(currentStructure));
   4083 
   4084 		currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::InterfaceBlock(currentStructure, namedBlock));
   4085 	}
   4086 
   4087 	currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(currentStructure, layout));
   4088 	currentStructure = generateRandomVariableDefinition(rnd, currentStructure, type, layout, false);
   4089 
   4090 	targetGroup->addChild(new ResourceTestCase(context, currentStructure, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_UNIFORM_INTERFACE_MASK), de::toString(index).c_str()));
   4091 }
   4092 
   4093 static void generateUniformCaseRandomCases (Context& context, tcu::TestCaseGroup* const targetGroup)
   4094 {
   4095 	const int numCases = 40;
   4096 
   4097 	for (int ndx = 0; ndx < numCases; ++ndx)
   4098 		generateUniformRandomCase(context, targetGroup, ndx);
   4099 }
   4100 
   4101 class UniformInterfaceTestGroup : public TestCaseGroup
   4102 {
   4103 public:
   4104 			UniformInterfaceTestGroup	(Context& context);
   4105 	void	init						(void);
   4106 };
   4107 
   4108 UniformInterfaceTestGroup::UniformInterfaceTestGroup (Context& context)
   4109 	: TestCaseGroup(context, "uniform", "Uniform interace")
   4110 {
   4111 }
   4112 
   4113 void UniformInterfaceTestGroup::init (void)
   4114 {
   4115 	const ResourceDefinition::Node::SharedPtr	program			(new ResourceDefinition::Program());
   4116 	const ResourceDefinition::Node::SharedPtr	computeShader	(new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES));
   4117 
   4118 	// .resource_list
   4119 	{
   4120 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "resource_list", "Resource list");
   4121 		addChild(blockGroup);
   4122 		generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformResourceListBlockContents);
   4123 	}
   4124 
   4125 	// .array_size
   4126 	{
   4127 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "array_size", "Query array size");
   4128 		addChild(blockGroup);
   4129 		generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockArraySizeContents);
   4130 	}
   4131 
   4132 	// .array_stride
   4133 	{
   4134 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "array_stride", "Query array stride");
   4135 		addChild(blockGroup);
   4136 		generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockArrayStrideContents);
   4137 	}
   4138 
   4139 	// .atomic_counter_buffer_index
   4140 	{
   4141 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "atomic_counter_buffer_index", "Query atomic counter buffer index");
   4142 		addChild(blockGroup);
   4143 		generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_DEFAULT | BLOCKFLAG_NAMED, generateUniformBlockAtomicCounterBufferIndexContents);
   4144 	}
   4145 
   4146 	// .block_index
   4147 	{
   4148 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "block_index", "Query block index");
   4149 		addChild(blockGroup);
   4150 		generateUniformBlockBlockIndexContents(m_context, blockGroup);
   4151 	}
   4152 
   4153 	// .location
   4154 	{
   4155 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "location", "Query location");
   4156 		addChild(blockGroup);
   4157 		generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_DEFAULT | BLOCKFLAG_NAMED | BLOCKFLAG_UNNAMED, generateUniformBlockLocationContents);
   4158 	}
   4159 
   4160 	// .matrix_row_major
   4161 	{
   4162 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "matrix_row_major", "Query matrix row_major");
   4163 		addChild(blockGroup);
   4164 		generateUniformMatrixCaseBlocks(m_context, computeShader, blockGroup, generateUniformMatrixOrderCaseBlockContentCases);
   4165 	}
   4166 
   4167 	// .matrix_stride
   4168 	{
   4169 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "matrix_stride", "Query matrix stride");
   4170 		addChild(blockGroup);
   4171 		generateUniformMatrixCaseBlocks(m_context, computeShader, blockGroup, generateUniformMatrixStrideCaseBlockContentCases);
   4172 	}
   4173 
   4174 	// .name_length
   4175 	{
   4176 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "name_length", "Query name length");
   4177 		addChild(blockGroup);
   4178 		generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockNameLengthContents);
   4179 	}
   4180 
   4181 	// .offset
   4182 	{
   4183 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "offset", "Query offset");
   4184 		addChild(blockGroup);
   4185 		generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockOffsetContents);
   4186 	}
   4187 
   4188 	// .referenced_by_shader
   4189 	{
   4190 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "referenced_by_shader", "Query referenced by shader");
   4191 		addChild(blockGroup);
   4192 		generateReferencedByShaderCaseBlocks(m_context, blockGroup, generateUniformReferencedByShaderSingleBlockContentCases);
   4193 	}
   4194 
   4195 	// .type
   4196 	{
   4197 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "type", "Query type");
   4198 		addChild(blockGroup);
   4199 		generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockTypeContents);
   4200 	}
   4201 
   4202 	// .random
   4203 	{
   4204 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random");
   4205 		addChild(blockGroup);
   4206 		generateUniformCaseRandomCases(m_context, blockGroup);
   4207 	}
   4208 }
   4209 
   4210 static void generateBufferBackedInterfaceResourceListCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, const char* blockName)
   4211 {
   4212 	targetGroup->addChild(new ResourceListTestCase(context, targetResource, interface, blockName));
   4213 }
   4214 
   4215 static void generateBufferBackedInterfaceNameLengthCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, const char* blockName)
   4216 {
   4217 	targetGroup->addChild(new ResourceTestCase(context, targetResource, ProgramResourceQueryTestTarget(interface, PROGRAMRESOURCEPROP_NAME_LENGTH), blockName));
   4218 }
   4219 
   4220 static void generateBufferBackedInterfaceResourceBasicBlockTypes (Context& context, tcu::TestCaseGroup* targetGroup, glu::Storage storage, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup* const, ProgramInterface interface, const char* blockName))
   4221 {
   4222 	const ResourceDefinition::Node::SharedPtr	program				(new ResourceDefinition::Program());
   4223 	const ResourceDefinition::Node::SharedPtr	shader				(new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES));
   4224 	const ResourceDefinition::Node::SharedPtr	defaultBlock		(new ResourceDefinition::DefaultBlock(shader));
   4225 	const ResourceDefinition::Node::SharedPtr	storageQualifier	(new ResourceDefinition::StorageQualifier(defaultBlock, storage));
   4226 	const ResourceDefinition::Node::SharedPtr	binding				(new ResourceDefinition::LayoutQualifier(storageQualifier, glu::Layout(-1, 1)));
   4227 	const ProgramInterface						programInterface	= (storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) : (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK);
   4228 
   4229 	// .named_block
   4230 	{
   4231 		const ResourceDefinition::Node::SharedPtr block			(new ResourceDefinition::InterfaceBlock(binding, true));
   4232 		const ResourceDefinition::Node::SharedPtr dummyVariable	(new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
   4233 
   4234 		blockContentGenerator(context, dummyVariable, targetGroup, programInterface, "named_block");
   4235 	}
   4236 
   4237 	// .unnamed_block
   4238 	{
   4239 		const ResourceDefinition::Node::SharedPtr block			(new ResourceDefinition::InterfaceBlock(binding, false));
   4240 		const ResourceDefinition::Node::SharedPtr dummyVariable	(new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
   4241 
   4242 		blockContentGenerator(context, dummyVariable, targetGroup, programInterface, "unnamed_block");
   4243 	}
   4244 
   4245 	// .block_array
   4246 	{
   4247 		const ResourceDefinition::Node::SharedPtr arrayElement	(new ResourceDefinition::ArrayElement(binding, 3));
   4248 		const ResourceDefinition::Node::SharedPtr block			(new ResourceDefinition::InterfaceBlock(arrayElement, true));
   4249 		const ResourceDefinition::Node::SharedPtr dummyVariable	(new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
   4250 
   4251 		blockContentGenerator(context, dummyVariable, targetGroup, programInterface, "block_array");
   4252 	}
   4253 
   4254 	// .block_array_single_element
   4255 	{
   4256 		const ResourceDefinition::Node::SharedPtr arrayElement	(new ResourceDefinition::ArrayElement(binding, 1));
   4257 		const ResourceDefinition::Node::SharedPtr block			(new ResourceDefinition::InterfaceBlock(arrayElement, true));
   4258 		const ResourceDefinition::Node::SharedPtr dummyVariable	(new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
   4259 
   4260 		blockContentGenerator(context, dummyVariable, targetGroup, programInterface, "block_array_single_element");
   4261 	}
   4262 }
   4263 
   4264 static void generateBufferBackedInterfaceResourceBufferBindingCases (Context& context, tcu::TestCaseGroup* targetGroup, glu::Storage storage)
   4265 {
   4266 	const ResourceDefinition::Node::SharedPtr	program				(new ResourceDefinition::Program());
   4267 	const ResourceDefinition::Node::SharedPtr	shader				(new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES));
   4268 	const ResourceDefinition::Node::SharedPtr	defaultBlock		(new ResourceDefinition::DefaultBlock(shader));
   4269 	const ResourceDefinition::Node::SharedPtr	storageQualifier	(new ResourceDefinition::StorageQualifier(defaultBlock, storage));
   4270 
   4271 	for (int ndx = 0; ndx < 2; ++ndx)
   4272 	{
   4273 		const bool									explicitBinding		= (ndx == 1);
   4274 		const int									bindingNdx			= (explicitBinding) ? (1) : (-1);
   4275 		const std::string							nameSuffix			= (explicitBinding) ? ("_explicit_binding") : ("");
   4276 		const ResourceDefinition::Node::SharedPtr	binding				(new ResourceDefinition::LayoutQualifier(storageQualifier, glu::Layout(-1, bindingNdx)));
   4277 		const ProgramInterface						programInterface	= (storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) : (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK);
   4278 
   4279 		// .named_block*
   4280 		{
   4281 			const ResourceDefinition::Node::SharedPtr block			(new ResourceDefinition::InterfaceBlock(binding, true));
   4282 			const ResourceDefinition::Node::SharedPtr dummyVariable	(new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
   4283 
   4284 			targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_BUFFER_BINDING), ("named_block" + nameSuffix).c_str()));
   4285 		}
   4286 
   4287 		// .unnamed_block*
   4288 		{
   4289 			const ResourceDefinition::Node::SharedPtr block			(new ResourceDefinition::InterfaceBlock(binding, false));
   4290 			const ResourceDefinition::Node::SharedPtr dummyVariable	(new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
   4291 
   4292 			targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_BUFFER_BINDING), ("unnamed_block" + nameSuffix).c_str()));
   4293 		}
   4294 
   4295 		// .block_array*
   4296 		{
   4297 			const ResourceDefinition::Node::SharedPtr arrayElement	(new ResourceDefinition::ArrayElement(binding, 3));
   4298 			const ResourceDefinition::Node::SharedPtr block			(new ResourceDefinition::InterfaceBlock(arrayElement, true));
   4299 			const ResourceDefinition::Node::SharedPtr dummyVariable	(new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
   4300 
   4301 			targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_BUFFER_BINDING), ("block_array" + nameSuffix).c_str()));
   4302 		}
   4303 	}
   4304 }
   4305 
   4306 template <glu::Storage Storage>
   4307 static void generateBufferBlockReferencedByShaderSingleBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, int expandLevel)
   4308 {
   4309 	const ProgramInterface						programInterface	= (Storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) :
   4310 																      (Storage == glu::STORAGE_BUFFER) ? (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK) :
   4311 																      (PROGRAMINTERFACE_LAST);
   4312 	const ResourceDefinition::Node::SharedPtr	defaultBlock		(new ResourceDefinition::DefaultBlock(parentStructure));
   4313 	const ResourceDefinition::Node::SharedPtr	storage				(new ResourceDefinition::StorageQualifier(defaultBlock, Storage));
   4314 
   4315 	DE_UNREF(expandLevel);
   4316 
   4317 	DE_ASSERT(programInterface != PROGRAMINTERFACE_LAST);
   4318 
   4319 	// .named_block
   4320 	{
   4321 		const ResourceDefinition::Node::SharedPtr block			(new ResourceDefinition::InterfaceBlock(storage, true));
   4322 		const ResourceDefinition::Node::SharedPtr dummyVariable	(new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
   4323 
   4324 		targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER), "named_block"));
   4325 	}
   4326 
   4327 	// .unnamed_block
   4328 	{
   4329 		const ResourceDefinition::Node::SharedPtr block			(new ResourceDefinition::InterfaceBlock(storage, false));
   4330 		const ResourceDefinition::Node::SharedPtr dummyVariable	(new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
   4331 
   4332 		targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER), "unnamed_block"));
   4333 	}
   4334 
   4335 	// .block_array
   4336 	{
   4337 		const ResourceDefinition::Node::SharedPtr arrayElement	(new ResourceDefinition::ArrayElement(storage, 3));
   4338 		const ResourceDefinition::Node::SharedPtr block			(new ResourceDefinition::InterfaceBlock(arrayElement, true));
   4339 		const ResourceDefinition::Node::SharedPtr dummyVariable	(new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
   4340 
   4341 		targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER), "block_array"));
   4342 	}
   4343 }
   4344 
   4345 static void generateBufferBackedInterfaceResourceActiveVariablesCase (Context& context, tcu::TestCaseGroup* targetGroup, glu::Storage storage)
   4346 {
   4347 	targetGroup->addChild(new InterfaceBlockActiveVariablesTestCase(context, "named_block",		"Named block",		storage,	InterfaceBlockActiveVariablesTestCase::CASE_NAMED_BLOCK));
   4348 	targetGroup->addChild(new InterfaceBlockActiveVariablesTestCase(context, "unnamed_block",	"Unnamed block",	storage,	InterfaceBlockActiveVariablesTestCase::CASE_UNNAMED_BLOCK));
   4349 	targetGroup->addChild(new InterfaceBlockActiveVariablesTestCase(context, "block_array",		"Block array",		storage,	InterfaceBlockActiveVariablesTestCase::CASE_BLOCK_ARRAY));
   4350 }
   4351 
   4352 static void generateBufferBackedInterfaceResourceBufferDataSizeCases (Context& context, tcu::TestCaseGroup* targetGroup, glu::Storage storage)
   4353 {
   4354 	targetGroup->addChild(new InterfaceBlockDataSizeTestCase(context, "named_block",	"Named block",		storage,	InterfaceBlockDataSizeTestCase::CASE_NAMED_BLOCK));
   4355 	targetGroup->addChild(new InterfaceBlockDataSizeTestCase(context, "unnamed_block",	"Unnamed block",	storage,	InterfaceBlockDataSizeTestCase::CASE_UNNAMED_BLOCK));
   4356 	targetGroup->addChild(new InterfaceBlockDataSizeTestCase(context, "block_array",	"Block array",		storage,	InterfaceBlockDataSizeTestCase::CASE_BLOCK_ARRAY));
   4357 }
   4358 
   4359 class BufferBackedBlockInterfaceTestGroup : public TestCaseGroup
   4360 {
   4361 public:
   4362 						BufferBackedBlockInterfaceTestGroup	(Context& context, glu::Storage interfaceBlockStorage);
   4363 	void				init								(void);
   4364 
   4365 private:
   4366 	static const char*	getGroupName						(glu::Storage storage);
   4367 	static const char*	getGroupDescription					(glu::Storage storage);
   4368 
   4369 	const glu::Storage	m_storage;
   4370 };
   4371 
   4372 BufferBackedBlockInterfaceTestGroup::BufferBackedBlockInterfaceTestGroup(Context& context, glu::Storage storage)
   4373 	: TestCaseGroup	(context, getGroupName(storage), getGroupDescription(storage))
   4374 	, m_storage		(storage)
   4375 {
   4376 	DE_ASSERT(storage == glu::STORAGE_BUFFER || storage == glu::STORAGE_UNIFORM);
   4377 }
   4378 
   4379 void BufferBackedBlockInterfaceTestGroup::init (void)
   4380 {
   4381 	// .resource_list
   4382 	{
   4383 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "resource_list", "Resource list");
   4384 		addChild(blockGroup);
   4385 		generateBufferBackedInterfaceResourceBasicBlockTypes(m_context, blockGroup, m_storage, generateBufferBackedInterfaceResourceListCase);
   4386 	}
   4387 
   4388 	// .active_variables
   4389 	{
   4390 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "active_variables", "Active variables");
   4391 		addChild(blockGroup);
   4392 		generateBufferBackedInterfaceResourceActiveVariablesCase(m_context, blockGroup, m_storage);
   4393 	}
   4394 
   4395 	// .buffer_binding
   4396 	{
   4397 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "buffer_binding", "Buffer binding");
   4398 		addChild(blockGroup);
   4399 		generateBufferBackedInterfaceResourceBufferBindingCases(m_context, blockGroup, m_storage);
   4400 	}
   4401 
   4402 	// .buffer_data_size
   4403 	{
   4404 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "buffer_data_size", "Buffer data size");
   4405 		addChild(blockGroup);
   4406 		generateBufferBackedInterfaceResourceBufferDataSizeCases(m_context, blockGroup, m_storage);
   4407 	}
   4408 
   4409 	// .name_length
   4410 	{
   4411 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "name_length", "Name length");
   4412 		addChild(blockGroup);
   4413 		generateBufferBackedInterfaceResourceBasicBlockTypes(m_context, blockGroup, m_storage, generateBufferBackedInterfaceNameLengthCase);
   4414 	}
   4415 
   4416 	// .referenced_by
   4417 	{
   4418 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "referenced_by", "Referenced by shader");
   4419 		addChild(blockGroup);
   4420 
   4421 		if (m_storage == glu::STORAGE_UNIFORM)
   4422 			generateReferencedByShaderCaseBlocks(m_context, blockGroup, generateBufferBlockReferencedByShaderSingleBlockContentCases<glu::STORAGE_UNIFORM>);
   4423 		else if (m_storage == glu::STORAGE_BUFFER)
   4424 			generateReferencedByShaderCaseBlocks(m_context, blockGroup, generateBufferBlockReferencedByShaderSingleBlockContentCases<glu::STORAGE_BUFFER>);
   4425 		else
   4426 			DE_ASSERT(false);
   4427 	}
   4428 }
   4429 
   4430 const char* BufferBackedBlockInterfaceTestGroup::getGroupName (glu::Storage storage)
   4431 {
   4432 	switch (storage)
   4433 	{
   4434 		case glu::STORAGE_UNIFORM:	return "uniform_block";
   4435 		case glu::STORAGE_BUFFER:	return "shader_storage_block";
   4436 		default:
   4437 			DE_ASSERT("false");
   4438 			return DE_NULL;
   4439 	}
   4440 }
   4441 
   4442 const char* BufferBackedBlockInterfaceTestGroup::getGroupDescription (glu::Storage storage)
   4443 {
   4444 	switch (storage)
   4445 	{
   4446 		case glu::STORAGE_UNIFORM:	return "Uniform block interface";
   4447 		case glu::STORAGE_BUFFER:	return "Shader storage block interface";
   4448 		default:
   4449 			DE_ASSERT("false");
   4450 			return DE_NULL;
   4451 	}
   4452 }
   4453 
   4454 class AtomicCounterTestGroup : public TestCaseGroup
   4455 {
   4456 public:
   4457 			AtomicCounterTestGroup	(Context& context);
   4458 	void	init					(void);
   4459 };
   4460 
   4461 AtomicCounterTestGroup::AtomicCounterTestGroup (Context& context)
   4462 	: TestCaseGroup(context, "atomic_counter_buffer", "Atomic counter buffer")
   4463 {
   4464 }
   4465 
   4466 void AtomicCounterTestGroup::init (void)
   4467 {
   4468 	// .resource_list
   4469 	addChild(new AtomicCounterResourceListCase(m_context, "resource_list", "Resource list"));
   4470 
   4471 	// .active_variables
   4472 	addChild(new AtomicCounterActiveVariablesCase(m_context, "active_variables", "Active variables"));
   4473 
   4474 	// .buffer_binding
   4475 	addChild(new AtomicCounterBufferBindingCase(m_context, "buffer_binding", "Buffer binding"));
   4476 
   4477 	// .buffer_data_size
   4478 	addChild(new AtomicCounterBufferDataSizeCase(m_context, "buffer_data_size", "Buffer binding"));
   4479 
   4480 	// .referenced_by
   4481 	addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_compute",							"",	(1 << glu::SHADERTYPE_COMPUTE),										(1 << glu::SHADERTYPE_COMPUTE)));
   4482 	addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_separable_vertex",					"",	(1 << glu::SHADERTYPE_VERTEX),										(1 << glu::SHADERTYPE_VERTEX)));
   4483 	addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_separable_fragment",				"",	(1 << glu::SHADERTYPE_FRAGMENT),									(1 << glu::SHADERTYPE_FRAGMENT)));
   4484 	addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_vertex_fragment",					"",	(1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT),	(1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT)));
   4485 	addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_vertex_fragment_only_fragment",	"",	(1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT),									(1 << glu::SHADERTYPE_FRAGMENT)));
   4486 	addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_vertex_fragment_only_vertex",		"",	(1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT),	(1 << glu::SHADERTYPE_VERTEX)));
   4487 }
   4488 
   4489 static void generateProgramInputOutputShaderCaseBlocks (Context& context, tcu::TestCaseGroup* targetGroup, bool withCompute, bool inputCase, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*, deUint32))
   4490 {
   4491 	// .vertex_fragment
   4492 	{
   4493 		tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "vertex_fragment", "Vertex and fragment");
   4494 		const ResourceDefinition::Node::SharedPtr	program			(new ResourceDefinition::Program(false));
   4495 		ResourceDefinition::ShaderSet*				shaderSetPtr	= new ResourceDefinition::ShaderSet(program, glu::GLSL_VERSION_310_ES);
   4496 		const ResourceDefinition::Node::SharedPtr	shaderSet		(shaderSetPtr);
   4497 
   4498 		shaderSetPtr->setStage(glu::SHADERTYPE_VERTEX, inputCase);
   4499 		shaderSetPtr->setStage(glu::SHADERTYPE_FRAGMENT, !inputCase);
   4500 
   4501 		targetGroup->addChild(blockGroup);
   4502 
   4503 		blockContentGenerator(context, shaderSet, blockGroup, (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT));
   4504 	}
   4505 
   4506 	// .separable_vertex
   4507 	{
   4508 		tcu::TestCaseGroup* const					blockGroup	= new TestCaseGroup(context, "separable_vertex", "Separable vertex");
   4509 		const ResourceDefinition::Node::SharedPtr	program		(new ResourceDefinition::Program(true));
   4510 		const ResourceDefinition::Node::SharedPtr	shader		(new ResourceDefinition::Shader(program, glu::SHADERTYPE_VERTEX, glu::GLSL_VERSION_310_ES));
   4511 
   4512 		targetGroup->addChild(blockGroup);
   4513 
   4514 		blockContentGenerator(context, shader, blockGroup, (1 << glu::SHADERTYPE_VERTEX));
   4515 	}
   4516 
   4517 	// .separable_fragment
   4518 	{
   4519 		tcu::TestCaseGroup* const					blockGroup	= new TestCaseGroup(context, "separable_fragment", "Separable fragment");
   4520 		const ResourceDefinition::Node::SharedPtr	program		(new ResourceDefinition::Program(true));
   4521 		const ResourceDefinition::Node::SharedPtr	shader		(new ResourceDefinition::Shader(program, glu::SHADERTYPE_FRAGMENT, glu::GLSL_VERSION_310_ES));
   4522 
   4523 		targetGroup->addChild(blockGroup);
   4524 
   4525 		blockContentGenerator(context, shader, blockGroup, (1 << glu::SHADERTYPE_FRAGMENT));
   4526 	}
   4527 
   4528 	// .compute
   4529 	if (withCompute)
   4530 	{
   4531 		tcu::TestCaseGroup* const					blockGroup	= new TestCaseGroup(context, "compute", "Compute");
   4532 		const ResourceDefinition::Node::SharedPtr	program		(new ResourceDefinition::Program(true));
   4533 		const ResourceDefinition::Node::SharedPtr	shader		(new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES));
   4534 
   4535 		targetGroup->addChild(blockGroup);
   4536 
   4537 		blockContentGenerator(context, shader, blockGroup, (1 << glu::SHADERTYPE_COMPUTE));
   4538 	}
   4539 }
   4540 
   4541 static void generateProgramInputResourceListBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
   4542 {
   4543 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   4544 	const ResourceDefinition::Node::SharedPtr	input			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_IN));
   4545 
   4546 	// .empty
   4547 	targetGroup->addChild(new ResourceListTestCase(context, defaultBlock, PROGRAMINTERFACE_PROGRAM_INPUT, "empty"));
   4548 
   4549 	// vertex first stage
   4550 	if (presentShadersMask & (1 << glu::SHADERTYPE_VERTEX))
   4551 	{
   4552 		// .var
   4553 		const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4));
   4554 		targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_INPUT));
   4555 	}
   4556 
   4557 	// fragment first stage
   4558 	if (presentShadersMask == (1 << glu::SHADERTYPE_FRAGMENT))
   4559 	{
   4560 		// .var
   4561 		{
   4562 			const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4));
   4563 			targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_INPUT));
   4564 		}
   4565 		// .var_struct
   4566 		{
   4567 			const ResourceDefinition::Node::SharedPtr structMbr	(new ResourceDefinition::StructMember(input));
   4568 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
   4569 			targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_INPUT));
   4570 		}
   4571 		// .var_array
   4572 		{
   4573 			const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(input));
   4574 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   4575 			targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_INPUT));
   4576 		}
   4577 	}
   4578 }
   4579 
   4580 static void generateProgramOutputResourceListBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
   4581 {
   4582 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   4583 	const ResourceDefinition::Node::SharedPtr	output			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT));
   4584 
   4585 	// .empty
   4586 	targetGroup->addChild(new ResourceListTestCase(context, defaultBlock, PROGRAMINTERFACE_PROGRAM_OUTPUT, "empty"));
   4587 
   4588 	// vertex last stage
   4589 	if (presentShadersMask == (1 << glu::SHADERTYPE_VERTEX))
   4590 	{
   4591 		// .var
   4592 		{
   4593 			const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4));
   4594 			targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_OUTPUT));
   4595 		}
   4596 		// .var_struct
   4597 		{
   4598 			const ResourceDefinition::Node::SharedPtr structMbr	(new ResourceDefinition::StructMember(output));
   4599 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
   4600 			targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_OUTPUT));
   4601 		}
   4602 		// .var_array
   4603 		{
   4604 			const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(output));
   4605 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   4606 			targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_OUTPUT));
   4607 		}
   4608 	}
   4609 
   4610 	// fragment last stage
   4611 	if (presentShadersMask & (1 << glu::SHADERTYPE_FRAGMENT))
   4612 	{
   4613 		// .var
   4614 		{
   4615 			const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4));
   4616 			targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_OUTPUT));
   4617 		}
   4618 		// .var_array
   4619 		{
   4620 			const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(output));
   4621 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   4622 			targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_OUTPUT));
   4623 		}
   4624 	}
   4625 }
   4626 
   4627 template <ProgramResourcePropFlags TargetProp>
   4628 static void generateProgramInputBasicBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
   4629 {
   4630 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   4631 	const ResourceDefinition::Node::SharedPtr	input			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_IN));
   4632 
   4633 	// vertex first stage
   4634 	if (presentShadersMask & (1 << glu::SHADERTYPE_VERTEX))
   4635 	{
   4636 		// .var
   4637 		const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4));
   4638 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, TargetProp), "var"));
   4639 	}
   4640 
   4641 	// fragment first stage
   4642 	if (presentShadersMask == (1 << glu::SHADERTYPE_FRAGMENT))
   4643 	{
   4644 		// .var
   4645 		{
   4646 			const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4));
   4647 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, TargetProp), "var"));
   4648 		}
   4649 		// .var_struct
   4650 		{
   4651 			const ResourceDefinition::Node::SharedPtr structMbr	(new ResourceDefinition::StructMember(input));
   4652 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
   4653 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, TargetProp), "var_struct"));
   4654 		}
   4655 		// .var_array
   4656 		{
   4657 			const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(input));
   4658 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   4659 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, TargetProp), "var_array"));
   4660 		}
   4661 	}
   4662 }
   4663 
   4664 template <ProgramResourcePropFlags TargetProp>
   4665 static void generateProgramOutputBasicBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
   4666 {
   4667 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   4668 	const ResourceDefinition::Node::SharedPtr	output			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT));
   4669 
   4670 	// vertex last stage
   4671 	if (presentShadersMask == (1 << glu::SHADERTYPE_VERTEX))
   4672 	{
   4673 		// .var
   4674 		{
   4675 			const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4));
   4676 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, TargetProp), "var"));
   4677 		}
   4678 		// .var_struct
   4679 		{
   4680 			const ResourceDefinition::Node::SharedPtr structMbr	(new ResourceDefinition::StructMember(output));
   4681 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
   4682 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, TargetProp), "var_struct"));
   4683 		}
   4684 		// .var_array
   4685 		{
   4686 			const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(output));
   4687 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   4688 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, TargetProp), "var_array"));
   4689 		}
   4690 	}
   4691 
   4692 	// fragment last stage
   4693 	if (presentShadersMask & (1 << glu::SHADERTYPE_FRAGMENT))
   4694 	{
   4695 		// .var
   4696 		{
   4697 			const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4));
   4698 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, TargetProp), "var"));
   4699 		}
   4700 		// .var_array
   4701 		{
   4702 			const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(output));
   4703 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   4704 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, TargetProp), "var_array"));
   4705 		}
   4706 	}
   4707 }
   4708 
   4709 static void generateProgramInputLocationBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
   4710 {
   4711 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   4712 	const ResourceDefinition::Node::SharedPtr	input			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_IN));
   4713 
   4714 	// vertex first stage
   4715 	if (presentShadersMask & (1 << glu::SHADERTYPE_VERTEX))
   4716 	{
   4717 		// .var
   4718 		{
   4719 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4));
   4720 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var"));
   4721 		}
   4722 		// .var_explicit_location
   4723 		{
   4724 			const ResourceDefinition::Node::SharedPtr layout	(new ResourceDefinition::LayoutQualifier(input, glu::Layout(2)));
   4725 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4));
   4726 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location"));
   4727 		}
   4728 	}
   4729 
   4730 	// fragment first stage
   4731 	if (presentShadersMask == (1 << glu::SHADERTYPE_FRAGMENT))
   4732 	{
   4733 		// .var
   4734 		{
   4735 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4));
   4736 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var"));
   4737 		}
   4738 		// .var_explicit_location
   4739 		{
   4740 			const ResourceDefinition::Node::SharedPtr layout	(new ResourceDefinition::LayoutQualifier(input, glu::Layout(2)));
   4741 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4));
   4742 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location"));
   4743 		}
   4744 		// .var_struct
   4745 		{
   4746 			const ResourceDefinition::Node::SharedPtr structMbr	(new ResourceDefinition::StructMember(input));
   4747 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
   4748 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_struct"));
   4749 		}
   4750 		// .var_struct_explicit_location
   4751 		{
   4752 			const ResourceDefinition::Node::SharedPtr layout	(new ResourceDefinition::LayoutQualifier(input, glu::Layout(2)));
   4753 			const ResourceDefinition::Node::SharedPtr structMbr	(new ResourceDefinition::StructMember(layout));
   4754 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
   4755 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_struct_explicit_location"));
   4756 		}
   4757 		// .var_array
   4758 		{
   4759 			const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(input));
   4760 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   4761 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array"));
   4762 		}
   4763 		// .var_array_explicit_location
   4764 		{
   4765 			const ResourceDefinition::Node::SharedPtr layout	(new ResourceDefinition::LayoutQualifier(input, glu::Layout(2)));
   4766 			const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(layout));
   4767 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   4768 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array_explicit_location"));
   4769 		}
   4770 	}
   4771 }
   4772 
   4773 static void generateProgramOutputLocationBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
   4774 {
   4775 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   4776 	const ResourceDefinition::Node::SharedPtr	output			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT));
   4777 
   4778 	// vertex last stage
   4779 	if (presentShadersMask == (1 << glu::SHADERTYPE_VERTEX))
   4780 	{
   4781 		// .var
   4782 		{
   4783 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4));
   4784 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var"));
   4785 		}
   4786 		// .var_explicit_location
   4787 		{
   4788 			const ResourceDefinition::Node::SharedPtr layout	(new ResourceDefinition::LayoutQualifier(output, glu::Layout(2)));
   4789 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4));
   4790 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location"));
   4791 		}
   4792 		// .var_struct
   4793 		{
   4794 			const ResourceDefinition::Node::SharedPtr structMbr	(new ResourceDefinition::StructMember(output));
   4795 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
   4796 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_struct"));
   4797 		}
   4798 		// .var_struct_explicit_location
   4799 		{
   4800 			const ResourceDefinition::Node::SharedPtr layout	(new ResourceDefinition::LayoutQualifier(output, glu::Layout(2)));
   4801 			const ResourceDefinition::Node::SharedPtr structMbr	(new ResourceDefinition::StructMember(layout));
   4802 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
   4803 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_struct_explicit_location"));
   4804 		}
   4805 		// .var_array
   4806 		{
   4807 			const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(output));
   4808 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   4809 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array"));
   4810 		}
   4811 		// .var_array_explicit_location
   4812 		{
   4813 			const ResourceDefinition::Node::SharedPtr layout	(new ResourceDefinition::LayoutQualifier(output, glu::Layout(2)));
   4814 			const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(layout));
   4815 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   4816 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array_explicit_location"));
   4817 		}
   4818 	}
   4819 
   4820 	// fragment last stage
   4821 	if (presentShadersMask & (1 << glu::SHADERTYPE_FRAGMENT))
   4822 	{
   4823 		// .var
   4824 		{
   4825 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4));
   4826 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var"));
   4827 		}
   4828 		// .var_explicit_location
   4829 		{
   4830 			const ResourceDefinition::Node::SharedPtr layout	(new ResourceDefinition::LayoutQualifier(output, glu::Layout(2)));
   4831 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4));
   4832 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location"));
   4833 		}
   4834 		// .var_array
   4835 		{
   4836 			const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(output));
   4837 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   4838 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array"));
   4839 		}
   4840 		// .var_array_explicit_location
   4841 		{
   4842 			const ResourceDefinition::Node::SharedPtr layout	(new ResourceDefinition::LayoutQualifier(output, glu::Layout(1)));
   4843 			const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(layout));
   4844 			const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   4845 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array_explicit_location"));
   4846 		}
   4847 	}
   4848 }
   4849 
   4850 static void generateProgramInputOutputReferencedByCases (Context& context, tcu::TestCaseGroup* targetGroup, glu::Storage storage)
   4851 {
   4852 	targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_vertex_fragment",		"",	storage,	ProgramInputOutputReferencedByCase::CASE_VERTEX_FRAGMENT));
   4853 	targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_separable_vertex",		"",	storage,	ProgramInputOutputReferencedByCase::CASE_SEPARABLE_VERTEX));
   4854 	targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_separable_fragment",	"",	storage,	ProgramInputOutputReferencedByCase::CASE_SEPARABLE_FRAGMENT));
   4855 }
   4856 
   4857 static void generateProgramInputTypeBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup)
   4858 {
   4859 	static const glu::DataType variableTypes[] =
   4860 	{
   4861 		glu::TYPE_FLOAT,
   4862 		glu::TYPE_INT,
   4863 		glu::TYPE_UINT,
   4864 
   4865 		glu::TYPE_FLOAT_VEC2,
   4866 		glu::TYPE_FLOAT_VEC3,
   4867 		glu::TYPE_FLOAT_VEC4,
   4868 
   4869 		glu::TYPE_INT_VEC2,
   4870 		glu::TYPE_INT_VEC3,
   4871 		glu::TYPE_INT_VEC4,
   4872 
   4873 		glu::TYPE_UINT_VEC2,
   4874 		glu::TYPE_UINT_VEC3,
   4875 		glu::TYPE_UINT_VEC4,
   4876 
   4877 		glu::TYPE_FLOAT_MAT2,
   4878 		glu::TYPE_FLOAT_MAT2X3,
   4879 		glu::TYPE_FLOAT_MAT2X4,
   4880 		glu::TYPE_FLOAT_MAT3X2,
   4881 		glu::TYPE_FLOAT_MAT3,
   4882 		glu::TYPE_FLOAT_MAT3X4,
   4883 		glu::TYPE_FLOAT_MAT4X2,
   4884 		glu::TYPE_FLOAT_MAT4X3,
   4885 		glu::TYPE_FLOAT_MAT4,
   4886 	};
   4887 
   4888 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
   4889 	{
   4890 		const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx]));
   4891 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_TYPE)));
   4892 	}
   4893 }
   4894 
   4895 static void generateProgramInputTypeBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
   4896 {
   4897 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   4898 	const ResourceDefinition::Node::SharedPtr	input			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_IN));
   4899 
   4900 	// vertex first stage
   4901 	if (presentShadersMask & (1 << glu::SHADERTYPE_VERTEX))
   4902 	{
   4903 		// Only basic types (and no booleans)
   4904 		generateProgramInputTypeBasicTypeCases(context, input, targetGroup);
   4905 	}
   4906 
   4907 	// fragment first stage
   4908 	if (presentShadersMask == (1 << glu::SHADERTYPE_FRAGMENT))
   4909 	{
   4910 		const ResourceDefinition::Node::SharedPtr flatShading(new ResourceDefinition::InterpolationQualifier(input, glu::INTERPOLATION_FLAT));
   4911 
   4912 		// Only basic types, arrays of basic types, struct of basic types (and no booleans)
   4913 		{
   4914 			tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic types");
   4915 			targetGroup->addChild(blockGroup);
   4916 			generateProgramInputTypeBasicTypeCases(context, flatShading, blockGroup);
   4917 		}
   4918 		{
   4919 			const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(flatShading));
   4920 			tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "array", "Array types");
   4921 
   4922 			targetGroup->addChild(blockGroup);
   4923 			generateProgramInputTypeBasicTypeCases(context, arrayElement, blockGroup);
   4924 		}
   4925 		{
   4926 			const ResourceDefinition::Node::SharedPtr	structMember	(new ResourceDefinition::StructMember(flatShading));
   4927 			tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "struct", "Struct types");
   4928 
   4929 			targetGroup->addChild(blockGroup);
   4930 			generateProgramInputTypeBasicTypeCases(context, structMember, blockGroup);
   4931 		}
   4932 	}
   4933 }
   4934 
   4935 static void generateProgramOutputTypeBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, bool addMatrixCases)
   4936 {
   4937 	static const glu::DataType variableTypes[] =
   4938 	{
   4939 		glu::TYPE_FLOAT,
   4940 		glu::TYPE_INT,
   4941 		glu::TYPE_UINT,
   4942 
   4943 		glu::TYPE_FLOAT_VEC2,
   4944 		glu::TYPE_FLOAT_VEC3,
   4945 		glu::TYPE_FLOAT_VEC4,
   4946 
   4947 		glu::TYPE_INT_VEC2,
   4948 		glu::TYPE_INT_VEC3,
   4949 		glu::TYPE_INT_VEC4,
   4950 
   4951 		glu::TYPE_UINT_VEC2,
   4952 		glu::TYPE_UINT_VEC3,
   4953 		glu::TYPE_UINT_VEC4,
   4954 
   4955 		glu::TYPE_FLOAT_MAT2,
   4956 		glu::TYPE_FLOAT_MAT2X3,
   4957 		glu::TYPE_FLOAT_MAT2X4,
   4958 		glu::TYPE_FLOAT_MAT3X2,
   4959 		glu::TYPE_FLOAT_MAT3,
   4960 		glu::TYPE_FLOAT_MAT3X4,
   4961 		glu::TYPE_FLOAT_MAT4X2,
   4962 		glu::TYPE_FLOAT_MAT4X3,
   4963 		glu::TYPE_FLOAT_MAT4,
   4964 	};
   4965 
   4966 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
   4967 	{
   4968 		if (addMatrixCases || !glu::isDataTypeMatrix(variableTypes[ndx]))
   4969 		{
   4970 			const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx]));
   4971 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_TYPE)));
   4972 		}
   4973 	}
   4974 }
   4975 
   4976 static void generateProgramOutputTypeBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
   4977 {
   4978 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   4979 	const ResourceDefinition::Node::SharedPtr	output			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT));
   4980 
   4981 	// vertex last stage
   4982 	if (presentShadersMask == (1 << glu::SHADERTYPE_VERTEX))
   4983 	{
   4984 		const ResourceDefinition::Node::SharedPtr flatShading(new ResourceDefinition::InterpolationQualifier(output, glu::INTERPOLATION_FLAT));
   4985 
   4986 		// Only basic types, arrays of basic types, struct of basic types (and no booleans)
   4987 		{
   4988 			tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic types");
   4989 			targetGroup->addChild(blockGroup);
   4990 			generateProgramOutputTypeBasicTypeCases(context, flatShading, blockGroup, true);
   4991 		}
   4992 		{
   4993 			const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(flatShading));
   4994 			tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "array", "Array types");
   4995 
   4996 			targetGroup->addChild(blockGroup);
   4997 			generateProgramOutputTypeBasicTypeCases(context, arrayElement, blockGroup, true);
   4998 		}
   4999 		{
   5000 			const ResourceDefinition::Node::SharedPtr	structMember	(new ResourceDefinition::StructMember(flatShading));
   5001 			tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "struct", "Struct types");
   5002 
   5003 			targetGroup->addChild(blockGroup);
   5004 			generateProgramOutputTypeBasicTypeCases(context, structMember, blockGroup, true);
   5005 		}
   5006 	}
   5007 
   5008 	// fragment last stage
   5009 	if (presentShadersMask & (1 << glu::SHADERTYPE_FRAGMENT))
   5010 	{
   5011 		// only basic type and basic type array (and no booleans or matrices)
   5012 		{
   5013 			tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic types");
   5014 			targetGroup->addChild(blockGroup);
   5015 			generateProgramOutputTypeBasicTypeCases(context, output, blockGroup, false);
   5016 		}
   5017 		{
   5018 			const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(output));
   5019 			tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "array", "Array types");
   5020 
   5021 			targetGroup->addChild(blockGroup);
   5022 			generateProgramOutputTypeBasicTypeCases(context, arrayElement, blockGroup, false);
   5023 		}
   5024 	}
   5025 }
   5026 
   5027 class ProgramInputTestGroup : public TestCaseGroup
   5028 {
   5029 public:
   5030 			ProgramInputTestGroup	(Context& context);
   5031 	void	init					(void);
   5032 };
   5033 
   5034 ProgramInputTestGroup::ProgramInputTestGroup (Context& context)
   5035 	: TestCaseGroup(context, "program_input", "Program input")
   5036 {
   5037 }
   5038 
   5039 void ProgramInputTestGroup::init (void)
   5040 {
   5041 	// .resource_list
   5042 	{
   5043 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "resource_list", "Resource list");
   5044 		addChild(blockGroup);
   5045 		generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, true, true, generateProgramInputResourceListBlockContents);
   5046 	}
   5047 
   5048 	// .array_size
   5049 	{
   5050 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "array_size", "Array size");
   5051 		addChild(blockGroup);
   5052 		generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, false, true, generateProgramInputBasicBlockContents<PROGRAMRESOURCEPROP_ARRAY_SIZE>);
   5053 	}
   5054 
   5055 	// .location
   5056 	{
   5057 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "location", "Location");
   5058 		addChild(blockGroup);
   5059 		generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, false, true, generateProgramInputLocationBlockContents);
   5060 	}
   5061 
   5062 	// .name_length
   5063 	{
   5064 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "name_length", "Name length");
   5065 		addChild(blockGroup);
   5066 		generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, false, true, generateProgramInputBasicBlockContents<PROGRAMRESOURCEPROP_NAME_LENGTH>);
   5067 	}
   5068 
   5069 	// .referenced_by
   5070 	{
   5071 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "referenced_by", "Reference by shader");
   5072 		addChild(blockGroup);
   5073 		generateProgramInputOutputReferencedByCases(m_context, blockGroup, glu::STORAGE_IN);
   5074 	}
   5075 
   5076 	// .type
   5077 	{
   5078 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "type", "Type");
   5079 		addChild(blockGroup);
   5080 		generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, true, true, generateProgramInputTypeBlockContents);
   5081 	}
   5082 }
   5083 
   5084 class ProgramOutputTestGroup : public TestCaseGroup
   5085 {
   5086 public:
   5087 			ProgramOutputTestGroup	(Context& context);
   5088 	void	init					(void);
   5089 };
   5090 
   5091 ProgramOutputTestGroup::ProgramOutputTestGroup (Context& context)
   5092 	: TestCaseGroup(context, "program_output", "Program output")
   5093 {
   5094 }
   5095 
   5096 void ProgramOutputTestGroup::init (void)
   5097 {
   5098 	// .resource_list
   5099 	{
   5100 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "resource_list", "Resource list");
   5101 		addChild(blockGroup);
   5102 		generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, true, false, generateProgramOutputResourceListBlockContents);
   5103 	}
   5104 
   5105 	// .array_size
   5106 	{
   5107 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "array_size", "Array size");
   5108 		addChild(blockGroup);
   5109 		generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, false, false, generateProgramOutputBasicBlockContents<PROGRAMRESOURCEPROP_ARRAY_SIZE>);
   5110 	}
   5111 
   5112 	// .location
   5113 	{
   5114 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "location", "Location");
   5115 		addChild(blockGroup);
   5116 		generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, false, false, generateProgramOutputLocationBlockContents);
   5117 	}
   5118 
   5119 	// .name_length
   5120 	{
   5121 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "name_length", "Name length");
   5122 		addChild(blockGroup);
   5123 		generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, false, false, generateProgramOutputBasicBlockContents<PROGRAMRESOURCEPROP_NAME_LENGTH>);
   5124 	}
   5125 
   5126 	// .referenced_by
   5127 	{
   5128 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "referenced_by", "Reference by shader");
   5129 		addChild(blockGroup);
   5130 		generateProgramInputOutputReferencedByCases(m_context, blockGroup, glu::STORAGE_OUT);
   5131 	}
   5132 
   5133 	// .type
   5134 	{
   5135 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "type", "Type");
   5136 		addChild(blockGroup);
   5137 		generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, true, false, generateProgramOutputTypeBlockContents);
   5138 	}
   5139 }
   5140 
   5141 static void generateTransformFeedbackShaderCaseBlocks (Context& context, tcu::TestCaseGroup* targetGroup, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*))
   5142 {
   5143 	// .vertex_fragment
   5144 	{
   5145 		tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "vertex_fragment", "Vertex and fragment");
   5146 		const ResourceDefinition::Node::SharedPtr	program			(new ResourceDefinition::Program(false));
   5147 		ResourceDefinition::ShaderSet*				shaderSetPtr	= new ResourceDefinition::ShaderSet(program, glu::GLSL_VERSION_310_ES);
   5148 		const ResourceDefinition::Node::SharedPtr	shaderSet		(shaderSetPtr);
   5149 
   5150 		shaderSetPtr->setStage(glu::SHADERTYPE_VERTEX, true);
   5151 		shaderSetPtr->setStage(glu::SHADERTYPE_FRAGMENT, false);
   5152 
   5153 		targetGroup->addChild(blockGroup);
   5154 
   5155 		blockContentGenerator(context, shaderSet, blockGroup);
   5156 	}
   5157 
   5158 	// .separable_vertex
   5159 	{
   5160 		tcu::TestCaseGroup* const					blockGroup	= new TestCaseGroup(context, "separable_vertex", "Separable vertex");
   5161 		const ResourceDefinition::Node::SharedPtr	program		(new ResourceDefinition::Program(true));
   5162 		const ResourceDefinition::Node::SharedPtr	shader		(new ResourceDefinition::Shader(program, glu::SHADERTYPE_VERTEX, glu::GLSL_VERSION_310_ES));
   5163 
   5164 		targetGroup->addChild(blockGroup);
   5165 
   5166 		blockContentGenerator(context, shader, blockGroup);
   5167 	}
   5168 }
   5169 
   5170 static void generateTransformFeedbackResourceListBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup)
   5171 {
   5172 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   5173 	const ResourceDefinition::Node::SharedPtr	output			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT));
   5174 
   5175 	// .builtin_gl_position
   5176 	{
   5177 		const ResourceDefinition::Node::SharedPtr xfbTarget(new ResourceDefinition::TransformFeedbackTarget(defaultBlock, "gl_Position"));
   5178 		targetGroup->addChild(new FeedbackResourceListTestCase(context, xfbTarget, "builtin_gl_position"));
   5179 	}
   5180 	// .default_block_basic_type
   5181 	{
   5182 		const ResourceDefinition::Node::SharedPtr xfbTarget	(new ResourceDefinition::TransformFeedbackTarget(output));
   5183 		const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4));
   5184 		targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_basic_type"));
   5185 	}
   5186 	// .default_block_struct
   5187 	{
   5188 		const ResourceDefinition::Node::SharedPtr xfbTarget	(new ResourceDefinition::TransformFeedbackTarget(output));
   5189 		const ResourceDefinition::Node::SharedPtr structMbr	(new ResourceDefinition::StructMember(xfbTarget));
   5190 		const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
   5191 		targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_struct"));
   5192 	}
   5193 	// .default_block_struct_member
   5194 	{
   5195 		const ResourceDefinition::Node::SharedPtr structMbr	(new ResourceDefinition::StructMember(output));
   5196 		const ResourceDefinition::Node::SharedPtr xfbTarget	(new ResourceDefinition::TransformFeedbackTarget(structMbr));
   5197 		const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4));
   5198 		targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_struct_member"));
   5199 	}
   5200 	// .default_block_array
   5201 	{
   5202 		const ResourceDefinition::Node::SharedPtr xfbTarget	(new ResourceDefinition::TransformFeedbackTarget(output));
   5203 		const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(xfbTarget));
   5204 		const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   5205 		targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_array"));
   5206 	}
   5207 	// .default_block_array_element
   5208 	{
   5209 		const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(output));
   5210 		const ResourceDefinition::Node::SharedPtr xfbTarget	(new ResourceDefinition::TransformFeedbackTarget(arrayElem));
   5211 		const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4));
   5212 		targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_array_element"));
   5213 	}
   5214 }
   5215 
   5216 template <ProgramResourcePropFlags TargetProp>
   5217 static void generateTransformFeedbackVariableBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup)
   5218 {
   5219 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   5220 	const ResourceDefinition::Node::SharedPtr	output			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT));
   5221 
   5222 	// .builtin_gl_position
   5223 	{
   5224 		const ResourceDefinition::Node::SharedPtr xfbTarget(new ResourceDefinition::TransformFeedbackTarget(defaultBlock, "gl_Position"));
   5225 		targetGroup->addChild(new ResourceTestCase(context, xfbTarget, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "builtin_gl_position"));
   5226 	}
   5227 	// .default_block_basic_type
   5228 	{
   5229 		const ResourceDefinition::Node::SharedPtr xfbTarget	(new ResourceDefinition::TransformFeedbackTarget(output));
   5230 		const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4));
   5231 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_basic_type"));
   5232 	}
   5233 	// .default_block_struct
   5234 	{
   5235 		const ResourceDefinition::Node::SharedPtr xfbTarget	(new ResourceDefinition::TransformFeedbackTarget(output));
   5236 		const ResourceDefinition::Node::SharedPtr structMbr	(new ResourceDefinition::StructMember(xfbTarget));
   5237 		const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
   5238 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_struct"));
   5239 	}
   5240 	// .default_block_struct_member
   5241 	{
   5242 		const ResourceDefinition::Node::SharedPtr structMbr	(new ResourceDefinition::StructMember(output));
   5243 		const ResourceDefinition::Node::SharedPtr xfbTarget	(new ResourceDefinition::TransformFeedbackTarget(structMbr));
   5244 		const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4));
   5245 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_struct_member"));
   5246 	}
   5247 	// .default_block_array
   5248 	{
   5249 		const ResourceDefinition::Node::SharedPtr xfbTarget	(new ResourceDefinition::TransformFeedbackTarget(output));
   5250 		const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(xfbTarget));
   5251 		const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
   5252 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_array"));
   5253 	}
   5254 	// .default_block_array_element
   5255 	{
   5256 		const ResourceDefinition::Node::SharedPtr arrayElem	(new ResourceDefinition::ArrayElement(output));
   5257 		const ResourceDefinition::Node::SharedPtr xfbTarget	(new ResourceDefinition::TransformFeedbackTarget(arrayElem));
   5258 		const ResourceDefinition::Node::SharedPtr variable	(new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4));
   5259 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_array_element"));
   5260 	}
   5261 }
   5262 
   5263 static void generateTransformFeedbackVariableBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup)
   5264 {
   5265 	static const glu::DataType variableTypes[] =
   5266 	{
   5267 		glu::TYPE_FLOAT,
   5268 		glu::TYPE_INT,
   5269 		glu::TYPE_UINT,
   5270 
   5271 		glu::TYPE_FLOAT_VEC2,
   5272 		glu::TYPE_FLOAT_VEC3,
   5273 		glu::TYPE_FLOAT_VEC4,
   5274 
   5275 		glu::TYPE_INT_VEC2,
   5276 		glu::TYPE_INT_VEC3,
   5277 		glu::TYPE_INT_VEC4,
   5278 
   5279 		glu::TYPE_UINT_VEC2,
   5280 		glu::TYPE_UINT_VEC3,
   5281 		glu::TYPE_UINT_VEC4,
   5282 
   5283 		glu::TYPE_FLOAT_MAT2,
   5284 		glu::TYPE_FLOAT_MAT2X3,
   5285 		glu::TYPE_FLOAT_MAT2X4,
   5286 		glu::TYPE_FLOAT_MAT3X2,
   5287 		glu::TYPE_FLOAT_MAT3,
   5288 		glu::TYPE_FLOAT_MAT3X4,
   5289 		glu::TYPE_FLOAT_MAT4X2,
   5290 		glu::TYPE_FLOAT_MAT4X3,
   5291 		glu::TYPE_FLOAT_MAT4,
   5292 	};
   5293 
   5294 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
   5295 	{
   5296 		const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx]));
   5297 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, PROGRAMRESOURCEPROP_TYPE)));
   5298 	}
   5299 }
   5300 
   5301 static void generateTransformFeedbackVariableTypeBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup)
   5302 {
   5303 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   5304 	const ResourceDefinition::Node::SharedPtr	output			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT));
   5305 	const ResourceDefinition::Node::SharedPtr	flatShading		(new ResourceDefinition::InterpolationQualifier(output, glu::INTERPOLATION_FLAT));
   5306 
   5307 	// Only builtins, basic types, arrays of basic types, struct of basic types (and no booleans)
   5308 	{
   5309 		const ResourceDefinition::Node::SharedPtr	xfbTarget		(new ResourceDefinition::TransformFeedbackTarget(defaultBlock, "gl_Position"));
   5310 		tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "builtin", "Built-in outputs");
   5311 
   5312 		targetGroup->addChild(blockGroup);
   5313 		blockGroup->addChild(new ResourceTestCase(context, xfbTarget, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, PROGRAMRESOURCEPROP_TYPE), "gl_position"));
   5314 	}
   5315 	{
   5316 		const ResourceDefinition::Node::SharedPtr	xfbTarget		(new ResourceDefinition::TransformFeedbackTarget(flatShading));
   5317 		tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "basic_type", "Basic types");
   5318 
   5319 		targetGroup->addChild(blockGroup);
   5320 		generateTransformFeedbackVariableBasicTypeCases(context, xfbTarget, blockGroup);
   5321 	}
   5322 	{
   5323 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(flatShading));
   5324 		const ResourceDefinition::Node::SharedPtr	xfbTarget		(new ResourceDefinition::TransformFeedbackTarget(arrayElement));
   5325 		tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "array", "Array types");
   5326 
   5327 		targetGroup->addChild(blockGroup);
   5328 		generateTransformFeedbackVariableBasicTypeCases(context, xfbTarget, blockGroup);
   5329 	}
   5330 	{
   5331 		const ResourceDefinition::Node::SharedPtr	xfbTarget		(new ResourceDefinition::TransformFeedbackTarget(flatShading));
   5332 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(xfbTarget));
   5333 		tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "whole_array", "Whole array");
   5334 
   5335 		targetGroup->addChild(blockGroup);
   5336 		generateTransformFeedbackVariableBasicTypeCases(context, arrayElement, blockGroup);
   5337 	}
   5338 	{
   5339 		const ResourceDefinition::Node::SharedPtr	structMember	(new ResourceDefinition::StructMember(flatShading));
   5340 		const ResourceDefinition::Node::SharedPtr	xfbTarget		(new ResourceDefinition::TransformFeedbackTarget(structMember));
   5341 		tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "struct", "Struct types");
   5342 
   5343 		targetGroup->addChild(blockGroup);
   5344 		generateTransformFeedbackVariableBasicTypeCases(context, xfbTarget, blockGroup);
   5345 	}
   5346 }
   5347 
   5348 class TransformFeedbackVaryingTestGroup : public TestCaseGroup
   5349 {
   5350 public:
   5351 			TransformFeedbackVaryingTestGroup	(Context& context);
   5352 	void	init								(void);
   5353 };
   5354 
   5355 TransformFeedbackVaryingTestGroup::TransformFeedbackVaryingTestGroup (Context& context)
   5356 	: TestCaseGroup(context, "transform_feedback_varying", "Transform feedback varyings")
   5357 {
   5358 }
   5359 
   5360 void TransformFeedbackVaryingTestGroup::init (void)
   5361 {
   5362 	// .resource_list
   5363 	{
   5364 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "resource_list", "Resource list");
   5365 		addChild(blockGroup);
   5366 		generateTransformFeedbackShaderCaseBlocks(m_context, blockGroup, generateTransformFeedbackResourceListBlockContents);
   5367 	}
   5368 
   5369 	// .array_size
   5370 	{
   5371 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "array_size", "Array size");
   5372 		addChild(blockGroup);
   5373 		generateTransformFeedbackShaderCaseBlocks(m_context, blockGroup, generateTransformFeedbackVariableBlockContents<PROGRAMRESOURCEPROP_ARRAY_SIZE>);
   5374 	}
   5375 
   5376 	// .name_length
   5377 	{
   5378 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "name_length", "Name length");
   5379 		addChild(blockGroup);
   5380 		generateTransformFeedbackShaderCaseBlocks(m_context, blockGroup, generateTransformFeedbackVariableBlockContents<PROGRAMRESOURCEPROP_NAME_LENGTH>);
   5381 	}
   5382 
   5383 	// .type
   5384 	{
   5385 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "type", "Type");
   5386 		addChild(blockGroup);
   5387 		generateTransformFeedbackShaderCaseBlocks(m_context, blockGroup, generateTransformFeedbackVariableTypeBlockContents);
   5388 	}
   5389 }
   5390 
   5391 static void generateBufferVariableBufferCaseBlocks (Context& context, tcu::TestCaseGroup* targetGroup, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*))
   5392 {
   5393 	const ResourceDefinition::Node::SharedPtr	program			(new ResourceDefinition::Program());
   5394 	const ResourceDefinition::Node::SharedPtr	shader			(new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES));
   5395 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(shader));
   5396 	const ResourceDefinition::Node::SharedPtr	bufferStorage	(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER));
   5397 	const ResourceDefinition::Node::SharedPtr	binding			(new ResourceDefinition::LayoutQualifier(bufferStorage, glu::Layout(-1, 0)));
   5398 
   5399 	// .named_block
   5400 	{
   5401 		const ResourceDefinition::Node::SharedPtr	buffer		(new ResourceDefinition::InterfaceBlock(binding, true));
   5402 		tcu::TestCaseGroup* const					blockGroup	= new TestCaseGroup(context, "named_block", "Named block");
   5403 
   5404 		targetGroup->addChild(blockGroup);
   5405 
   5406 		blockContentGenerator(context, buffer, blockGroup);
   5407 	}
   5408 
   5409 	// .unnamed_block
   5410 	{
   5411 		const ResourceDefinition::Node::SharedPtr	buffer		(new ResourceDefinition::InterfaceBlock(binding, false));
   5412 		tcu::TestCaseGroup* const					blockGroup	= new TestCaseGroup(context, "unnamed_block", "Unnamed block");
   5413 
   5414 		targetGroup->addChild(blockGroup);
   5415 
   5416 		blockContentGenerator(context, buffer, blockGroup);
   5417 	}
   5418 
   5419 	// .block_array
   5420 	{
   5421 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(binding));
   5422 		const ResourceDefinition::Node::SharedPtr	buffer			(new ResourceDefinition::InterfaceBlock(arrayElement, true));
   5423 		tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "block_array", "Block array");
   5424 
   5425 		targetGroup->addChild(blockGroup);
   5426 
   5427 		blockContentGenerator(context, buffer, blockGroup);
   5428 	}
   5429 }
   5430 
   5431 static void generateBufferVariableResourceListBlockContentsProxy (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
   5432 {
   5433 	generateBufferBackedResourceListBlockContentCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, 4);
   5434 }
   5435 
   5436 static void generateBufferVariableArraySizeSubCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, ProgramResourcePropFlags targetProp, bool sizedArray, bool extendedCases)
   5437 {
   5438 	const ProgramResourceQueryTestTarget	queryTarget		(PROGRAMINTERFACE_BUFFER_VARIABLE, targetProp);
   5439 	tcu::TestCaseGroup*						aggregateGroup;
   5440 
   5441 	// .types
   5442 	if (extendedCases)
   5443 	{
   5444 		tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types");
   5445 		targetGroup->addChild(blockGroup);
   5446 
   5447 		generateVariableCases(context, parentStructure, blockGroup, queryTarget, (sizedArray) ? (2) : (1), false);
   5448 	}
   5449 
   5450 	// .aggregates
   5451 	if (extendedCases)
   5452 	{
   5453 		aggregateGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types");
   5454 		targetGroup->addChild(aggregateGroup);
   5455 	}
   5456 	else
   5457 		aggregateGroup = targetGroup;
   5458 
   5459 	// .float_*
   5460 	generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_FLOAT, (extendedCases && sizedArray) ? (2) : (1), !extendedCases);
   5461 
   5462 	// .bool_*
   5463 	generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_BOOL, (extendedCases && sizedArray) ? (1) : (0), !extendedCases);
   5464 
   5465 	// .bvec3_*
   5466 	generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_BOOL_VEC3, (extendedCases && sizedArray) ? (2) : (1), !extendedCases);
   5467 
   5468 	// .vec4_*
   5469 	generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_FLOAT_VEC4, (extendedCases && sizedArray) ? (2) : (1), !extendedCases);
   5470 
   5471 	// .ivec2_*
   5472 	generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_INT_VEC2, (extendedCases && sizedArray) ? (2) : (1), !extendedCases);
   5473 }
   5474 
   5475 template <ProgramResourcePropFlags TargetProp>
   5476 static void generateBufferVariableArrayCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
   5477 {
   5478 	const ProgramResourceQueryTestTarget	queryTarget			(PROGRAMINTERFACE_BUFFER_VARIABLE, TargetProp);
   5479 	const bool								namedNonArrayBlock	= static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named && parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT;
   5480 
   5481 	// .non_array
   5482 	if (namedNonArrayBlock)
   5483 	{
   5484 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "non_array", "Non-array target");
   5485 		targetGroup->addChild(blockGroup);
   5486 
   5487 		generateVariableCases(context, parentStructure, blockGroup, queryTarget, 1, false);
   5488 	}
   5489 
   5490 	// .sized
   5491 	{
   5492 		const ResourceDefinition::Node::SharedPtr	sized		(new ResourceDefinition::ArrayElement(parentStructure));
   5493 		tcu::TestCaseGroup* const					blockGroup	= new TestCaseGroup(context, "sized", "Sized target");
   5494 		targetGroup->addChild(blockGroup);
   5495 
   5496 		generateBufferVariableArraySizeSubCases(context, sized, blockGroup, TargetProp, true, namedNonArrayBlock);
   5497 	}
   5498 
   5499 	// .unsized
   5500 	{
   5501 		const ResourceDefinition::Node::SharedPtr	unsized		(new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
   5502 		tcu::TestCaseGroup* const					blockGroup	= new TestCaseGroup(context, "unsized", "Unsized target");
   5503 		targetGroup->addChild(blockGroup);
   5504 
   5505 		generateBufferVariableArraySizeSubCases(context, unsized, blockGroup, TargetProp, false, namedNonArrayBlock);
   5506 	}
   5507 }
   5508 
   5509 static void generateBufferVariableBlockIndexCases (Context& context, tcu::TestCaseGroup* const targetGroup)
   5510 {
   5511 	const ResourceDefinition::Node::SharedPtr	program			(new ResourceDefinition::Program());
   5512 	const ResourceDefinition::Node::SharedPtr	shader			(new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES));
   5513 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(shader));
   5514 	const ResourceDefinition::Node::SharedPtr	bufferStorage	(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER));
   5515 	const ResourceDefinition::Node::SharedPtr	binding			(new ResourceDefinition::LayoutQualifier(bufferStorage, glu::Layout(-1, 0)));
   5516 
   5517 	// .named_block
   5518 	{
   5519 		const ResourceDefinition::Node::SharedPtr	buffer		(new ResourceDefinition::InterfaceBlock(binding, true));
   5520 		const ResourceDefinition::Node::SharedPtr	variable	(new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4));
   5521 
   5522 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_BLOCK_INDEX), "named_block"));
   5523 	}
   5524 
   5525 	// .unnamed_block
   5526 	{
   5527 		const ResourceDefinition::Node::SharedPtr	buffer		(new ResourceDefinition::InterfaceBlock(binding, false));
   5528 		const ResourceDefinition::Node::SharedPtr	variable	(new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4));
   5529 
   5530 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_BLOCK_INDEX), "unnamed_block"));
   5531 	}
   5532 
   5533 	// .block_array
   5534 	{
   5535 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(binding));
   5536 		const ResourceDefinition::Node::SharedPtr	buffer			(new ResourceDefinition::InterfaceBlock(arrayElement, true));
   5537 		const ResourceDefinition::Node::SharedPtr	variable		(new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4));
   5538 
   5539 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_BLOCK_INDEX), "block_array"));
   5540 	}
   5541 }
   5542 
   5543 static void generateBufferVariableMatrixCaseBlocks (Context& context, tcu::TestCaseGroup* const targetGroup, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*, bool))
   5544 {
   5545 	static const struct
   5546 	{
   5547 		const char*			name;
   5548 		const char*			description;
   5549 		bool				namedBlock;
   5550 		bool				extendedBasicTypeCases;
   5551 		glu::MatrixOrder	order;
   5552 	} children[] =
   5553 	{
   5554 		{ "named_block",				"Named uniform block",		true,	true,	glu::MATRIXORDER_LAST			},
   5555 		{ "named_block_row_major",		"Named uniform block",		true,	false,	glu::MATRIXORDER_ROW_MAJOR		},
   5556 		{ "named_block_col_major",		"Named uniform block",		true,	false,	glu::MATRIXORDER_COLUMN_MAJOR	},
   5557 		{ "unnamed_block",				"Unnamed uniform block",	false,	false,	glu::MATRIXORDER_LAST			},
   5558 		{ "unnamed_block_row_major",	"Unnamed uniform block",	false,	false,	glu::MATRIXORDER_ROW_MAJOR		},
   5559 		{ "unnamed_block_col_major",	"Unnamed uniform block",	false,	false,	glu::MATRIXORDER_COLUMN_MAJOR	},
   5560 	};
   5561 
   5562 	const ResourceDefinition::Node::SharedPtr	program			(new ResourceDefinition::Program());
   5563 	const ResourceDefinition::Node::SharedPtr	shader			(new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES));
   5564 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(shader));
   5565 	const ResourceDefinition::Node::SharedPtr	buffer			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER));
   5566 
   5567 	for (int childNdx = 0; childNdx < (int)DE_LENGTH_OF_ARRAY(children); ++childNdx)
   5568 	{
   5569 		ResourceDefinition::Node::SharedPtr	parentStructure	= buffer;
   5570 		tcu::TestCaseGroup* const			blockGroup		= new TestCaseGroup(context, children[childNdx].name, children[childNdx].description);
   5571 
   5572 		targetGroup->addChild(blockGroup);
   5573 
   5574 		if (children[childNdx].order != glu::MATRIXORDER_LAST)
   5575 		{
   5576 			glu::Layout layout;
   5577 			layout.matrixOrder = children[childNdx].order;
   5578 			parentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(parentStructure, layout));
   5579 		}
   5580 
   5581 		parentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::InterfaceBlock(parentStructure, children[childNdx].namedBlock));
   5582 
   5583 		blockContentGenerator(context, parentStructure, blockGroup, children[childNdx].extendedBasicTypeCases);
   5584 	}
   5585 }
   5586 
   5587 static void generateBufferVariableMatrixVariableBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, ProgramResourcePropFlags targetProp)
   5588 {
   5589 	// all matrix types and some non-matrix
   5590 
   5591 	static const glu::DataType variableTypes[] =
   5592 	{
   5593 		glu::TYPE_FLOAT,
   5594 		glu::TYPE_INT_VEC3,
   5595 		glu::TYPE_FLOAT_MAT2,
   5596 		glu::TYPE_FLOAT_MAT2X3,
   5597 		glu::TYPE_FLOAT_MAT2X4,
   5598 		glu::TYPE_FLOAT_MAT3X2,
   5599 		glu::TYPE_FLOAT_MAT3,
   5600 		glu::TYPE_FLOAT_MAT3X4,
   5601 		glu::TYPE_FLOAT_MAT4X2,
   5602 		glu::TYPE_FLOAT_MAT4X3,
   5603 		glu::TYPE_FLOAT_MAT4,
   5604 	};
   5605 
   5606 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
   5607 	{
   5608 		const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx]));
   5609 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, targetProp)));
   5610 	}
   5611 }
   5612 
   5613 static void generateBufferVariableMatrixVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, ProgramResourcePropFlags targetProp)
   5614 {
   5615 	// Basic aggregates
   5616 	generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, targetProp, glu::TYPE_FLOAT_MAT3X2, "", 2);
   5617 
   5618 	// Unsized array
   5619 	{
   5620 		const ResourceDefinition::Node::SharedPtr	unsized		(new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
   5621 		const ResourceDefinition::Node::SharedPtr	variable	(new ResourceDefinition::Variable(unsized, glu::TYPE_FLOAT_MAT3X2));
   5622 
   5623 		targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, targetProp), "var_unsized_array"));
   5624 	}
   5625 }
   5626 
   5627 template <ProgramResourcePropFlags TargetProp>
   5628 static void generateBufferVariableMatrixCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, bool extendedTypeCases)
   5629 {
   5630 	// .types
   5631 	if (extendedTypeCases)
   5632 	{
   5633 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "types", "Types");
   5634 		targetGroup->addChild(blockGroup);
   5635 		generateBufferVariableMatrixVariableBasicTypeCases(context, parentStructure, blockGroup, TargetProp);
   5636 	}
   5637 
   5638 	// .no_qualifier
   5639 	{
   5640 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "no_qualifier", "No qualifier");
   5641 		targetGroup->addChild(blockGroup);
   5642 		generateBufferVariableMatrixVariableCases(context, parentStructure, blockGroup, TargetProp);
   5643 	}
   5644 
   5645 	// .column_major
   5646 	{
   5647 		const ResourceDefinition::Node::SharedPtr matrixOrder(new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, -1, -1, glu::FORMATLAYOUT_LAST, glu::MATRIXORDER_COLUMN_MAJOR)));
   5648 
   5649 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "column_major", "Column major qualifier");
   5650 		targetGroup->addChild(blockGroup);
   5651 		generateBufferVariableMatrixVariableCases(context, matrixOrder, blockGroup, TargetProp);
   5652 	}
   5653 
   5654 	// .row_major
   5655 	{
   5656 		const ResourceDefinition::Node::SharedPtr matrixOrder(new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, -1, -1, glu::FORMATLAYOUT_LAST, glu::MATRIXORDER_ROW_MAJOR)));
   5657 
   5658 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "row_major", "Row major qualifier");
   5659 		targetGroup->addChild(blockGroup);
   5660 		generateBufferVariableMatrixVariableCases(context, matrixOrder, blockGroup, TargetProp);
   5661 	}
   5662 }
   5663 
   5664 static void generateBufferVariableNameLengthCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup)
   5665 {
   5666 	// .sized
   5667 	{
   5668 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "sized", "Sized target");
   5669 		targetGroup->addChild(blockGroup);
   5670 
   5671 		generateBufferBackedVariableAggregateTypeCases(context, parentStructure, blockGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_NAME_LENGTH, glu::TYPE_FLOAT, "", 3);
   5672 	}
   5673 
   5674 	// .unsized
   5675 	{
   5676 		const ResourceDefinition::Node::SharedPtr	unsized		(new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
   5677 		tcu::TestCaseGroup* const					blockGroup	= new TestCaseGroup(context, "unsized", "Unsized target");
   5678 		targetGroup->addChild(blockGroup);
   5679 
   5680 		generateBufferBackedVariableAggregateTypeCases(context, unsized, blockGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_NAME_LENGTH, glu::TYPE_FLOAT, "", 2);
   5681 	}
   5682 }
   5683 
   5684 static void generateBufferVariableOffsetCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup)
   5685 {
   5686 	// .sized
   5687 	{
   5688 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "sized", "Sized target");
   5689 		targetGroup->addChild(blockGroup);
   5690 
   5691 		generateBufferBackedVariableAggregateTypeCases(context, parentStructure, blockGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_OFFSET, glu::TYPE_FLOAT, "", 3);
   5692 	}
   5693 
   5694 	// .unsized
   5695 	{
   5696 		const ResourceDefinition::Node::SharedPtr	unsized		(new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
   5697 		tcu::TestCaseGroup* const					blockGroup	= new TestCaseGroup(context, "unsized", "Unsized target");
   5698 		targetGroup->addChild(blockGroup);
   5699 
   5700 		generateBufferBackedVariableAggregateTypeCases(context, unsized, blockGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_OFFSET, glu::TYPE_FLOAT, "", 2);
   5701 	}
   5702 }
   5703 
   5704 static void generateBufferVariableReferencedByBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, int expandLevel)
   5705 {
   5706 	DE_UNREF(expandLevel);
   5707 
   5708 	const ProgramResourceQueryTestTarget		queryTarget		(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER);
   5709 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(parentStructure));
   5710 	const ResourceDefinition::Node::SharedPtr	storage			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER));
   5711 	const bool									singleShaderCase	= parentStructure->getType() == ResourceDefinition::Node::TYPE_SHADER;
   5712 
   5713 	// .named_block
   5714 	{
   5715 		const ResourceDefinition::Node::SharedPtr	buffer		(new ResourceDefinition::InterfaceBlock(storage, true));
   5716 		tcu::TestCaseGroup* const					blockGroup	= new TestCaseGroup(context, "named_block", "Named block");
   5717 
   5718 		targetGroup->addChild(blockGroup);
   5719 
   5720 		generateBufferReferencedByShaderInterfaceBlockCases(context, buffer, blockGroup, queryTarget, singleShaderCase);
   5721 	}
   5722 
   5723 	// .unnamed_block
   5724 	{
   5725 		const ResourceDefinition::Node::SharedPtr	buffer		(new ResourceDefinition::InterfaceBlock(storage, false));
   5726 		tcu::TestCaseGroup* const					blockGroup	= new TestCaseGroup(context, "unnamed_block", "Unnamed block");
   5727 
   5728 		targetGroup->addChild(blockGroup);
   5729 
   5730 		generateBufferReferencedByShaderInterfaceBlockCases(context, buffer, blockGroup, queryTarget, false);
   5731 	}
   5732 
   5733 	// .block_array
   5734 	{
   5735 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(storage));
   5736 		const ResourceDefinition::Node::SharedPtr	buffer			(new ResourceDefinition::InterfaceBlock(arrayElement, true));
   5737 		tcu::TestCaseGroup* const					blockGroup	= new TestCaseGroup(context, "block_array", "Block array");
   5738 
   5739 		targetGroup->addChild(blockGroup);
   5740 
   5741 		generateBufferReferencedByShaderInterfaceBlockCases(context, buffer, blockGroup, queryTarget, false);
   5742 	}
   5743 }
   5744 
   5745 template <ProgramResourcePropFlags TargetProp>
   5746 static void generateBufferVariableTopLevelCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup)
   5747 {
   5748 	// basic and aggregate types
   5749 	generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, TargetProp, glu::TYPE_FLOAT_VEC4, "", 3);
   5750 
   5751 	// basic and aggregate types in an unsized array
   5752 	{
   5753 		const ResourceDefinition::Node::SharedPtr unsized(new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
   5754 
   5755 		generateBufferBackedVariableAggregateTypeCases(context, unsized, targetGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, TargetProp, glu::TYPE_FLOAT_VEC4, "_unsized_array", 2);
   5756 	}
   5757 }
   5758 
   5759 static void generateBufferVariableTypeBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, int expandLevel)
   5760 {
   5761 	static const struct
   5762 	{
   5763 		int				level;
   5764 		glu::DataType	dataType;
   5765 	} variableTypes[] =
   5766 	{
   5767 		{ 0,	glu::TYPE_FLOAT			},
   5768 		{ 1,	glu::TYPE_INT			},
   5769 		{ 1,	glu::TYPE_UINT			},
   5770 		{ 1,	glu::TYPE_BOOL			},
   5771 
   5772 		{ 3,	glu::TYPE_FLOAT_VEC2	},
   5773 		{ 1,	glu::TYPE_FLOAT_VEC3	},
   5774 		{ 1,	glu::TYPE_FLOAT_VEC4	},
   5775 
   5776 		{ 3,	glu::TYPE_INT_VEC2		},
   5777 		{ 2,	glu::TYPE_INT_VEC3		},
   5778 		{ 3,	glu::TYPE_INT_VEC4		},
   5779 
   5780 		{ 3,	glu::TYPE_UINT_VEC2		},
   5781 		{ 2,	glu::TYPE_UINT_VEC3		},
   5782 		{ 3,	glu::TYPE_UINT_VEC4		},
   5783 
   5784 		{ 3,	glu::TYPE_BOOL_VEC2		},
   5785 		{ 2,	glu::TYPE_BOOL_VEC3		},
   5786 		{ 3,	glu::TYPE_BOOL_VEC4		},
   5787 
   5788 		{ 2,	glu::TYPE_FLOAT_MAT2	},
   5789 		{ 3,	glu::TYPE_FLOAT_MAT2X3	},
   5790 		{ 3,	glu::TYPE_FLOAT_MAT2X4	},
   5791 		{ 2,	glu::TYPE_FLOAT_MAT3X2	},
   5792 		{ 2,	glu::TYPE_FLOAT_MAT3	},
   5793 		{ 3,	glu::TYPE_FLOAT_MAT3X4	},
   5794 		{ 2,	glu::TYPE_FLOAT_MAT4X2	},
   5795 		{ 3,	glu::TYPE_FLOAT_MAT4X3	},
   5796 		{ 2,	glu::TYPE_FLOAT_MAT4	},
   5797 	};
   5798 
   5799 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
   5800 	{
   5801 		if (variableTypes[ndx].level <= expandLevel)
   5802 		{
   5803 			const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].dataType));
   5804 			targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_TYPE)));
   5805 		}
   5806 	}
   5807 }
   5808 
   5809 static void generateBufferVariableTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, int depth = 3)
   5810 {
   5811 	// .basic_type
   5812 	if (depth > 0)
   5813 	{
   5814 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic type");
   5815 		targetGroup->addChild(blockGroup);
   5816 		generateBufferVariableTypeBasicTypeCases(context, parentStructure, blockGroup, depth);
   5817 	}
   5818 	else
   5819 	{
   5820 		// flatten bottom-level
   5821 		generateBufferVariableTypeBasicTypeCases(context, parentStructure, targetGroup, depth);
   5822 	}
   5823 
   5824 	// .array
   5825 	if (depth > 0)
   5826 	{
   5827 		const ResourceDefinition::Node::SharedPtr	arrayElement	(new ResourceDefinition::ArrayElement(parentStructure));
   5828 		tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "array", "Arrays");
   5829 
   5830 		targetGroup->addChild(blockGroup);
   5831 		generateBufferVariableTypeCases(context, arrayElement, blockGroup, depth-1);
   5832 	}
   5833 
   5834 	// .struct
   5835 	if (depth > 0)
   5836 	{
   5837 		const ResourceDefinition::Node::SharedPtr	structMember	(new ResourceDefinition::StructMember(parentStructure));
   5838 		tcu::TestCaseGroup* const					blockGroup		= new TestCaseGroup(context, "struct", "Structs");
   5839 
   5840 		targetGroup->addChild(blockGroup);
   5841 		generateBufferVariableTypeCases(context, structMember, blockGroup, depth-1);
   5842 	}
   5843 }
   5844 
   5845 static void generateBufferVariableTypeBlock (Context& context, tcu::TestCaseGroup* targetGroup)
   5846 {
   5847 	const ResourceDefinition::Node::SharedPtr	program			(new ResourceDefinition::Program());
   5848 	const ResourceDefinition::Node::SharedPtr	shader			(new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES));
   5849 	const ResourceDefinition::Node::SharedPtr	defaultBlock	(new ResourceDefinition::DefaultBlock(shader));
   5850 	const ResourceDefinition::Node::SharedPtr	buffer			(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER));
   5851 	const ResourceDefinition::Node::SharedPtr	block			(new ResourceDefinition::InterfaceBlock(buffer, true));
   5852 
   5853 	generateBufferVariableTypeCases(context, block, targetGroup);
   5854 }
   5855 
   5856 static void generateBufferVariableRandomCase (Context& context, tcu::TestCaseGroup* const targetGroup, int index)
   5857 {
   5858 	de::Random									rnd					(index * 0x12345);
   5859 	const ResourceDefinition::Node::SharedPtr	shader				= generateRandomShaderSet(rnd);
   5860 	const glu::DataType							type				= generateRandomDataType(rnd, true);
   5861 	const glu::Layout							layout				= generateRandomVariableLayout(rnd, type, true);
   5862 	const bool									namedBlock			= rnd.getBool();
   5863 	const ResourceDefinition::Node::SharedPtr	defaultBlock		(new ResourceDefinition::DefaultBlock(shader));
   5864 	const ResourceDefinition::Node::SharedPtr	buffer				(new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER));
   5865 	ResourceDefinition::Node::SharedPtr			currentStructure	(new ResourceDefinition::LayoutQualifier(buffer, generateRandomBufferBlockLayout(rnd)));
   5866 
   5867 	if (namedBlock && rnd.getBool())
   5868 		currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::ArrayElement(currentStructure));
   5869 	currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::InterfaceBlock(currentStructure, namedBlock));
   5870 
   5871 	currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(currentStructure, layout));
   5872 	currentStructure = generateRandomVariableDefinition(rnd, currentStructure, type, layout, true);
   5873 
   5874 	targetGroup->addChild(new ResourceTestCase(context, currentStructure, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_BUFFER_VARIABLE_MASK), de::toString(index).c_str()));
   5875 }
   5876 
   5877 static void generateBufferVariableRandomCases (Context& context, tcu::TestCaseGroup* const targetGroup)
   5878 {
   5879 	const int numCases = 40;
   5880 
   5881 	for (int ndx = 0; ndx < numCases; ++ndx)
   5882 		generateBufferVariableRandomCase(context, targetGroup, ndx);
   5883 }
   5884 
   5885 class BufferVariableTestGroup : public TestCaseGroup
   5886 {
   5887 public:
   5888 			BufferVariableTestGroup	(Context& context);
   5889 	void	init								(void);
   5890 };
   5891 
   5892 BufferVariableTestGroup::BufferVariableTestGroup (Context& context)
   5893 	: TestCaseGroup(context, "buffer_variable", "Buffer variable")
   5894 {
   5895 }
   5896 
   5897 void BufferVariableTestGroup::init (void)
   5898 {
   5899 	// .resource_list
   5900 	{
   5901 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "resource_list", "Resource list");
   5902 		addChild(blockGroup);
   5903 		generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableResourceListBlockContentsProxy);
   5904 	}
   5905 
   5906 	// .array_size
   5907 	{
   5908 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "array_size", "Array size");
   5909 		addChild(blockGroup);
   5910 		generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableArrayCases<PROGRAMRESOURCEPROP_ARRAY_SIZE>);
   5911 	}
   5912 
   5913 	// .array_stride
   5914 	{
   5915 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "array_stride", "Array stride");
   5916 		addChild(blockGroup);
   5917 		generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableArrayCases<PROGRAMRESOURCEPROP_ARRAY_STRIDE>);
   5918 	}
   5919 
   5920 	// .block_index
   5921 	{
   5922 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "block_index", "Block index");
   5923 		addChild(blockGroup);
   5924 		generateBufferVariableBlockIndexCases(m_context, blockGroup);
   5925 	}
   5926 
   5927 	// .is_row_major
   5928 	{
   5929 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "is_row_major", "Is row major");
   5930 		addChild(blockGroup);
   5931 		generateBufferVariableMatrixCaseBlocks(m_context, blockGroup, generateBufferVariableMatrixCases<PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR>);
   5932 	}
   5933 
   5934 	// .matrix_stride
   5935 	{
   5936 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "matrix_stride", "Matrix stride");
   5937 		addChild(blockGroup);
   5938 		generateBufferVariableMatrixCaseBlocks(m_context, blockGroup, generateBufferVariableMatrixCases<PROGRAMRESOURCEPROP_MATRIX_STRIDE>);
   5939 	}
   5940 
   5941 	// .name_length
   5942 	{
   5943 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "name_length", "Name length");
   5944 		addChild(blockGroup);
   5945 		generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableNameLengthCases);
   5946 	}
   5947 
   5948 	// .offset
   5949 	{
   5950 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "offset", "Offset");
   5951 		addChild(blockGroup);
   5952 		generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableOffsetCases);
   5953 	}
   5954 
   5955 	// .referenced_by
   5956 	{
   5957 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "referenced_by", "Referenced by");
   5958 		addChild(blockGroup);
   5959 		generateReferencedByShaderCaseBlocks(m_context, blockGroup, generateBufferVariableReferencedByBlockContents);
   5960 	}
   5961 
   5962 	// .top_level_array_size
   5963 	{
   5964 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "top_level_array_size", "Top-level array size");
   5965 		addChild(blockGroup);
   5966 		generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableTopLevelCases<PROGRAMRESOURCEPROP_TOP_LEVEL_ARRAY_SIZE>);
   5967 	}
   5968 
   5969 	// .top_level_array_stride
   5970 	{
   5971 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "top_level_array_stride", "Top-level array stride");
   5972 		addChild(blockGroup);
   5973 		generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableTopLevelCases<PROGRAMRESOURCEPROP_TOP_LEVEL_ARRAY_STRIDE>);
   5974 	}
   5975 
   5976 	// .type
   5977 	{
   5978 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "type", "Type");
   5979 		addChild(blockGroup);
   5980 		generateBufferVariableTypeBlock(m_context, blockGroup);
   5981 	}
   5982 
   5983 	// .random
   5984 	{
   5985 		tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "random", "Random");
   5986 		addChild(blockGroup);
   5987 		generateBufferVariableRandomCases(m_context, blockGroup);
   5988 	}
   5989 }
   5990 
   5991 } // anonymous
   5992 
   5993 ProgramInterfaceQueryTests::ProgramInterfaceQueryTests (Context& context)
   5994 	: TestCaseGroup(context, "program_interface_query", "Program interface query tests")
   5995 {
   5996 }
   5997 
   5998 ProgramInterfaceQueryTests::~ProgramInterfaceQueryTests (void)
   5999 {
   6000 }
   6001 
   6002 void ProgramInterfaceQueryTests::init (void)
   6003 {
   6004 	// Misc queries
   6005 
   6006 	// .buffer_limited_query
   6007 	{
   6008 		tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "buffer_limited_query", "Queries limited by the buffer size");
   6009 
   6010 		addChild(group);
   6011 
   6012 		group->addChild(new ResourceNameBufferLimitCase(m_context, "resource_name_query", "Test GetProgramResourceName with too small a buffer"));
   6013 		group->addChild(new ResourceQueryBufferLimitCase(m_context, "resource_query", "Test GetProgramResourceiv with too small a buffer"));
   6014 	}
   6015 
   6016 	// Interfaces
   6017 
   6018 	// .uniform
   6019 	addChild(new UniformInterfaceTestGroup(m_context));
   6020 
   6021 	// .uniform_block
   6022 	addChild(new BufferBackedBlockInterfaceTestGroup(m_context, glu::STORAGE_UNIFORM));
   6023 
   6024 	// .atomic_counter_buffer
   6025 	addChild(new AtomicCounterTestGroup(m_context));
   6026 
   6027 	// .program_input
   6028 	addChild(new ProgramInputTestGroup(m_context));
   6029 
   6030 	// .program_output
   6031 	addChild(new ProgramOutputTestGroup(m_context));
   6032 
   6033 	// .transform_feedback_varying
   6034 	addChild(new TransformFeedbackVaryingTestGroup(m_context));
   6035 
   6036 	// .buffer_variable
   6037 	addChild(new BufferVariableTestGroup(m_context));
   6038 
   6039 	// .shader_storage_block
   6040 	addChild(new BufferBackedBlockInterfaceTestGroup(m_context, glu::STORAGE_BUFFER));
   6041 }
   6042 
   6043 } // Functional
   6044 } // gles31
   6045 } // deqp
   6046