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