Home | History | Annotate | Download | only in functional
      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 
     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 
    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 
    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 
    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 
    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 
    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:
    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:
    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 
    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:
    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 
    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:
    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 
    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:
    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 
    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:
    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 
    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:
    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 
    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:
    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 
    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:
    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 
    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:
    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 
    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:
    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 
    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 
    730 SSBOLayoutTests::SSBOLayoutTests (Context& context)
    731 	: TestCaseGroup(context, "layout", "SSBO Layout Tests")
    732 {
    733 }
    734 
    735 SSBOLayoutTests::~SSBOLayoutTests (void)
    736 {
    737 }
    738 
    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