Block/non-block uniforms match
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcUniformBlockTests.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2016 Google Inc.
6  * Copyright (c) 2016 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */ /*!
21  * \file
22  * \brief Uniform block tests.
23  */ /*-------------------------------------------------------------------*/
24
25 #include "glcUniformBlockTests.hpp"
26 #include "deRandom.hpp"
27 #include "deStringUtil.hpp"
28 #include "glcUniformBlockCase.hpp"
29 #include "glwEnums.hpp"
30 #include "glwFunctions.hpp"
31 #include "tcuCommandLine.hpp"
32 #include "tcuTestLog.hpp"
33
34 namespace deqp
35 {
36
37 using std::string;
38 using std::vector;
39 using deqp::Context;
40
41 using namespace ub;
42
43 enum FeatureBits
44 {
45         FEATURE_VECTORS                 = (1 << 0),
46         FEATURE_MATRICES                = (1 << 1),
47         FEATURE_ARRAYS                  = (1 << 2),
48         FEATURE_STRUCTS                 = (1 << 3),
49         FEATURE_NESTED_STRUCTS  = (1 << 4),
50         FEATURE_INSTANCE_ARRAYS = (1 << 5),
51         FEATURE_VERTEX_BLOCKS   = (1 << 6),
52         FEATURE_FRAGMENT_BLOCKS = (1 << 7),
53         FEATURE_SHARED_BLOCKS   = (1 << 8),
54         FEATURE_UNUSED_UNIFORMS = (1 << 9),
55         FEATURE_UNUSED_MEMBERS  = (1 << 10),
56         FEATURE_PACKED_LAYOUT   = (1 << 11),
57         FEATURE_SHARED_LAYOUT   = (1 << 12),
58         FEATURE_STD140_LAYOUT   = (1 << 13),
59         FEATURE_MATRIX_LAYOUT   = (1 << 14) //!< Matrix layout flags.
60 };
61
62 class RandomUniformBlockCase : public UniformBlockCase
63 {
64 public:
65         RandomUniformBlockCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion,
66                                                    BufferMode bufferMode, deUint32 features, deUint32 seed);
67
68         void init(void);
69
70 private:
71         void generateBlock(de::Random& rnd, deUint32 layoutFlags);
72         void generateUniform(de::Random& rnd, UniformBlock& block);
73         VarType generateType(de::Random& rnd, int typeDepth, bool arrayOk);
74
75         deUint32 m_features;
76         int              m_maxVertexBlocks;
77         int              m_maxFragmentBlocks;
78         int              m_maxSharedBlocks;
79         int              m_maxInstances;
80         int              m_maxArrayLength;
81         int              m_maxStructDepth;
82         int              m_maxBlockMembers;
83         int              m_maxStructMembers;
84         deUint32 m_seed;
85
86         int m_blockNdx;
87         int m_uniformNdx;
88         int m_structNdx;
89 };
90
91 RandomUniformBlockCase::RandomUniformBlockCase(Context& context, const char* name, const char* description,
92                                                                                            glu::GLSLVersion glslVersion, BufferMode bufferMode, deUint32 features,
93                                                                                            deUint32 seed)
94         : UniformBlockCase(context, name, description, glslVersion, bufferMode)
95         , m_features(features)
96         , m_maxVertexBlocks((features & FEATURE_VERTEX_BLOCKS) ? 4 : 0)
97         , m_maxFragmentBlocks((features & FEATURE_FRAGMENT_BLOCKS) ? 4 : 0)
98         , m_maxSharedBlocks((features & FEATURE_SHARED_BLOCKS) ? 4 : 0)
99         , m_maxInstances((features & FEATURE_INSTANCE_ARRAYS) ? 3 : 0)
100         , m_maxArrayLength((features & FEATURE_ARRAYS) ? 8 : 0)
101         , m_maxStructDepth((features & FEATURE_STRUCTS) ? 2 : 0)
102         , m_maxBlockMembers(5)
103         , m_maxStructMembers(4)
104         , m_seed(seed)
105         , m_blockNdx(1)
106         , m_uniformNdx(1)
107         , m_structNdx(1)
108 {
109 }
110
111 void RandomUniformBlockCase::init(void)
112 {
113         de::Random rnd(m_seed);
114
115         int numShared    = m_maxSharedBlocks > 0 ? rnd.getInt(1, m_maxSharedBlocks) : 0;
116         int numVtxBlocks  = m_maxVertexBlocks - numShared > 0 ? rnd.getInt(1, m_maxVertexBlocks - numShared) : 0;
117         int numFragBlocks = m_maxFragmentBlocks - numShared > 0 ? rnd.getInt(1, m_maxFragmentBlocks - numShared) : 0;
118
119         for (int ndx = 0; ndx < numShared; ndx++)
120                 generateBlock(rnd, DECLARE_VERTEX | DECLARE_FRAGMENT);
121
122         for (int ndx = 0; ndx < numVtxBlocks; ndx++)
123                 generateBlock(rnd, DECLARE_VERTEX);
124
125         for (int ndx = 0; ndx < numFragBlocks; ndx++)
126                 generateBlock(rnd, DECLARE_FRAGMENT);
127 }
128
129 void RandomUniformBlockCase::generateBlock(de::Random& rnd, deUint32 layoutFlags)
130 {
131         DE_ASSERT(m_blockNdx <= 'z' - 'a');
132
133         const float   instanceArrayWeight = 0.3f;
134         UniformBlock& block                               = m_interface.allocBlock((string("Block") + (char)('A' + m_blockNdx)).c_str());
135         int numInstances = (m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, m_maxInstances) : 0;
136         int numUniforms  = rnd.getInt(1, m_maxBlockMembers);
137
138         if (numInstances > 0)
139                 block.setArraySize(numInstances);
140
141         if (numInstances > 0 || rnd.getBool())
142                 block.setInstanceName((string("block") + (char)('A' + m_blockNdx)).c_str());
143
144         // Layout flag candidates.
145         vector<deUint32> layoutFlagCandidates;
146         layoutFlagCandidates.push_back(0);
147         if (m_features & FEATURE_PACKED_LAYOUT)
148                 layoutFlagCandidates.push_back(LAYOUT_SHARED);
149         if ((m_features & FEATURE_SHARED_LAYOUT) && ((layoutFlags & DECLARE_BOTH) != DECLARE_BOTH))
150                 layoutFlagCandidates.push_back(LAYOUT_PACKED); // \note packed layout can only be used in a single shader stage.
151         if (m_features & FEATURE_STD140_LAYOUT)
152                 layoutFlagCandidates.push_back(LAYOUT_STD140);
153
154         layoutFlags |= rnd.choose<deUint32>(layoutFlagCandidates.begin(), layoutFlagCandidates.end());
155
156         if (m_features & FEATURE_MATRIX_LAYOUT)
157         {
158                 static const deUint32 matrixCandidates[] = { 0, LAYOUT_ROW_MAJOR, LAYOUT_COLUMN_MAJOR };
159                 layoutFlags |=
160                         rnd.choose<deUint32>(&matrixCandidates[0], &matrixCandidates[DE_LENGTH_OF_ARRAY(matrixCandidates)]);
161         }
162
163         block.setFlags(layoutFlags);
164
165         for (int ndx = 0; ndx < numUniforms; ndx++)
166                 generateUniform(rnd, block);
167
168         m_blockNdx += 1;
169 }
170
171 static std::string genName(char first, char last, int ndx)
172 {
173         std::string str                 = "";
174         int                     alphabetLen = last - first + 1;
175
176         while (ndx > alphabetLen)
177         {
178                 str.insert(str.begin(), (char)(first + ((ndx - 1) % alphabetLen)));
179                 ndx = ((ndx - 1) / alphabetLen);
180         }
181
182         str.insert(str.begin(), (char)(first + (ndx % (alphabetLen + 1)) - 1));
183
184         return str;
185 }
186
187 void RandomUniformBlockCase::generateUniform(de::Random& rnd, UniformBlock& block)
188 {
189         const float unusedVtxWeight  = 0.15f;
190         const float unusedFragWeight = 0.15f;
191         bool            unusedOk                 = (m_features & FEATURE_UNUSED_UNIFORMS) != 0;
192         deUint32        flags                    = 0;
193         std::string name                         = genName('a', 'z', m_uniformNdx);
194         VarType         type                     = generateType(rnd, 0, true);
195
196         flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? UNUSED_VERTEX : 0;
197         flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? UNUSED_FRAGMENT : 0;
198
199         block.addUniform(Uniform(name.c_str(), type, flags));
200
201         m_uniformNdx += 1;
202 }
203
204 VarType RandomUniformBlockCase::generateType(de::Random& rnd, int typeDepth, bool arrayOk)
205 {
206         const float structWeight = 0.1f;
207         const float arrayWeight  = 0.1f;
208
209         if (typeDepth < m_maxStructDepth && rnd.getFloat() < structWeight)
210         {
211                 const float             unusedVtxWeight  = 0.15f;
212                 const float             unusedFragWeight = 0.15f;
213                 bool                    unusedOk                 = (m_features & FEATURE_UNUSED_MEMBERS) != 0;
214                 vector<VarType> memberTypes;
215                 int                             numMembers = rnd.getInt(1, m_maxStructMembers);
216
217                 // Generate members first so nested struct declarations are in correct order.
218                 for (int ndx = 0; ndx < numMembers; ndx++)
219                         memberTypes.push_back(generateType(rnd, typeDepth + 1, true));
220
221                 StructType& structType = m_interface.allocStruct((string("s") + genName('A', 'Z', m_structNdx)).c_str());
222                 m_structNdx += 1;
223
224                 DE_ASSERT(numMembers <= 'Z' - 'A');
225                 for (int ndx = 0; ndx < numMembers; ndx++)
226                 {
227                         deUint32 flags = 0;
228
229                         flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? UNUSED_VERTEX : 0;
230                         flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? UNUSED_FRAGMENT : 0;
231
232                         structType.addMember((string("m") + (char)('A' + ndx)).c_str(), memberTypes[ndx], flags);
233                 }
234
235                 return VarType(&structType);
236         }
237         else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight)
238         {
239                 int             arrayLength = rnd.getInt(1, m_maxArrayLength);
240                 VarType elementType = generateType(rnd, typeDepth, false /* nested arrays are not allowed */);
241                 return VarType(elementType, arrayLength);
242         }
243         else
244         {
245                 vector<glu::DataType> typeCandidates;
246
247                 typeCandidates.push_back(glu::TYPE_FLOAT);
248                 typeCandidates.push_back(glu::TYPE_INT);
249                 typeCandidates.push_back(glu::TYPE_UINT);
250                 typeCandidates.push_back(glu::TYPE_BOOL);
251
252                 if (m_features & FEATURE_VECTORS)
253                 {
254                         typeCandidates.push_back(glu::TYPE_FLOAT_VEC2);
255                         typeCandidates.push_back(glu::TYPE_FLOAT_VEC3);
256                         typeCandidates.push_back(glu::TYPE_FLOAT_VEC4);
257                         typeCandidates.push_back(glu::TYPE_INT_VEC2);
258                         typeCandidates.push_back(glu::TYPE_INT_VEC3);
259                         typeCandidates.push_back(glu::TYPE_INT_VEC4);
260                         typeCandidates.push_back(glu::TYPE_UINT_VEC2);
261                         typeCandidates.push_back(glu::TYPE_UINT_VEC3);
262                         typeCandidates.push_back(glu::TYPE_UINT_VEC4);
263                         typeCandidates.push_back(glu::TYPE_BOOL_VEC2);
264                         typeCandidates.push_back(glu::TYPE_BOOL_VEC3);
265                         typeCandidates.push_back(glu::TYPE_BOOL_VEC4);
266                 }
267
268                 if (m_features & FEATURE_MATRICES)
269                 {
270                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT2);
271                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT2X3);
272                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X2);
273                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT3);
274                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X4);
275                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X2);
276                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X3);
277                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT4);
278                 }
279
280                 glu::DataType type  = rnd.choose<glu::DataType>(typeCandidates.begin(), typeCandidates.end());
281                 deUint32          flags = 0;
282
283                 if (!glu::isDataTypeBoolOrBVec(type))
284                 {
285                         // Precision.
286                         static const deUint32 precisionCandidates[] = { PRECISION_LOW, PRECISION_MEDIUM, PRECISION_HIGH };
287                         flags |= rnd.choose<deUint32>(&precisionCandidates[0],
288                                                                                   &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]);
289                 }
290
291                 return VarType(type, flags);
292         }
293 }
294
295 class BlockBasicTypeCase : public UniformBlockCase
296 {
297 public:
298         BlockBasicTypeCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion,
299                                            const VarType& type, deUint32 layoutFlags, int numInstances)
300                 : UniformBlockCase(context, name, description, glslVersion, BUFFERMODE_PER_BLOCK)
301         {
302                 UniformBlock& block = m_interface.allocBlock("Block");
303                 block.addUniform(Uniform("var", type, 0));
304                 block.setFlags(layoutFlags);
305
306                 if (numInstances > 0)
307                 {
308                         block.setArraySize(numInstances);
309                         block.setInstanceName("block");
310                 }
311         }
312 };
313
314 static void createRandomCaseGroup(tcu::TestCaseGroup* parentGroup, Context& context, const char* groupName,
315                                                                   const char* description, glu::GLSLVersion glslVersion,
316                                                                   UniformBlockCase::BufferMode bufferMode, deUint32 features, int numCases,
317                                                                   deUint32 baseSeed)
318 {
319         tcu::TestCaseGroup* group = new tcu::TestCaseGroup(context.getTestContext(), groupName, description);
320         parentGroup->addChild(group);
321
322         baseSeed += (deUint32)context.getTestContext().getCommandLine().getBaseSeed();
323
324         for (int ndx = 0; ndx < numCases; ndx++)
325                 group->addChild(new RandomUniformBlockCase(context, de::toString(ndx).c_str(), "", glslVersion, bufferMode,
326                                                                                                    features, (deUint32)deInt32Hash(ndx + baseSeed)));
327 }
328
329 class BlockSingleStructCase : public UniformBlockCase
330 {
331 public:
332         BlockSingleStructCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion,
333                                                   deUint32 layoutFlags, BufferMode bufferMode, int numInstances)
334                 : UniformBlockCase(context, name, description, glslVersion, bufferMode)
335                 , m_layoutFlags(layoutFlags)
336                 , m_numInstances(numInstances)
337         {
338         }
339
340         void init(void)
341         {
342                 StructType& typeS = m_interface.allocStruct("S");
343                 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), UNUSED_BOTH); // First member is unused.
344                 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
345                 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
346
347                 UniformBlock& block = m_interface.allocBlock("Block");
348                 block.addUniform(Uniform("s", VarType(&typeS), 0));
349                 block.setFlags(m_layoutFlags);
350
351                 if (m_numInstances > 0)
352                 {
353                         block.setInstanceName("block");
354                         block.setArraySize(m_numInstances);
355                 }
356         }
357
358 private:
359         deUint32 m_layoutFlags;
360         int              m_numInstances;
361 };
362
363 class BlockSingleStructArrayCase : public UniformBlockCase
364 {
365 public:
366         BlockSingleStructArrayCase(Context& context, const char* name, const char* description,
367                                                            glu::GLSLVersion glslVersion, deUint32 layoutFlags, BufferMode bufferMode,
368                                                            int numInstances)
369                 : UniformBlockCase(context, name, description, glslVersion, bufferMode)
370                 , m_layoutFlags(layoutFlags)
371                 , m_numInstances(numInstances)
372         {
373         }
374
375         void init(void)
376         {
377                 StructType& typeS = m_interface.allocStruct("S");
378                 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), UNUSED_BOTH);
379                 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
380                 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
381
382                 UniformBlock& block = m_interface.allocBlock("Block");
383                 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_LOW)));
384                 block.addUniform(Uniform("s", VarType(VarType(&typeS), 3)));
385                 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_MEDIUM)));
386                 block.setFlags(m_layoutFlags);
387
388                 if (m_numInstances > 0)
389                 {
390                         block.setInstanceName("block");
391                         block.setArraySize(m_numInstances);
392                 }
393         }
394
395 private:
396         deUint32 m_layoutFlags;
397         int              m_numInstances;
398 };
399
400 class BlockSingleNestedStructCase : public UniformBlockCase
401 {
402 public:
403         BlockSingleNestedStructCase(Context& context, const char* name, const char* description,
404                                                                 glu::GLSLVersion glslVersion, deUint32 layoutFlags, BufferMode bufferMode,
405                                                                 int numInstances)
406                 : UniformBlockCase(context, name, description, glslVersion, bufferMode)
407                 , m_layoutFlags(layoutFlags)
408                 , m_numInstances(numInstances)
409         {
410         }
411
412         void init(void)
413         {
414                 StructType& typeS = m_interface.allocStruct("S");
415                 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
416                 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
417                 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH);
418
419                 StructType& typeT = m_interface.allocStruct("T");
420                 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
421                 typeT.addMember("b", VarType(&typeS));
422
423                 UniformBlock& block = m_interface.allocBlock("Block");
424                 block.addUniform(Uniform("s", VarType(&typeS), 0));
425                 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), UNUSED_BOTH));
426                 block.addUniform(Uniform("t", VarType(&typeT), 0));
427                 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
428                 block.setFlags(m_layoutFlags);
429
430                 if (m_numInstances > 0)
431                 {
432                         block.setInstanceName("block");
433                         block.setArraySize(m_numInstances);
434                 }
435         }
436
437 private:
438         deUint32 m_layoutFlags;
439         int              m_numInstances;
440 };
441
442 class BlockSingleNestedStructArrayCase : public UniformBlockCase
443 {
444 public:
445         BlockSingleNestedStructArrayCase(Context& context, const char* name, const char* description,
446                                                                          glu::GLSLVersion glslVersion, deUint32 layoutFlags, BufferMode bufferMode,
447                                                                          int numInstances)
448                 : UniformBlockCase(context, name, description, glslVersion, bufferMode)
449                 , m_layoutFlags(layoutFlags)
450                 , m_numInstances(numInstances)
451         {
452         }
453
454         void init(void)
455         {
456                 StructType& typeS = m_interface.allocStruct("S");
457                 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
458                 typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, PRECISION_MEDIUM), 4));
459                 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH);
460
461                 StructType& typeT = m_interface.allocStruct("T");
462                 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
463                 typeT.addMember("b", VarType(VarType(&typeS), 3));
464
465                 UniformBlock& block = m_interface.allocBlock("Block");
466                 block.addUniform(Uniform("s", VarType(&typeS), 0));
467                 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), UNUSED_BOTH));
468                 block.addUniform(Uniform("t", VarType(VarType(&typeT), 2), 0));
469                 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
470                 block.setFlags(m_layoutFlags);
471
472                 if (m_numInstances > 0)
473                 {
474                         block.setInstanceName("block");
475                         block.setArraySize(m_numInstances);
476                 }
477         }
478
479 private:
480         deUint32 m_layoutFlags;
481         int              m_numInstances;
482 };
483
484 class BlockMultiBasicTypesCase : public UniformBlockCase
485 {
486 public:
487         BlockMultiBasicTypesCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion,
488                                                          deUint32 flagsA, deUint32 flagsB, BufferMode bufferMode, int numInstances)
489                 : UniformBlockCase(context, name, description, glslVersion, bufferMode)
490                 , m_flagsA(flagsA)
491                 , m_flagsB(flagsB)
492                 , m_numInstances(numInstances)
493         {
494         }
495
496         void init(void)
497         {
498                 UniformBlock& blockA = m_interface.allocBlock("BlockA");
499                 blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
500                 blockA.addUniform(Uniform("b", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
501                 blockA.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
502                 blockA.setInstanceName("blockA");
503                 blockA.setFlags(m_flagsA);
504
505                 UniformBlock& blockB = m_interface.allocBlock("BlockB");
506                 blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM)));
507                 blockB.addUniform(Uniform("b", VarType(glu::TYPE_INT_VEC2, PRECISION_LOW)));
508                 blockB.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH));
509                 blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
510                 blockB.setInstanceName("blockB");
511                 blockB.setFlags(m_flagsB);
512
513                 if (m_numInstances > 0)
514                 {
515                         blockA.setArraySize(m_numInstances);
516                         blockB.setArraySize(m_numInstances);
517                 }
518         }
519
520 private:
521         deUint32 m_flagsA;
522         deUint32 m_flagsB;
523         int              m_numInstances;
524 };
525
526 class BlockMultiNestedStructCase : public UniformBlockCase
527 {
528 public:
529         BlockMultiNestedStructCase(Context& context, const char* name, const char* description,
530                                                            glu::GLSLVersion glslVersion, deUint32 flagsA, deUint32 flagsB, BufferMode bufferMode,
531                                                            int numInstances)
532                 : UniformBlockCase(context, name, description, glslVersion, bufferMode)
533                 , m_flagsA(flagsA)
534                 , m_flagsB(flagsB)
535                 , m_numInstances(numInstances)
536         {
537         }
538
539         void init(void)
540         {
541                 StructType& typeS = m_interface.allocStruct("S");
542                 typeS.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_LOW));
543                 typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, PRECISION_MEDIUM), 4));
544                 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
545
546                 StructType& typeT = m_interface.allocStruct("T");
547                 typeT.addMember("a", VarType(glu::TYPE_UINT, PRECISION_MEDIUM), UNUSED_BOTH);
548                 typeT.addMember("b", VarType(&typeS));
549                 typeT.addMember("c", VarType(glu::TYPE_BOOL_VEC4, 0));
550
551                 UniformBlock& blockA = m_interface.allocBlock("BlockA");
552                 blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
553                 blockA.addUniform(Uniform("b", VarType(&typeS)));
554                 blockA.addUniform(Uniform("c", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
555                 blockA.setInstanceName("blockA");
556                 blockA.setFlags(m_flagsA);
557
558                 UniformBlock& blockB = m_interface.allocBlock("BlockB");
559                 blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
560                 blockB.addUniform(Uniform("b", VarType(&typeT)));
561                 blockB.addUniform(Uniform("c", VarType(glu::TYPE_BOOL_VEC4, 0), UNUSED_BOTH));
562                 blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
563                 blockB.setInstanceName("blockB");
564                 blockB.setFlags(m_flagsB);
565
566                 if (m_numInstances > 0)
567                 {
568                         blockA.setArraySize(m_numInstances);
569                         blockB.setArraySize(m_numInstances);
570                 }
571         }
572
573 private:
574         deUint32 m_flagsA;
575         deUint32 m_flagsB;
576         int              m_numInstances;
577 };
578
579 class UniformBlockPrecisionMatching : public TestCase
580 {
581 public:
582         UniformBlockPrecisionMatching(Context& context, glu::GLSLVersion glslVersion)
583                 : TestCase(context, "precision_matching", ""), m_glslVersion(glslVersion)
584         {
585         }
586
587         IterateResult iterate(void)
588         {
589                 std::string vs1("layout (std140) uniform Data { lowp float x; } myData;\n"
590                                                 "void main() {\n"
591                                                 "  gl_Position = vec4(myData.x, 0.0, 0.0, 1.0);\n"
592                                                 "}");
593                 std::string fs1("precision highp float;\n"
594                                                 "out vec4 color;\n"
595                                                 "layout (std140) uniform Data { float x; } myData;\n"
596                                                 "void main() {\n"
597                                                 "  color = vec4(myData.x);\n"
598                                                 "}");
599
600                 std::string vs2("layout (std140) uniform Data { highp int x; mediump int y; } myData;\n"
601                                                 "void main() {\n"
602                                                 "  gl_Position = vec4(float(myData.x), 0.0, 0.0, 1.0);\n"
603                                                 "}");
604                 std::string fs2("precision highp float;\n"
605                                                 "out vec4 color;\n"
606                                                 "layout (std140) uniform Data { mediump int x; highp int y; } myData;\n"
607                                                 "void main() {\n"
608                                                 "  color = vec4(float(myData.y));\n"
609                                                 "}");
610
611                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
612                 if (!Link(vs1, fs1) || !Link(vs2, fs2))
613                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
614                 return STOP;
615         }
616
617         bool Link(const std::string& vs, const std::string& fs)
618         {
619                 const glw::Functions& gl          = m_context.getRenderContext().getFunctions();
620                 const glw::GLuint        p                = gl.createProgram();
621                 const std::string        version = glu::getGLSLVersionDeclaration(m_glslVersion);
622
623                 const struct
624                 {
625                         const char*                name;
626                         const std::string& body;
627                         glw::GLenum                type;
628                 } shaderDefinition[] = { { "VS", vs, GL_VERTEX_SHADER }, { "FS", fs, GL_FRAGMENT_SHADER } };
629
630                 for (unsigned int index = 0; index < 2; ++index)
631                 {
632                         std::string shaderSource        = version + "\n" + shaderDefinition[index].body;
633                         const char* shaderSourcePtr = shaderSource.c_str();
634
635                         glw::GLuint sh = gl.createShader(shaderDefinition[index].type);
636                         gl.attachShader(p, sh);
637                         gl.deleteShader(sh);
638                         gl.shaderSource(sh, 1, &shaderSourcePtr, NULL);
639                         gl.compileShader(sh);
640
641                         glw::GLint status;
642                         gl.getShaderiv(sh, GL_COMPILE_STATUS, &status);
643                         if (status == GL_FALSE)
644                         {
645                                 glw::GLint length;
646                                 gl.getShaderiv(sh, GL_INFO_LOG_LENGTH, &length);
647                                 if (length > 0)
648                                 {
649                                         std::vector<glw::GLchar> log(length);
650                                         gl.getShaderInfoLog(sh, length, NULL, &log[0]);
651                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << shaderDefinition[index].name
652                                                                                                                 << " compilation should succed. Info Log:\n"
653                                                                                                                 << &log[0] << tcu::TestLog::EndMessage;
654                                 }
655                                 gl.deleteProgram(p);
656                                 return false;
657                         }
658                 }
659
660                 gl.linkProgram(p);
661
662                 bool       result = true;
663                 glw::GLint status;
664                 gl.getProgramiv(p, GL_LINK_STATUS, &status);
665                 if (status == GL_FALSE)
666                 {
667                         glw::GLchar log[1024];
668                         gl.getProgramInfoLog(p, sizeof(log), NULL, log);
669                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Link operation should succed. Info Log:\n"
670                                                                                                 << log << tcu::TestLog::EndMessage;
671                         result = false;
672                 }
673
674                 gl.deleteProgram(p);
675                 return result;
676         }
677
678 private:
679         glu::GLSLVersion m_glslVersion;
680 };
681
682 class UniformBlockNameMatching : public TestCase
683 {
684 public:
685         UniformBlockNameMatching(Context& context, glu::GLSLVersion glslVersion)
686                 : TestCase(context, "name_matching", ""), m_glslVersion(glslVersion)
687         {
688         }
689
690         IterateResult iterate(void)
691         {
692                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
693
694                 std::string vs1("precision highp float;\n"
695                                                 "layout (std140) uniform Data { vec4 v; };\n"
696                                                 "void main() {\n"
697                                                 "  gl_Position = v;\n"
698                                                 "}");
699                 std::string fs1("precision highp float;\n"
700                                                 "out vec4 color;\n"
701                                                 "layout (std140) uniform Data { vec4 v; } myData;\n"
702                                                 "void main() {\n"
703                                                 "  color = vec4(myData.v);\n"
704                                                 "}");
705
706                 // check if link error is generated when one of matched blocks has instance name and other doesn't
707                 if (!Test(vs1, fs1, GL_FALSE))
708                         return STOP;
709
710                 std::string vs2("precision highp float;\n"
711                                                 "uniform Data { vec4 v; };\n"
712                                                 "void main() {\n"
713                                                 "  gl_Position = v;\n"
714                                                 "}");
715                 std::string fs2("precision highp float;\n"
716                                                 "out vec4 color;\n"
717                                                 "uniform Data { vec4 v; };\n"
718                                                 "void main() {\n"
719                                                 "  color = v;\n"
720                                                 "}");
721
722                 // check if linking succeeds when both matched blocks are lacking an instance name
723                 if (!Test(vs2, fs2, GL_TRUE))
724                         return STOP;
725
726                 std::string vs3("precision highp float;\n"
727                                                 "layout (std140) uniform Data { vec4 v; } a;\n"
728                                                 "void main() {\n"
729                                                 "  gl_Position = a.v;\n"
730                                                 "}");
731                 std::string fs3("precision highp float;\n"
732                                                 "out vec4 color;\n"
733                                                 "layout (std140) uniform Data { vec4 v; } b;\n"
734                                                 "void main() {\n"
735                                                 "  color = b.v;\n"
736                                                 "}");
737
738                 // check if linking succeeds when both matched blocks are lacking an instance name
739                 if (!Test(vs3, fs3, GL_TRUE))
740                         return STOP;
741
742                 std::string vs4("precision highp float;\n"
743                                                 "layout (std140) uniform Data { float f; };\n"
744                                                 "void main() {\n"
745                                                 "  gl_Position = vec4(f);\n"
746                                                 "}\n");
747                 std::string fs4("precision highp float;\n"
748                                                 "uniform float f;\n"
749                                                 "out vec4 color;\n"
750                                                 "void main() {\n"
751                                                 "  color = vec4(f);\n"
752                                                 "}\n");
753
754                 // check if link error is generated when the same name is used for block and non-block uniform
755                 if (!Test(vs4, fs4, GL_FALSE))
756                         return STOP;
757
758                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
759                 return STOP;
760         }
761
762         bool Test(const std::string& vs, const std::string& fs, glw::GLint expectedLinkStatus)
763         {
764                 const glw::Functions& gl          = m_context.getRenderContext().getFunctions();
765                 const glw::GLuint        p                = gl.createProgram();
766                 const std::string        version = glu::getGLSLVersionDeclaration(m_glslVersion);
767
768                 const struct
769                 {
770                         const char*                name;
771                         const std::string& body;
772                         glw::GLenum                type;
773                 } shaderDefinition[] = { { "VS", vs, GL_VERTEX_SHADER }, { "FS", fs, GL_FRAGMENT_SHADER } };
774
775                 for (unsigned int index = 0; index < 2; ++index)
776                 {
777                         std::string shaderSource        = version + "\n" + shaderDefinition[index].body;
778                         const char* shaderSourcePtr = shaderSource.c_str();
779
780                         glw::GLuint sh = gl.createShader(shaderDefinition[index].type);
781                         gl.attachShader(p, sh);
782                         gl.deleteShader(sh);
783                         gl.shaderSource(sh, 1, &shaderSourcePtr, NULL);
784                         gl.compileShader(sh);
785
786                         glw::GLint status;
787                         gl.getShaderiv(sh, GL_COMPILE_STATUS, &status);
788                         if (status == GL_FALSE)
789                         {
790                                 glw::GLint length;
791                                 gl.getShaderiv(sh, GL_INFO_LOG_LENGTH, &length);
792                                 if (length > 0)
793                                 {
794                                         std::vector<glw::GLchar> log(length);
795                                         gl.getShaderInfoLog(sh, length, NULL, &log[0]);
796                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << shaderDefinition[index].name
797                                                                                                                 << " compilation should succed. Info Log:\n"
798                                                                                                                 << &log[0] << tcu::TestLog::EndMessage;
799                                 }
800                                 gl.deleteProgram(p);
801                                 return false;
802                         }
803                 }
804
805                 gl.linkProgram(p);
806
807                 bool       result = true;
808                 glw::GLint status;
809                 gl.getProgramiv(p, GL_LINK_STATUS, &status);
810                 if (status != expectedLinkStatus)
811                 {
812                         if (status == GL_TRUE)
813                         {
814                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Link operation should fail.\n"
815                                                                                                         << tcu::TestLog::EndMessage;
816                         }
817                         else
818                         {
819                                 glw::GLchar log[1024];
820                                 gl.getProgramInfoLog(p, sizeof(log), NULL, log);
821                                 m_context.getTestContext().getLog()
822                                         << tcu::TestLog::Message << "Link operation should succed. Info Log:\n"
823                                         << log << tcu::TestLog::EndMessage;
824                         }
825                         result = false;
826                 }
827
828                 gl.deleteProgram(p);
829                 return result;
830         }
831
832 private:
833         glu::GLSLVersion m_glslVersion;
834 };
835
836 UniformBlockTests::UniformBlockTests(Context& context, glu::GLSLVersion glslVersion)
837         : TestCaseGroup(context, "uniform_block", "Uniform Block tests"), m_glslVersion(glslVersion)
838 {
839 }
840
841 UniformBlockTests::~UniformBlockTests(void)
842 {
843 }
844
845 void UniformBlockTests::init(void)
846 {
847         static const glu::DataType basicTypes[] = { glu::TYPE_FLOAT,            glu::TYPE_FLOAT_VEC2,   glu::TYPE_FLOAT_VEC3,
848                                                                                                 glu::TYPE_FLOAT_VEC4,   glu::TYPE_INT,                  glu::TYPE_INT_VEC2,
849                                                                                                 glu::TYPE_INT_VEC3,             glu::TYPE_INT_VEC4,             glu::TYPE_UINT,
850                                                                                                 glu::TYPE_UINT_VEC2,    glu::TYPE_UINT_VEC3,    glu::TYPE_UINT_VEC4,
851                                                                                                 glu::TYPE_BOOL,                 glu::TYPE_BOOL_VEC2,    glu::TYPE_BOOL_VEC3,
852                                                                                                 glu::TYPE_BOOL_VEC4,    glu::TYPE_FLOAT_MAT2,   glu::TYPE_FLOAT_MAT3,
853                                                                                                 glu::TYPE_FLOAT_MAT4,   glu::TYPE_FLOAT_MAT2X3, glu::TYPE_FLOAT_MAT2X4,
854                                                                                                 glu::TYPE_FLOAT_MAT3X2, glu::TYPE_FLOAT_MAT3X4, glu::TYPE_FLOAT_MAT4X2,
855                                                                                                 glu::TYPE_FLOAT_MAT4X3 };
856
857         static const struct
858         {
859                 const char* name;
860                 deUint32        flags;
861         } precisionFlags[] = { { "lowp", PRECISION_LOW }, { "mediump", PRECISION_MEDIUM }, { "highp", PRECISION_HIGH } };
862
863         static const struct
864         {
865                 const char* name;
866                 deUint32        flags;
867         } layoutFlags[] = { { "shared", LAYOUT_SHARED }, { "packed", LAYOUT_PACKED }, { "std140", LAYOUT_STD140 } };
868
869         static const struct
870         {
871                 const char* name;
872                 deUint32        flags;
873         } matrixFlags[] = { { "row_major", LAYOUT_ROW_MAJOR }, { "column_major", LAYOUT_COLUMN_MAJOR } };
874
875         static const struct
876         {
877                 const char*                                      name;
878                 UniformBlockCase::BufferMode mode;
879         } bufferModes[] = { { "per_block_buffer", UniformBlockCase::BUFFERMODE_PER_BLOCK },
880                                                 { "single_buffer", UniformBlockCase::BUFFERMODE_SINGLE } };
881
882         // ubo.single_basic_type
883         {
884                 tcu::TestCaseGroup* singleBasicTypeGroup =
885                         new tcu::TestCaseGroup(m_testCtx, "single_basic_type", "Single basic variable in single buffer");
886                 addChild(singleBasicTypeGroup);
887
888                 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
889                 {
890                         tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
891                         singleBasicTypeGroup->addChild(layoutGroup);
892
893                         for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
894                         {
895                                 glu::DataType type              = basicTypes[basicTypeNdx];
896                                 const char*   typeName  = glu::getDataTypeName(type);
897                                 deUint32          baseFlags = layoutFlags[layoutFlagNdx].flags;
898                                 deUint32          flags         = baseFlags | ((baseFlags & LAYOUT_PACKED) ?
899                                                                                                   (basicTypeNdx % 2 == 0 ? DECLARE_VERTEX : DECLARE_FRAGMENT) :
900                                                                                                   DECLARE_BOTH);
901
902                                 if (glu::isDataTypeBoolOrBVec(type))
903                                         layoutGroup->addChild(new BlockBasicTypeCase(m_context, typeName, "", m_glslVersion,
904                                                                                                                                  VarType(type, 0), flags, 0 /* no instance array */));
905                                 else
906                                 {
907                                         for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisionFlags); precNdx++)
908                                                 layoutGroup->addChild(new BlockBasicTypeCase(
909                                                         m_context, (string(precisionFlags[precNdx].name) + "_" + typeName).c_str(), "",
910                                                         m_glslVersion, VarType(type, precisionFlags[precNdx].flags), flags,
911                                                         0 /* no instance array */));
912                                 }
913
914                                 if (glu::isDataTypeMatrix(type))
915                                 {
916                                         for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
917                                         {
918                                                 for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisionFlags); precNdx++)
919                                                         layoutGroup->addChild(new BlockBasicTypeCase(
920                                                                 m_context,
921                                                                 (string(matrixFlags[matFlagNdx].name) + "_" + precisionFlags[precNdx].name + "_" +
922                                                                  typeName)
923                                                                         .c_str(),
924                                                                 "", m_glslVersion, VarType(type, precisionFlags[precNdx].flags),
925                                                                 flags | matrixFlags[matFlagNdx].flags, 0 /* no instance array */));
926                                         }
927                                 }
928                         }
929                 }
930         }
931
932         // ubo.single_basic_array
933         {
934                 tcu::TestCaseGroup* singleBasicArrayGroup =
935                         new tcu::TestCaseGroup(m_testCtx, "single_basic_array", "Single basic array variable in single buffer");
936                 addChild(singleBasicArrayGroup);
937
938                 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
939                 {
940                         tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
941                         singleBasicArrayGroup->addChild(layoutGroup);
942
943                         for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
944                         {
945                                 glu::DataType type              = basicTypes[basicTypeNdx];
946                                 const char*   typeName  = glu::getDataTypeName(type);
947                                 const int        arraySize = 3;
948                                 deUint32          baseFlags = layoutFlags[layoutFlagNdx].flags;
949                                 deUint32          flags         = baseFlags | ((baseFlags & LAYOUT_PACKED) ?
950                                                                                                   (basicTypeNdx % 2 == 0 ? DECLARE_VERTEX : DECLARE_FRAGMENT) :
951                                                                                                   DECLARE_BOTH);
952
953                                 layoutGroup->addChild(new BlockBasicTypeCase(
954                                         m_context, typeName, "", m_glslVersion,
955                                         VarType(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), arraySize), flags,
956                                         0 /* no instance array */));
957
958                                 if (glu::isDataTypeMatrix(type))
959                                 {
960                                         for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
961                                                 layoutGroup->addChild(new BlockBasicTypeCase(
962                                                         m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "",
963                                                         m_glslVersion, VarType(VarType(type, PRECISION_HIGH), arraySize),
964                                                         flags | matrixFlags[matFlagNdx].flags, 0 /* no instance array */));
965                                 }
966                         }
967                 }
968         }
969
970         // ubo.single_struct
971         {
972                 tcu::TestCaseGroup* singleStructGroup =
973                         new tcu::TestCaseGroup(m_testCtx, "single_struct", "Single struct in uniform block");
974                 addChild(singleStructGroup);
975
976                 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
977                 {
978                         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
979                         {
980                                 for (int isArray = 0; isArray < 2; isArray++)
981                                 {
982                                         std::string name = std::string(bufferModes[modeNdx].name) + "_" + layoutFlags[layoutFlagNdx].name;
983                                         deUint32        baseFlags = layoutFlags[layoutFlagNdx].flags;
984                                         deUint32        flags    = baseFlags | ((baseFlags & LAYOUT_PACKED) ? DECLARE_VERTEX : DECLARE_BOTH);
985
986                                         if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
987                                                 continue; // Doesn't make sense to add this variant.
988
989                                         if (isArray)
990                                                 name += "_instance_array";
991
992                                         singleStructGroup->addChild(new BlockSingleStructCase(
993                                                 m_context, name.c_str(), "", m_glslVersion, flags, bufferModes[modeNdx].mode, isArray ? 3 : 0));
994                                 }
995                         }
996                 }
997         }
998
999         // ubo.single_struct_array
1000         {
1001                 tcu::TestCaseGroup* singleStructArrayGroup =
1002                         new tcu::TestCaseGroup(m_testCtx, "single_struct_array", "Struct array in one uniform block");
1003                 addChild(singleStructArrayGroup);
1004
1005                 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1006                 {
1007                         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1008                         {
1009                                 for (int isArray = 0; isArray < 2; isArray++)
1010                                 {
1011                                         std::string name = std::string(bufferModes[modeNdx].name) + "_" + layoutFlags[layoutFlagNdx].name;
1012                                         deUint32        baseFlags = layoutFlags[layoutFlagNdx].flags;
1013                                         deUint32        flags    = baseFlags | ((baseFlags & LAYOUT_PACKED) ? DECLARE_FRAGMENT : DECLARE_BOTH);
1014
1015                                         if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
1016                                                 continue; // Doesn't make sense to add this variant.
1017
1018                                         if (isArray)
1019                                                 name += "_instance_array";
1020
1021                                         singleStructArrayGroup->addChild(new BlockSingleStructArrayCase(
1022                                                 m_context, name.c_str(), "", m_glslVersion, flags, bufferModes[modeNdx].mode, isArray ? 3 : 0));
1023                                 }
1024                         }
1025                 }
1026         }
1027
1028         // ubo.single_nested_struct
1029         {
1030                 tcu::TestCaseGroup* singleNestedStructGroup =
1031                         new tcu::TestCaseGroup(m_testCtx, "single_nested_struct", "Nested struct in one uniform block");
1032                 addChild(singleNestedStructGroup);
1033
1034                 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1035                 {
1036                         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1037                         {
1038                                 for (int isArray = 0; isArray < 2; isArray++)
1039                                 {
1040                                         std::string name = std::string(bufferModes[modeNdx].name) + "_" + layoutFlags[layoutFlagNdx].name;
1041                                         deUint32        baseFlags = layoutFlags[layoutFlagNdx].flags;
1042                                         deUint32        flags    = baseFlags | ((baseFlags & LAYOUT_PACKED) ? DECLARE_VERTEX : DECLARE_BOTH);
1043
1044                                         if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
1045                                                 continue; // Doesn't make sense to add this variant.
1046
1047                                         if (isArray)
1048                                                 name += "_instance_array";
1049
1050                                         singleNestedStructGroup->addChild(new BlockSingleNestedStructCase(
1051                                                 m_context, name.c_str(), "", m_glslVersion, flags, bufferModes[modeNdx].mode, isArray ? 3 : 0));
1052                                 }
1053                         }
1054                 }
1055         }
1056
1057         // ubo.single_nested_struct_array
1058         {
1059                 tcu::TestCaseGroup* singleNestedStructArrayGroup =
1060                         new tcu::TestCaseGroup(m_testCtx, "single_nested_struct_array", "Nested struct array in one uniform block");
1061                 addChild(singleNestedStructArrayGroup);
1062
1063                 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1064                 {
1065                         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1066                         {
1067                                 for (int isArray = 0; isArray < 2; isArray++)
1068                                 {
1069                                         std::string name = std::string(bufferModes[modeNdx].name) + "_" + layoutFlags[layoutFlagNdx].name;
1070                                         deUint32        baseFlags = layoutFlags[layoutFlagNdx].flags;
1071                                         deUint32        flags    = baseFlags | ((baseFlags & LAYOUT_PACKED) ? DECLARE_FRAGMENT : DECLARE_BOTH);
1072
1073                                         if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
1074                                                 continue; // Doesn't make sense to add this variant.
1075
1076                                         if (isArray)
1077                                                 name += "_instance_array";
1078
1079                                         singleNestedStructArrayGroup->addChild(new BlockSingleNestedStructArrayCase(
1080                                                 m_context, name.c_str(), "", m_glslVersion, flags, bufferModes[modeNdx].mode, isArray ? 3 : 0));
1081                                 }
1082                         }
1083                 }
1084         }
1085
1086         // ubo.instance_array_basic_type
1087         {
1088                 tcu::TestCaseGroup* instanceArrayBasicTypeGroup =
1089                         new tcu::TestCaseGroup(m_testCtx, "instance_array_basic_type", "Single basic variable in instance array");
1090                 addChild(instanceArrayBasicTypeGroup);
1091
1092                 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1093                 {
1094                         tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
1095                         instanceArrayBasicTypeGroup->addChild(layoutGroup);
1096
1097                         for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
1098                         {
1099                                 glu::DataType type                 = basicTypes[basicTypeNdx];
1100                                 const char*   typeName   = glu::getDataTypeName(type);
1101                                 const int        numInstances = 3;
1102                                 deUint32          baseFlags     = layoutFlags[layoutFlagNdx].flags;
1103                                 deUint32          flags            = baseFlags | ((baseFlags & LAYOUT_PACKED) ?
1104                                                                                                   (basicTypeNdx % 2 == 0 ? DECLARE_VERTEX : DECLARE_FRAGMENT) :
1105                                                                                                   DECLARE_BOTH);
1106
1107                                 layoutGroup->addChild(new BlockBasicTypeCase(
1108                                         m_context, typeName, "", m_glslVersion,
1109                                         VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), flags, numInstances));
1110
1111                                 if (glu::isDataTypeMatrix(type))
1112                                 {
1113                                         for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
1114                                                 layoutGroup->addChild(new BlockBasicTypeCase(
1115                                                         m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "",
1116                                                         m_glslVersion, VarType(type, PRECISION_HIGH), flags | matrixFlags[matFlagNdx].flags,
1117                                                         numInstances));
1118                                 }
1119                         }
1120                 }
1121         }
1122
1123         // ubo.multi_basic_types
1124         {
1125                 tcu::TestCaseGroup* multiBasicTypesGroup =
1126                         new tcu::TestCaseGroup(m_testCtx, "multi_basic_types", "Multiple buffers with basic types");
1127                 addChild(multiBasicTypesGroup);
1128
1129                 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1130                 {
1131                         tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1132                         multiBasicTypesGroup->addChild(modeGroup);
1133
1134                         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1135                         {
1136                                 for (int isArray = 0; isArray < 2; isArray++)
1137                                 {
1138                                         std::string baseName  = layoutFlags[layoutFlagNdx].name;
1139                                         deUint32        baseFlags = layoutFlags[layoutFlagNdx].flags;
1140
1141                                         if (isArray)
1142                                                 baseName += "_instance_array";
1143
1144                                         modeGroup->addChild(new BlockMultiBasicTypesCase(
1145                                                 m_context, (baseName + "_mixed").c_str(), "", m_glslVersion, baseFlags | DECLARE_VERTEX,
1146                                                 baseFlags | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
1147
1148                                         if (!(baseFlags & LAYOUT_PACKED))
1149                                                 modeGroup->addChild(new BlockMultiBasicTypesCase(
1150                                                         m_context, (baseName + "_both").c_str(), "", m_glslVersion,
1151                                                         baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
1152                                                         baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
1153                                 }
1154                         }
1155                 }
1156         }
1157
1158         // ubo.multi_nested_struct
1159         {
1160                 tcu::TestCaseGroup* multiNestedStructGroup =
1161                         new tcu::TestCaseGroup(m_testCtx, "multi_nested_struct", "Multiple buffers with nested structs");
1162                 addChild(multiNestedStructGroup);
1163
1164                 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1165                 {
1166                         tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1167                         multiNestedStructGroup->addChild(modeGroup);
1168
1169                         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1170                         {
1171                                 for (int isArray = 0; isArray < 2; isArray++)
1172                                 {
1173                                         std::string baseName  = layoutFlags[layoutFlagNdx].name;
1174                                         deUint32        baseFlags = layoutFlags[layoutFlagNdx].flags;
1175
1176                                         if (isArray)
1177                                                 baseName += "_instance_array";
1178
1179                                         modeGroup->addChild(new BlockMultiNestedStructCase(
1180                                                 m_context, (baseName + "_mixed").c_str(), "", m_glslVersion, baseFlags | DECLARE_VERTEX,
1181                                                 baseFlags | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
1182
1183                                         if (!(baseFlags & LAYOUT_PACKED))
1184                                                 modeGroup->addChild(new BlockMultiNestedStructCase(
1185                                                         m_context, (baseName + "_both").c_str(), "", m_glslVersion,
1186                                                         baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
1187                                                         baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
1188                                 }
1189                         }
1190                 }
1191         }
1192
1193         // ubo.random
1194         {
1195                 const deUint32 allShaders       = FEATURE_VERTEX_BLOCKS | FEATURE_FRAGMENT_BLOCKS | FEATURE_SHARED_BLOCKS;
1196                 const deUint32 allLayouts       = FEATURE_PACKED_LAYOUT | FEATURE_SHARED_LAYOUT | FEATURE_STD140_LAYOUT;
1197                 const deUint32 allBasicTypes = FEATURE_VECTORS | FEATURE_MATRICES;
1198                 const deUint32 unused            = FEATURE_UNUSED_MEMBERS | FEATURE_UNUSED_UNIFORMS;
1199                 const deUint32 matFlags          = FEATURE_MATRIX_LAYOUT;
1200
1201                 tcu::TestCaseGroup* randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random Uniform Block cases");
1202                 addChild(randomGroup);
1203
1204                 // Basic types.
1205                 createRandomCaseGroup(randomGroup, m_context, "scalar_types", "Scalar types only, per-block buffers",
1206                                                           m_glslVersion, UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders | allLayouts | unused,
1207                                                           10, 0);
1208                 createRandomCaseGroup(randomGroup, m_context, "vector_types", "Scalar and vector types only, per-block buffers",
1209                                                           m_glslVersion, UniformBlockCase::BUFFERMODE_PER_BLOCK,
1210                                                           allShaders | allLayouts | unused | FEATURE_VECTORS, 10, 25);
1211                 createRandomCaseGroup(randomGroup, m_context, "basic_types", "All basic types, per-block buffers",
1212                                                           m_glslVersion, UniformBlockCase::BUFFERMODE_PER_BLOCK,
1213                                                           allShaders | allLayouts | unused | allBasicTypes | matFlags, 10, 50);
1214                 createRandomCaseGroup(randomGroup, m_context, "basic_arrays", "Arrays, per-block buffers", m_glslVersion,
1215                                                           UniformBlockCase::BUFFERMODE_PER_BLOCK,
1216                                                           allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_ARRAYS, 10, 50);
1217
1218                 createRandomCaseGroup(
1219                         randomGroup, m_context, "basic_instance_arrays", "Basic instance arrays, per-block buffers", m_glslVersion,
1220                         UniformBlockCase::BUFFERMODE_PER_BLOCK,
1221                         allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_INSTANCE_ARRAYS, 10, 75);
1222                 createRandomCaseGroup(randomGroup, m_context, "nested_structs", "Nested structs, per-block buffers",
1223                                                           m_glslVersion, UniformBlockCase::BUFFERMODE_PER_BLOCK,
1224                                                           allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_STRUCTS, 10, 100);
1225                 createRandomCaseGroup(
1226                         randomGroup, m_context, "nested_structs_arrays", "Nested structs, arrays, per-block buffers", m_glslVersion,
1227                         UniformBlockCase::BUFFERMODE_PER_BLOCK,
1228                         allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_STRUCTS | FEATURE_ARRAYS, 10, 150);
1229                 createRandomCaseGroup(
1230                         randomGroup, m_context, "nested_structs_instance_arrays",
1231                         "Nested structs, instance arrays, per-block buffers", m_glslVersion, UniformBlockCase::BUFFERMODE_PER_BLOCK,
1232                         allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_STRUCTS | FEATURE_INSTANCE_ARRAYS, 10,
1233                         125);
1234                 createRandomCaseGroup(randomGroup, m_context, "nested_structs_arrays_instance_arrays",
1235                                                           "Nested structs, instance arrays, per-block buffers", m_glslVersion,
1236                                                           UniformBlockCase::BUFFERMODE_PER_BLOCK,
1237                                                           allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_STRUCTS |
1238                                                                   FEATURE_ARRAYS | FEATURE_INSTANCE_ARRAYS,
1239                                                           10, 175);
1240
1241                 createRandomCaseGroup(randomGroup, m_context, "all_per_block_buffers", "All random features, per-block buffers",
1242                                                           m_glslVersion, UniformBlockCase::BUFFERMODE_PER_BLOCK, ~0u, 20, 200);
1243                 createRandomCaseGroup(randomGroup, m_context, "all_shared_buffer", "All random features, shared buffer",
1244                                                           m_glslVersion, UniformBlockCase::BUFFERMODE_SINGLE, ~0u, 20, 250);
1245         }
1246
1247         // ubo.common
1248         if (glu::isGLSLVersionSupported(m_context.getRenderContext().getType(), glu::GLSL_VERSION_300_ES))
1249         {
1250                 tcu::TestCaseGroup* commonGroup = new tcu::TestCaseGroup(m_testCtx, "common", "Common Uniform Block cases");
1251                 addChild(commonGroup);
1252                 commonGroup->addChild(new UniformBlockPrecisionMatching(m_context, m_glslVersion));
1253                 commonGroup->addChild(new UniformBlockNameMatching(m_context, m_glslVersion));
1254         }
1255         else if (glu::isGLSLVersionSupported(m_context.getRenderContext().getType(), glu::GLSL_VERSION_150))
1256         {
1257                 tcu::TestCaseGroup* commonGroup = new tcu::TestCaseGroup(m_testCtx, "common", "Common Uniform Block cases");
1258                 addChild(commonGroup);
1259                 commonGroup->addChild(new UniformBlockNameMatching(m_context, m_glslVersion));
1260         }
1261 }
1262
1263 } // deqp