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