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