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