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