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