1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2016 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Uniform block tests.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktUniformBlockTests.hpp"
27 
28 #include "vktUniformBlockCase.hpp"
29 #include "vktRandomUniformBlockCase.hpp"
30 
31 #include "tcuCommandLine.hpp"
32 #include "deStringUtil.hpp"
33 
34 namespace vkt
35 {
36 namespace ubo
37 {
38 
39 namespace
40 {
41 
42 class BlockBasicTypeCase : public UniformBlockCase
43 {
44 public:
BlockBasicTypeCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const VarType & type,deUint32 layoutFlags,int numInstances)45 	BlockBasicTypeCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const VarType& type, deUint32 layoutFlags, int numInstances)
46 		: UniformBlockCase(testCtx, name, description, BUFFERMODE_PER_BLOCK)
47 	{
48 		UniformBlock& block = m_interface.allocBlock("Block");
49 		block.addUniform(Uniform("var", type, 0));
50 		block.setFlags(layoutFlags);
51 
52 		if (numInstances > 0)
53 		{
54 			block.setArraySize(numInstances);
55 			block.setInstanceName("block");
56 		}
57 
58 		init();
59 	}
60 };
61 
createBlockBasicTypeCases(tcu::TestCaseGroup * group,tcu::TestContext & testCtx,const std::string & name,const VarType & type,deUint32 layoutFlags,int numInstances=0)62 static void createBlockBasicTypeCases (tcu::TestCaseGroup* group, tcu::TestContext& testCtx, const std::string& name, const VarType& type, deUint32 layoutFlags, int numInstances = 0)
63 {
64 	group->addChild(new BlockBasicTypeCase(testCtx, name + "_vertex",	"", type, layoutFlags|DECLARE_VERTEX,					numInstances));
65 	group->addChild(new BlockBasicTypeCase(testCtx, name + "_fragment",	"", type, layoutFlags|DECLARE_FRAGMENT,					numInstances));
66 	group->addChild(new BlockBasicTypeCase(testCtx, name + "_both",	"",		type, layoutFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,	numInstances));
67 }
68 
69 class BlockSingleStructCase : public UniformBlockCase
70 {
71 public:
BlockSingleStructCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances)72 	BlockSingleStructCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances)
73 		: UniformBlockCase	(testCtx, name, description, bufferMode)
74 	{
75 		StructType& typeS = m_interface.allocStruct("S");
76 		typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), UNUSED_BOTH); // First member is unused.
77 		typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
78 		typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
79 
80 		UniformBlock& block = m_interface.allocBlock("Block");
81 		block.addUniform(Uniform("s", VarType(&typeS), 0));
82 		block.setFlags(layoutFlags);
83 
84 		if (numInstances > 0)
85 		{
86 			block.setInstanceName("block");
87 			block.setArraySize(numInstances);
88 		}
89 
90 		init();
91 	}
92 };
93 
94 class BlockSingleStructArrayCase : public UniformBlockCase
95 {
96 public:
BlockSingleStructArrayCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances)97 	BlockSingleStructArrayCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances)
98 		: UniformBlockCase	(testCtx, name, description, bufferMode)
99 	{
100 		StructType& typeS = m_interface.allocStruct("S");
101 		typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), UNUSED_BOTH);
102 		typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
103 		typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
104 
105 		UniformBlock& block = m_interface.allocBlock("Block");
106 		block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_LOW)));
107 		block.addUniform(Uniform("s", VarType(VarType(&typeS), 3)));
108 		block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_MEDIUM)));
109 		block.setFlags(layoutFlags);
110 
111 		if (numInstances > 0)
112 		{
113 			block.setInstanceName("block");
114 			block.setArraySize(numInstances);
115 		}
116 
117 		init();
118 	}
119 };
120 
121 class BlockSingleNestedStructCase : public UniformBlockCase
122 {
123 public:
BlockSingleNestedStructCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances)124 	BlockSingleNestedStructCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances)
125 		: UniformBlockCase	(testCtx, name, description, bufferMode)
126 	{
127 		StructType& typeS = m_interface.allocStruct("S");
128 		typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
129 		typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
130 		typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH);
131 
132 		StructType& typeT = m_interface.allocStruct("T");
133 		typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
134 		typeT.addMember("b", VarType(&typeS));
135 
136 		UniformBlock& block = m_interface.allocBlock("Block");
137 		block.addUniform(Uniform("s", VarType(&typeS), 0));
138 		block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), UNUSED_BOTH));
139 		block.addUniform(Uniform("t", VarType(&typeT), 0));
140 		block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
141 		block.setFlags(layoutFlags);
142 
143 		if (numInstances > 0)
144 		{
145 			block.setInstanceName("block");
146 			block.setArraySize(numInstances);
147 		}
148 
149 		init();
150 	}
151 };
152 
153 class BlockSingleNestedStructArrayCase : public UniformBlockCase
154 {
155 public:
BlockSingleNestedStructArrayCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances)156 	BlockSingleNestedStructArrayCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances)
157 		: UniformBlockCase	(testCtx, name, description, bufferMode)
158 	{
159 		StructType& typeS = m_interface.allocStruct("S");
160 		typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
161 		typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, PRECISION_MEDIUM), 4));
162 		typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH);
163 
164 		StructType& typeT = m_interface.allocStruct("T");
165 		typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
166 		typeT.addMember("b", VarType(VarType(&typeS), 3));
167 
168 		UniformBlock& block = m_interface.allocBlock("Block");
169 		block.addUniform(Uniform("s", VarType(&typeS), 0));
170 		block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), UNUSED_BOTH));
171 		block.addUniform(Uniform("t", VarType(VarType(&typeT), 2), 0));
172 		block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
173 		block.setFlags(layoutFlags);
174 
175 		if (numInstances > 0)
176 		{
177 			block.setInstanceName("block");
178 			block.setArraySize(numInstances);
179 		}
180 
181 		init();
182 	}
183 };
184 
185 class BlockMultiBasicTypesCase : public UniformBlockCase
186 {
187 public:
BlockMultiBasicTypesCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,deUint32 flagsA,deUint32 flagsB,BufferMode bufferMode,int numInstances)188 	BlockMultiBasicTypesCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 flagsA, deUint32 flagsB, BufferMode bufferMode, int numInstances)
189 		: UniformBlockCase	(testCtx, name, description, bufferMode)
190 	{
191 		UniformBlock& blockA = m_interface.allocBlock("BlockA");
192 		blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
193 		blockA.addUniform(Uniform("b", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
194 		blockA.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
195 		blockA.setInstanceName("blockA");
196 		blockA.setFlags(flagsA);
197 
198 		UniformBlock& blockB = m_interface.allocBlock("BlockB");
199 		blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM)));
200 		blockB.addUniform(Uniform("b", VarType(glu::TYPE_INT_VEC2, PRECISION_LOW)));
201 		blockB.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH));
202 		blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
203 		blockB.setInstanceName("blockB");
204 		blockB.setFlags(flagsB);
205 
206 		if (numInstances > 0)
207 		{
208 			blockA.setArraySize(numInstances);
209 			blockB.setArraySize(numInstances);
210 		}
211 
212 		init();
213 	}
214 };
215 
216 class BlockMultiNestedStructCase : public UniformBlockCase
217 {
218 public:
BlockMultiNestedStructCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,deUint32 flagsA,deUint32 flagsB,BufferMode bufferMode,int numInstances)219 	BlockMultiNestedStructCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 flagsA, deUint32 flagsB, BufferMode bufferMode, int numInstances)
220 		: UniformBlockCase	(testCtx, name, description, bufferMode)
221 	{
222 		StructType& typeS = m_interface.allocStruct("S");
223 		typeS.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_LOW));
224 		typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, PRECISION_MEDIUM), 4));
225 		typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
226 
227 		StructType& typeT = m_interface.allocStruct("T");
228 		typeT.addMember("a", VarType(glu::TYPE_UINT, PRECISION_MEDIUM), UNUSED_BOTH);
229 		typeT.addMember("b", VarType(&typeS));
230 		typeT.addMember("c", VarType(glu::TYPE_BOOL_VEC4, 0));
231 
232 		UniformBlock& blockA = m_interface.allocBlock("BlockA");
233 		blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
234 		blockA.addUniform(Uniform("b", VarType(&typeS)));
235 		blockA.addUniform(Uniform("c", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
236 		blockA.setInstanceName("blockA");
237 		blockA.setFlags(flagsA);
238 
239 		UniformBlock& blockB = m_interface.allocBlock("BlockB");
240 		blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
241 		blockB.addUniform(Uniform("b", VarType(&typeT)));
242 		blockB.addUniform(Uniform("c", VarType(glu::TYPE_BOOL_VEC4, 0), UNUSED_BOTH));
243 		blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
244 		blockB.setInstanceName("blockB");
245 		blockB.setFlags(flagsB);
246 
247 		if (numInstances > 0)
248 		{
249 			blockA.setArraySize(numInstances);
250 			blockB.setArraySize(numInstances);
251 		}
252 
253 		init();
254 	}
255 };
256 
257 class Block2LevelStructArrayCase : public UniformBlockCase
258 {
259 public:
Block2LevelStructArrayCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances)260 	Block2LevelStructArrayCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances)
261 		: UniformBlockCase	(testCtx, name, description, bufferMode)
262 		, m_layoutFlags		(layoutFlags)
263 		, m_numInstances	(numInstances)
264 	{
265 		StructType& typeS = m_interface.allocStruct("S");
266 		typeS.addMember("a", VarType(glu::TYPE_UINT_VEC3, PRECISION_HIGH), UNUSED_BOTH);
267 		typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM), 4));
268 		typeS.addMember("c", VarType(glu::TYPE_UINT, PRECISION_LOW));
269 
270 		UniformBlock& block = m_interface.allocBlock("Block");
271 		block.addUniform(Uniform("u", VarType(glu::TYPE_INT, PRECISION_MEDIUM)));
272 		block.addUniform(Uniform("s", VarType(VarType(VarType(&typeS), 3), 2)));
273 		block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_MEDIUM)));
274 		block.setFlags(m_layoutFlags);
275 
276 		if (m_numInstances > 0)
277 		{
278 			block.setInstanceName("block");
279 			block.setArraySize(m_numInstances);
280 		}
281 
282 		init();
283 	}
284 
285 private:
286 	deUint32	m_layoutFlags;
287 	int			m_numInstances;
288 };
289 
290 class LinkByBindingCase : public UniformBlockCase
291 {
292 public:
LinkByBindingCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,BufferMode bufferMode,int numInstances)293 	LinkByBindingCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, BufferMode bufferMode, int numInstances)
294 		: UniformBlockCase	(testCtx, name, description, bufferMode)
295 	{
296 		UniformBlock& blockA = m_interface.allocBlock("TestBlock");
297 		blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
298 		blockA.addUniform(Uniform("b", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
299 		blockA.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
300 		blockA.setFlags(LAYOUT_STD140|DECLARE_VERTEX);
301 
302 		UniformBlock& blockB = m_interface.allocBlock("TestBlock");
303 		blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM)));
304 		blockB.addUniform(Uniform("b", VarType(glu::TYPE_INT_VEC2, PRECISION_LOW)));
305 		blockB.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH));
306 		blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
307 		blockB.setFlags(LAYOUT_STD140|DECLARE_FRAGMENT);
308 
309 		if (numInstances > 0)
310 		{
311 			blockA.setInstanceName("testBlock");
312 			blockA.setArraySize(numInstances);
313 			blockB.setInstanceName("testBlock");
314 			blockB.setArraySize(numInstances);
315 		}
316 
317 		init();
318 	}
319 };
320 
createRandomCaseGroup(tcu::TestCaseGroup * parentGroup,tcu::TestContext & testCtx,const char * groupName,const char * description,UniformBlockCase::BufferMode bufferMode,deUint32 features,int numCases,deUint32 baseSeed)321 void createRandomCaseGroup (tcu::TestCaseGroup* parentGroup, tcu::TestContext& testCtx, const char* groupName, const char* description, UniformBlockCase::BufferMode bufferMode, deUint32 features, int numCases, deUint32 baseSeed)
322 {
323 	tcu::TestCaseGroup* group = new tcu::TestCaseGroup(testCtx, groupName, description);
324 	parentGroup->addChild(group);
325 
326 	baseSeed += (deUint32)testCtx.getCommandLine().getBaseSeed();
327 
328 	for (int ndx = 0; ndx < numCases; ndx++)
329 		group->addChild(new RandomUniformBlockCase(testCtx, de::toString(ndx), "", bufferMode, features, (deUint32)ndx + baseSeed));
330 }
331 
332 // UniformBlockTests
333 
334 class UniformBlockTests : public tcu::TestCaseGroup
335 {
336 public:
337 							UniformBlockTests		(tcu::TestContext& testCtx);
338 							~UniformBlockTests		(void);
339 
340 	void					init					(void);
341 
342 private:
343 							UniformBlockTests		(const UniformBlockTests& other);
344 	UniformBlockTests&		operator=				(const UniformBlockTests& other);
345 };
346 
UniformBlockTests(tcu::TestContext & testCtx)347 UniformBlockTests::UniformBlockTests (tcu::TestContext& testCtx)
348 	: TestCaseGroup(testCtx, "ubo", "Uniform Block tests")
349 {
350 }
351 
~UniformBlockTests(void)352 UniformBlockTests::~UniformBlockTests (void)
353 {
354 }
355 
init(void)356 void UniformBlockTests::init (void)
357 {
358 	static const glu::DataType basicTypes[] =
359 	{
360 		glu::TYPE_FLOAT,
361 		glu::TYPE_FLOAT_VEC2,
362 		glu::TYPE_FLOAT_VEC3,
363 		glu::TYPE_FLOAT_VEC4,
364 		glu::TYPE_INT,
365 		glu::TYPE_INT_VEC2,
366 		glu::TYPE_INT_VEC3,
367 		glu::TYPE_INT_VEC4,
368 		glu::TYPE_UINT,
369 		glu::TYPE_UINT_VEC2,
370 		glu::TYPE_UINT_VEC3,
371 		glu::TYPE_UINT_VEC4,
372 		glu::TYPE_BOOL,
373 		glu::TYPE_BOOL_VEC2,
374 		glu::TYPE_BOOL_VEC3,
375 		glu::TYPE_BOOL_VEC4,
376 		glu::TYPE_FLOAT_MAT2,
377 		glu::TYPE_FLOAT_MAT3,
378 		glu::TYPE_FLOAT_MAT4,
379 		glu::TYPE_FLOAT_MAT2X3,
380 		glu::TYPE_FLOAT_MAT2X4,
381 		glu::TYPE_FLOAT_MAT3X2,
382 		glu::TYPE_FLOAT_MAT3X4,
383 		glu::TYPE_FLOAT_MAT4X2,
384 		glu::TYPE_FLOAT_MAT4X3
385 	};
386 
387 	static const struct
388 	{
389 		const std::string	name;
390 		deUint32			flags;
391 	} precisionFlags[] =
392 	{
393 		// TODO remove PRECISION_LOW because both PRECISION_LOW and PRECISION_MEDIUM means relaxed precision?
394 		{ "lowp",		PRECISION_LOW		},
395 		{ "mediump",	PRECISION_MEDIUM	},
396 		{ "highp",		PRECISION_HIGH		}
397 	};
398 
399 	static const struct
400 	{
401 		const char*			name;
402 		deUint32			flags;
403 	} layoutFlags[] =
404 	{
405 		{ "std140",		LAYOUT_STD140	}
406 	};
407 
408 	static const struct
409 	{
410 		const std::string	name;
411 		deUint32			flags;
412 	} matrixFlags[] =
413 	{
414 		{ "row_major",		LAYOUT_ROW_MAJOR	},
415 		{ "column_major",	LAYOUT_COLUMN_MAJOR }
416 	};
417 
418 	static const struct
419 	{
420 		const char*							name;
421 		UniformBlockCase::BufferMode		mode;
422 	} bufferModes[] =
423 	{
424 		{ "per_block_buffer",	UniformBlockCase::BUFFERMODE_PER_BLOCK },
425 		{ "single_buffer",		UniformBlockCase::BUFFERMODE_SINGLE	}
426 	};
427 
428 	// ubo.2_level_array
429 	{
430 		tcu::TestCaseGroup* nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_array", "2-level basic array variable in single buffer");
431 		addChild(nestedArrayGroup);
432 
433 		for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
434 		{
435 			tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
436 			nestedArrayGroup->addChild(layoutGroup);
437 
438 			for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
439 			{
440 				const glu::DataType	type		= basicTypes[basicTypeNdx];
441 				const char*			typeName	= glu::getDataTypeName(type);
442 				const int			childSize	= 4;
443 				const int			parentSize	= 3;
444 				const VarType		childType	(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), childSize);
445 				const VarType		parentType	(childType, parentSize);
446 
447 				createBlockBasicTypeCases(layoutGroup, m_testCtx, typeName, parentType, layoutFlags[layoutFlagNdx].flags);
448 
449 				if (glu::isDataTypeMatrix(type))
450 				{
451 					for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
452 						createBlockBasicTypeCases(layoutGroup, m_testCtx, (std::string(matrixFlags[matFlagNdx].name) + "_" + typeName),
453 												  parentType, layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags);
454 				}
455 			}
456 		}
457 	}
458 
459 	// ubo.3_level_array
460 	{
461 		tcu::TestCaseGroup* nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "3_level_array", "3-level basic array variable in single buffer");
462 		addChild(nestedArrayGroup);
463 
464 		for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
465 		{
466 			tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
467 			nestedArrayGroup->addChild(layoutGroup);
468 
469 			for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
470 			{
471 				const glu::DataType	type		= basicTypes[basicTypeNdx];
472 				const char*			typeName	= glu::getDataTypeName(type);
473 				const int			childSize0	= 2;
474 				const int			childSize1	= 4;
475 				const int			parentSize	= 3;
476 				const VarType		childType0	(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), childSize0);
477 				const VarType		childType1	(childType0, childSize1);
478 				const VarType		parentType	(childType1, parentSize);
479 
480 				createBlockBasicTypeCases(layoutGroup, m_testCtx, typeName, parentType, layoutFlags[layoutFlagNdx].flags);
481 
482 				if (glu::isDataTypeMatrix(type))
483 				{
484 					for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
485 						createBlockBasicTypeCases(layoutGroup, m_testCtx, (std::string(matrixFlags[matFlagNdx].name) + "_" + typeName),
486 												  parentType, layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags);
487 				}
488 			}
489 		}
490 	}
491 
492 	// ubo.2_level_struct_array
493 	{
494 		tcu::TestCaseGroup* structArrayArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_struct_array", "Struct array in one uniform block");
495 		addChild(structArrayArrayGroup);
496 
497 		for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
498 		{
499 			tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
500 			structArrayArrayGroup->addChild(modeGroup);
501 
502 			for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
503 			{
504 				for (int isArray = 0; isArray < 2; isArray++)
505 				{
506 					std::string	baseName	= layoutFlags[layoutFlagNdx].name;
507 					deUint32	baseFlags	= layoutFlags[layoutFlagNdx].flags;
508 
509 					if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
510 						continue; // Doesn't make sense to add this variant.
511 
512 					if (isArray)
513 						baseName += "_instance_array";
514 
515 					modeGroup->addChild(new Block2LevelStructArrayCase(m_testCtx, (baseName + "_vertex"),	"", baseFlags|DECLARE_VERTEX,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
516 					modeGroup->addChild(new Block2LevelStructArrayCase(m_testCtx, (baseName + "_fragment"),	"", baseFlags|DECLARE_FRAGMENT,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
517 					modeGroup->addChild(new Block2LevelStructArrayCase(m_testCtx, (baseName + "_both"),	"",		baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,	bufferModes[modeNdx].mode, isArray ? 3 : 0));
518 				}
519 			}
520 		}
521 	}
522 
523 	// ubo.single_basic_type
524 	{
525 		tcu::TestCaseGroup* singleBasicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "single_basic_type", "Single basic variable in single buffer");
526 		addChild(singleBasicTypeGroup);
527 
528 		for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
529 		{
530 			tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
531 			singleBasicTypeGroup->addChild(layoutGroup);
532 
533 			for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
534 			{
535 				glu::DataType	type		= basicTypes[basicTypeNdx];
536 				const char*		typeName	= glu::getDataTypeName(type);
537 
538 				if (glu::isDataTypeBoolOrBVec(type))
539 					createBlockBasicTypeCases(layoutGroup, m_testCtx, typeName, VarType(type, 0), layoutFlags[layoutFlagNdx].flags);
540 				else
541 				{
542 					for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisionFlags); precNdx++)
543 						createBlockBasicTypeCases(layoutGroup, m_testCtx, precisionFlags[precNdx].name + "_" + typeName,
544 												  VarType(type, precisionFlags[precNdx].flags), layoutFlags[layoutFlagNdx].flags);
545 				}
546 
547 				if (glu::isDataTypeMatrix(type))
548 				{
549 					for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
550 					{
551 						for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisionFlags); precNdx++)
552 							createBlockBasicTypeCases(layoutGroup, m_testCtx, matrixFlags[matFlagNdx].name + "_" + precisionFlags[precNdx].name + "_" + typeName,
553 													  VarType(type, precisionFlags[precNdx].flags), layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags);
554 					}
555 				}
556 			}
557 		}
558 	}
559 
560 	// ubo.single_basic_array
561 	{
562 		tcu::TestCaseGroup* singleBasicArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_basic_array", "Single basic array variable in single buffer");
563 		addChild(singleBasicArrayGroup);
564 
565 		for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
566 		{
567 			tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
568 			singleBasicArrayGroup->addChild(layoutGroup);
569 
570 			for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
571 			{
572 				glu::DataType	type		= basicTypes[basicTypeNdx];
573 				const char*		typeName	= glu::getDataTypeName(type);
574 				const int		arraySize	= 3;
575 
576 				createBlockBasicTypeCases(layoutGroup, m_testCtx, typeName,
577 										  VarType(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), arraySize),
578 										  layoutFlags[layoutFlagNdx].flags);
579 
580 				if (glu::isDataTypeMatrix(type))
581 				{
582 					for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
583 						createBlockBasicTypeCases(layoutGroup, m_testCtx, matrixFlags[matFlagNdx].name + "_" + typeName,
584 												  VarType(VarType(type, PRECISION_HIGH), arraySize),
585 												  layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags);
586 				}
587 			}
588 		}
589 	}
590 
591 	// ubo.single_struct
592 	{
593 		tcu::TestCaseGroup* singleStructGroup = new tcu::TestCaseGroup(m_testCtx, "single_struct", "Single struct in uniform block");
594 		addChild(singleStructGroup);
595 
596 		for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
597 		{
598 			tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
599 			singleStructGroup->addChild(modeGroup);
600 
601 			for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
602 			{
603 				for (int isArray = 0; isArray < 2; isArray++)
604 				{
605 					std::string	baseName	= layoutFlags[layoutFlagNdx].name;
606 					deUint32	baseFlags	= layoutFlags[layoutFlagNdx].flags;
607 
608 					if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
609 						continue; // Doesn't make sense to add this variant.
610 
611 					if (isArray)
612 						baseName += "_instance_array";
613 
614 					modeGroup->addChild(new BlockSingleStructCase(m_testCtx, baseName + "_vertex",		"", baseFlags|DECLARE_VERTEX,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
615 					modeGroup->addChild(new BlockSingleStructCase(m_testCtx, baseName + "_fragment",	"", baseFlags|DECLARE_FRAGMENT,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
616 					modeGroup->addChild(new BlockSingleStructCase(m_testCtx, baseName + "_both",	"",		baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,	bufferModes[modeNdx].mode, isArray ? 3 : 0));
617 				}
618 			}
619 		}
620 	}
621 
622 	// ubo.single_struct_array
623 	{
624 		tcu::TestCaseGroup* singleStructArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_struct_array", "Struct array in one uniform block");
625 		addChild(singleStructArrayGroup);
626 
627 		for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
628 		{
629 			tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
630 			singleStructArrayGroup->addChild(modeGroup);
631 
632 			for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
633 			{
634 				for (int isArray = 0; isArray < 2; isArray++)
635 				{
636 					std::string	baseName	= layoutFlags[layoutFlagNdx].name;
637 					deUint32	baseFlags	= layoutFlags[layoutFlagNdx].flags;
638 
639 					if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
640 						continue; // Doesn't make sense to add this variant.
641 
642 					if (isArray)
643 						baseName += "_instance_array";
644 
645 					modeGroup->addChild(new BlockSingleStructArrayCase(m_testCtx, baseName + "_vertex",		"", baseFlags|DECLARE_VERTEX,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
646 					modeGroup->addChild(new BlockSingleStructArrayCase(m_testCtx, baseName + "_fragment",	"", baseFlags|DECLARE_FRAGMENT,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
647 					modeGroup->addChild(new BlockSingleStructArrayCase(m_testCtx, baseName + "_both",	"",		baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,	bufferModes[modeNdx].mode, isArray ? 3 : 0));
648 				}
649 			}
650 		}
651 	}
652 
653 	// ubo.single_nested_struct
654 	{
655 		tcu::TestCaseGroup* singleNestedStructGroup = new tcu::TestCaseGroup(m_testCtx, "single_nested_struct", "Nested struct in one uniform block");
656 		addChild(singleNestedStructGroup);
657 
658 		for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
659 		{
660 			tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
661 			singleNestedStructGroup->addChild(modeGroup);
662 
663 			for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
664 			{
665 				for (int isArray = 0; isArray < 2; isArray++)
666 				{
667 					std::string	baseName	= layoutFlags[layoutFlagNdx].name;
668 					deUint32	baseFlags	= layoutFlags[layoutFlagNdx].flags;
669 
670 					if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
671 						continue; // Doesn't make sense to add this variant.
672 
673 					if (isArray)
674 						baseName += "_instance_array";
675 
676 					modeGroup->addChild(new BlockSingleNestedStructCase(m_testCtx, baseName + "_vertex",	"", baseFlags|DECLARE_VERTEX,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
677 					modeGroup->addChild(new BlockSingleNestedStructCase(m_testCtx, baseName + "_fragment",	"", baseFlags|DECLARE_FRAGMENT,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
678 					modeGroup->addChild(new BlockSingleNestedStructCase(m_testCtx, baseName + "_both",	"",		baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,	bufferModes[modeNdx].mode, isArray ? 3 : 0));
679 				}
680 			}
681 		}
682 	}
683 
684 	// ubo.single_nested_struct_array
685 	{
686 		tcu::TestCaseGroup* singleNestedStructArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_nested_struct_array", "Nested struct array in one uniform block");
687 		addChild(singleNestedStructArrayGroup);
688 
689 		for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
690 		{
691 			tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
692 			singleNestedStructArrayGroup->addChild(modeGroup);
693 
694 			for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
695 			{
696 				for (int isArray = 0; isArray < 2; isArray++)
697 				{
698 					std::string	baseName	= layoutFlags[layoutFlagNdx].name;
699 					deUint32	baseFlags	= layoutFlags[layoutFlagNdx].flags;
700 
701 					if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
702 						continue; // Doesn't make sense to add this variant.
703 
704 					if (isArray)
705 						baseName += "_instance_array";
706 
707 					modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_testCtx, baseName + "_vertex",	"", baseFlags|DECLARE_VERTEX,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
708 					modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_testCtx, baseName + "_fragment",	"", baseFlags|DECLARE_FRAGMENT,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
709 					modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_testCtx, baseName + "_both",	"",		baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,	bufferModes[modeNdx].mode, isArray ? 3 : 0));
710 				}
711 			}
712 		}
713 	}
714 
715 	// ubo.instance_array_basic_type
716 	{
717 		tcu::TestCaseGroup* instanceArrayBasicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "instance_array_basic_type", "Single basic variable in instance array");
718 		addChild(instanceArrayBasicTypeGroup);
719 
720 		for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
721 		{
722 			tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
723 			instanceArrayBasicTypeGroup->addChild(layoutGroup);
724 
725 			for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
726 			{
727 				glu::DataType	type			= basicTypes[basicTypeNdx];
728 				const char*		typeName		= glu::getDataTypeName(type);
729 				const int		numInstances	= 3;
730 
731 				createBlockBasicTypeCases(layoutGroup, m_testCtx, typeName,
732 										  VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH),
733 										  layoutFlags[layoutFlagNdx].flags, numInstances);
734 
735 				if (glu::isDataTypeMatrix(type))
736 				{
737 					for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
738 						createBlockBasicTypeCases(layoutGroup, m_testCtx, matrixFlags[matFlagNdx].name + "_" + typeName,
739 												  VarType(type, PRECISION_HIGH), layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags,
740 												  numInstances);
741 				}
742 			}
743 		}
744 	}
745 
746 	// ubo.multi_basic_types
747 	{
748 		tcu::TestCaseGroup* multiBasicTypesGroup = new tcu::TestCaseGroup(m_testCtx, "multi_basic_types", "Multiple buffers with basic types");
749 		addChild(multiBasicTypesGroup);
750 
751 		for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
752 		{
753 			tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
754 			multiBasicTypesGroup->addChild(modeGroup);
755 
756 			for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
757 			{
758 				for (int isArray = 0; isArray < 2; isArray++)
759 				{
760 					std::string	baseName	= layoutFlags[layoutFlagNdx].name;
761 					deUint32	baseFlags	= layoutFlags[layoutFlagNdx].flags;
762 
763 					if (isArray)
764 						baseName += "_instance_array";
765 
766 					modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_vertex",	"", baseFlags|DECLARE_VERTEX,					baseFlags|DECLARE_VERTEX,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
767 					modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_fragment",	"", baseFlags|DECLARE_FRAGMENT,					baseFlags|DECLARE_FRAGMENT,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
768 					modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_both",	"", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,		baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,	bufferModes[modeNdx].mode, isArray ? 3 : 0));
769 					modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_mixed",	"", baseFlags|DECLARE_VERTEX,					baseFlags|DECLARE_FRAGMENT,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
770 				}
771 			}
772 		}
773 	}
774 
775 	// ubo.multi_nested_struct
776 	{
777 		tcu::TestCaseGroup* multiNestedStructGroup = new tcu::TestCaseGroup(m_testCtx, "multi_nested_struct", "Multiple buffers with nested structs");
778 		addChild(multiNestedStructGroup);
779 
780 		for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
781 		{
782 			tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
783 			multiNestedStructGroup->addChild(modeGroup);
784 
785 			for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
786 			{
787 				for (int isArray = 0; isArray < 2; isArray++)
788 				{
789 					std::string	baseName	= layoutFlags[layoutFlagNdx].name;
790 					deUint32	baseFlags	= layoutFlags[layoutFlagNdx].flags;
791 
792 					if (isArray)
793 						baseName += "_instance_array";
794 
795 					modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_vertex",		"", baseFlags|DECLARE_VERTEX,					baseFlags|DECLARE_VERTEX,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
796 					modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_fragment",	"", baseFlags|DECLARE_FRAGMENT,					baseFlags|DECLARE_FRAGMENT,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
797 					modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_both",	"",		baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,	baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,	bufferModes[modeNdx].mode, isArray ? 3 : 0));
798 					modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_mixed",		"", baseFlags|DECLARE_VERTEX,					baseFlags|DECLARE_FRAGMENT,					bufferModes[modeNdx].mode, isArray ? 3 : 0));
799 				}
800 			}
801 		}
802 	}
803 
804 	// .link_by_binding
805 	{
806 		tcu::TestCaseGroup* linkByBindingGroup = new tcu::TestCaseGroup(m_testCtx, "link_by_binding", "Blocks with same name but different binding");
807 		addChild(linkByBindingGroup);
808 
809 		linkByBindingGroup->addChild(new LinkByBindingCase(m_testCtx, "single_buf_single_instance",		"", UniformBlockCase::BUFFERMODE_SINGLE, 0));
810 		linkByBindingGroup->addChild(new LinkByBindingCase(m_testCtx, "single_buf_instance_array",		"", UniformBlockCase::BUFFERMODE_SINGLE, 2));
811 		linkByBindingGroup->addChild(new LinkByBindingCase(m_testCtx, "per_block_buf_single_instance",	"", UniformBlockCase::BUFFERMODE_PER_BLOCK, 0));
812 		linkByBindingGroup->addChild(new LinkByBindingCase(m_testCtx, "per_block_buf_instance_array",	"", UniformBlockCase::BUFFERMODE_PER_BLOCK, 2));
813 	}
814 
815 	// ubo.random
816 	{
817 		const deUint32	allShaders		= FEATURE_VERTEX_BLOCKS|FEATURE_FRAGMENT_BLOCKS|FEATURE_SHARED_BLOCKS;
818 		const deUint32	allLayouts		= FEATURE_STD140_LAYOUT;
819 		const deUint32	allBasicTypes	= FEATURE_VECTORS|FEATURE_MATRICES;
820 		const deUint32	unused			= FEATURE_UNUSED_MEMBERS|FEATURE_UNUSED_UNIFORMS;
821 		const deUint32	matFlags		= FEATURE_MATRIX_LAYOUT;
822 		const deUint32	allFeatures		= ~FEATURE_ARRAYS_OF_ARRAYS;
823 
824 		tcu::TestCaseGroup* randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random Uniform Block cases");
825 		addChild(randomGroup);
826 
827 		// Basic types.
828 		createRandomCaseGroup(randomGroup, m_testCtx, "scalar_types",	"Scalar types only, per-block buffers",				UniformBlockCase::BUFFERMODE_PER_BLOCK,	allShaders|allLayouts|unused,										25, 0);
829 		createRandomCaseGroup(randomGroup, m_testCtx, "vector_types",	"Scalar and vector types only, per-block buffers",	UniformBlockCase::BUFFERMODE_PER_BLOCK,	allShaders|allLayouts|unused|FEATURE_VECTORS,						25, 25);
830 		createRandomCaseGroup(randomGroup, m_testCtx, "basic_types",	"All basic types, per-block buffers",				UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags,				25, 50);
831 		createRandomCaseGroup(randomGroup, m_testCtx, "basic_arrays",	"Arrays, per-block buffers",						UniformBlockCase::BUFFERMODE_PER_BLOCK,	allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_ARRAYS,	25, 50);
832 
833 		createRandomCaseGroup(randomGroup, m_testCtx, "basic_instance_arrays",					"Basic instance arrays, per-block buffers",				UniformBlockCase::BUFFERMODE_PER_BLOCK,	allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_INSTANCE_ARRAYS,								25, 75);
834 		createRandomCaseGroup(randomGroup, m_testCtx, "nested_structs",							"Nested structs, per-block buffers",					UniformBlockCase::BUFFERMODE_PER_BLOCK,	allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_STRUCTS,										25, 100);
835 		createRandomCaseGroup(randomGroup, m_testCtx, "nested_structs_arrays",					"Nested structs, arrays, per-block buffers",			UniformBlockCase::BUFFERMODE_PER_BLOCK,	allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_STRUCTS|FEATURE_ARRAYS,							25, 150);
836 		createRandomCaseGroup(randomGroup, m_testCtx, "nested_structs_instance_arrays",			"Nested structs, instance arrays, per-block buffers",	UniformBlockCase::BUFFERMODE_PER_BLOCK,	allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_STRUCTS|FEATURE_INSTANCE_ARRAYS,				25, 125);
837 		createRandomCaseGroup(randomGroup, m_testCtx, "nested_structs_arrays_instance_arrays",	"Nested structs, instance arrays, per-block buffers",	UniformBlockCase::BUFFERMODE_PER_BLOCK,	allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_STRUCTS|FEATURE_ARRAYS|FEATURE_INSTANCE_ARRAYS,	25, 175);
838 
839 		createRandomCaseGroup(randomGroup, m_testCtx, "all_per_block_buffers",	"All random features, per-block buffers",	UniformBlockCase::BUFFERMODE_PER_BLOCK,	allFeatures,	50, 200);
840 		createRandomCaseGroup(randomGroup, m_testCtx, "all_shared_buffer",		"All random features, shared buffer",		UniformBlockCase::BUFFERMODE_SINGLE,	allFeatures,	50, 250);
841 	}
842 }
843 
844 } // anonymous
845 
createTests(tcu::TestContext & testCtx)846 tcu::TestCaseGroup*	createTests	(tcu::TestContext& testCtx)
847 {
848 	return new UniformBlockTests(testCtx);
849 }
850 
851 } // ubo
852 } // vkt
853