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