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