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