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