Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.0 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 Vertex array and buffer tests
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es3fVertexArrayTest.hpp"
     25 #include "glsVertexArrayTests.hpp"
     26 
     27 #include <sstream>
     28 
     29 using namespace deqp::gls;
     30 
     31 namespace deqp
     32 {
     33 namespace gles3
     34 {
     35 namespace Functional
     36 {
     37 
     38 class SingleVertexArrayUsageGroup : public TestCaseGroup
     39 {
     40 public:
     41 									SingleVertexArrayUsageGroup		(Context& context, Array::Usage usage);
     42 	virtual							~SingleVertexArrayUsageGroup	(void);
     43 
     44 	virtual void					init							(void);
     45 
     46 private:
     47 									SingleVertexArrayUsageGroup		(const SingleVertexArrayUsageGroup& other);
     48 	SingleVertexArrayUsageGroup&	operator=						(const SingleVertexArrayUsageGroup& other);
     49 
     50 	Array::Usage					m_usage;
     51 };
     52 
     53 SingleVertexArrayUsageGroup::SingleVertexArrayUsageGroup (Context& context, Array::Usage usage)
     54 	: TestCaseGroup	(context, Array::usageTypeToString(usage).c_str(), Array::usageTypeToString(usage).c_str())
     55 	, m_usage		(usage)
     56 {
     57 }
     58 
     59 SingleVertexArrayUsageGroup::~SingleVertexArrayUsageGroup (void)
     60 {
     61 }
     62 
     63 template<class T>
     64 static std::string typeToString (T t)
     65 {
     66 	std::stringstream strm;
     67 	strm << t;
     68 	return strm.str();
     69 }
     70 
     71 void SingleVertexArrayUsageGroup::init (void)
     72 {
     73 	int					counts[]		= {1, 256};
     74 	int					strides[]		= {0, -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
     75 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE};
     76 
     77 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
     78 	{
     79 		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
     80 		{
     81 			for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
     82 			{
     83 				const int			stride	= (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]);
     84 				const bool			aligned	= (stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0;
     85 				const std::string	name	= "stride" + typeToString(stride) + "_" + Array::inputTypeToString(inputTypes[inputTypeNdx]) + "_quads" + typeToString(counts[countNdx]);
     86 
     87 				MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
     88 																Array::OUTPUTTYPE_VEC2,
     89 																Array::STORAGE_BUFFER,
     90 																m_usage,
     91 																2,
     92 																0,
     93 																stride,
     94 																false,
     95 																GLValue::getMinValue(inputTypes[inputTypeNdx]),
     96 																GLValue::getMaxValue(inputTypes[inputTypeNdx]));
     97 
     98 				MultiVertexArrayTest::Spec spec;
     99 				spec.primitive	= Array::PRIMITIVE_TRIANGLES;
    100 				spec.drawCount	= counts[countNdx];
    101 				spec.first		= 0;
    102 				spec.arrays.push_back(arraySpec);
    103 
    104 				if (aligned)
    105 					addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
    106 			}
    107 		}
    108 	}
    109 }
    110 
    111 class SingleVertexArrayUsageTests : public TestCaseGroup
    112 {
    113 public:
    114 									SingleVertexArrayUsageTests		(Context& context);
    115 	virtual							~SingleVertexArrayUsageTests	(void);
    116 
    117 	virtual void					init							(void);
    118 
    119 private:
    120 									SingleVertexArrayUsageTests		(const SingleVertexArrayUsageTests& other);
    121 	SingleVertexArrayUsageTests&	operator=						(const SingleVertexArrayUsageTests& other);
    122 };
    123 
    124 SingleVertexArrayUsageTests::SingleVertexArrayUsageTests (Context& context)
    125 	: TestCaseGroup(context, "usages", "Single vertex atribute, usage")
    126 {
    127 }
    128 
    129 SingleVertexArrayUsageTests::~SingleVertexArrayUsageTests (void)
    130 {
    131 }
    132 
    133 void SingleVertexArrayUsageTests::init (void)
    134 {
    135 	// Test usage
    136 	Array::Usage		usages[]		= { Array::USAGE_STATIC_DRAW, Array::USAGE_STREAM_DRAW, Array::USAGE_DYNAMIC_DRAW, Array::USAGE_STATIC_COPY, Array::USAGE_STREAM_COPY, Array::USAGE_DYNAMIC_COPY, Array::USAGE_STATIC_READ, Array::USAGE_STREAM_READ, Array::USAGE_DYNAMIC_READ };
    137 	for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++)
    138 	{
    139 		addChild(new SingleVertexArrayUsageGroup(m_context, usages[usageNdx]));
    140 	}
    141 }
    142 
    143 class SingleVertexArrayStrideGroup : public TestCaseGroup
    144 {
    145 public:
    146 									SingleVertexArrayStrideGroup	(Context& context, Array::InputType type);
    147 	virtual							~SingleVertexArrayStrideGroup	(void);
    148 
    149 	virtual void					init							(void);
    150 
    151 private:
    152 									SingleVertexArrayStrideGroup	(const SingleVertexArrayStrideGroup& other);
    153 	SingleVertexArrayStrideGroup&	operator=						(const SingleVertexArrayStrideGroup& other);
    154 
    155 	Array::InputType				m_type;
    156 };
    157 
    158 SingleVertexArrayStrideGroup::SingleVertexArrayStrideGroup (Context& context, Array::InputType type)
    159 	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
    160 	, m_type		(type)
    161 {
    162 }
    163 
    164 SingleVertexArrayStrideGroup::~SingleVertexArrayStrideGroup (void)
    165 {
    166 }
    167 
    168 void SingleVertexArrayStrideGroup::init (void)
    169 {
    170 	Array::Storage		storages[]		= {Array::STORAGE_USER, Array::STORAGE_BUFFER};
    171 	int					counts[]		= {1, 256};
    172 	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
    173 
    174 	for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
    175 	{
    176 		for (int componentCount = 2; componentCount < 5; componentCount++)
    177 		{
    178 			for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
    179 			{
    180 				for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
    181 				{
    182 					const bool	packed			= m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
    183 					const int	stride			= (strides[strideNdx] < 0) ? ((packed) ? (16) : (Array::inputTypeSize(m_type) * componentCount)) : (strides[strideNdx]);
    184 					const int	alignment		= (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
    185 					const bool	bufferUnaligned	= (storages[storageNdx] == Array::STORAGE_BUFFER) && (stride % alignment) != 0;
    186 
    187 					std::string name = Array::storageToString(storages[storageNdx]) + "_stride" + typeToString(stride) + "_components" + typeToString(componentCount) + "_quads" + typeToString(counts[countNdx]);
    188 
    189 					if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && componentCount != 4)
    190 						continue;
    191 
    192 					MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
    193 																	Array::OUTPUTTYPE_VEC4,
    194 																	storages[storageNdx],
    195 																	Array::USAGE_DYNAMIC_DRAW,
    196 																	componentCount,
    197 																	0,
    198 																	stride,
    199 																	false,
    200 																	GLValue::getMinValue(m_type),
    201 																	GLValue::getMaxValue(m_type));
    202 
    203 					MultiVertexArrayTest::Spec spec;
    204 					spec.primitive	= Array::PRIMITIVE_TRIANGLES;
    205 					spec.drawCount	= counts[countNdx];
    206 					spec.first		= 0;
    207 					spec.arrays.push_back(arraySpec);
    208 
    209 					if (!bufferUnaligned)
    210 						addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
    211 				}
    212 			}
    213 		}
    214 	}
    215 }
    216 
    217 class SingleVertexArrayStrideTests : public TestCaseGroup
    218 {
    219 public:
    220 									SingleVertexArrayStrideTests	(Context& context);
    221 	virtual							~SingleVertexArrayStrideTests	(void);
    222 
    223 	virtual void					init							(void);
    224 
    225 private:
    226 									SingleVertexArrayStrideTests	(const SingleVertexArrayStrideTests& other);
    227 	SingleVertexArrayStrideTests&	operator=						(const SingleVertexArrayStrideTests& other);
    228 };
    229 
    230 SingleVertexArrayStrideTests::SingleVertexArrayStrideTests (Context& context)
    231 	: TestCaseGroup(context, "strides", "Single stride vertex atribute")
    232 {
    233 }
    234 
    235 SingleVertexArrayStrideTests::~SingleVertexArrayStrideTests (void)
    236 {
    237 }
    238 
    239 void SingleVertexArrayStrideTests::init (void)
    240 {
    241 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE, /*Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE,*/ Array::INPUTTYPE_FIXED, Array::INPUTTYPE_INT_2_10_10_10 };
    242 
    243 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
    244 	{
    245 		addChild(new SingleVertexArrayStrideGroup(m_context, inputTypes[inputTypeNdx]));
    246 	}
    247 }
    248 
    249 class SingleVertexArrayFirstGroup : public TestCaseGroup
    250 {
    251 public:
    252 									SingleVertexArrayFirstGroup	(Context& context, Array::InputType type);
    253 	virtual							~SingleVertexArrayFirstGroup	(void);
    254 
    255 	virtual void					init							(void);
    256 
    257 private:
    258 									SingleVertexArrayFirstGroup	(const SingleVertexArrayFirstGroup& other);
    259 	SingleVertexArrayFirstGroup&	operator=						(const SingleVertexArrayFirstGroup& other);
    260 	Array::InputType				m_type;
    261 };
    262 
    263 SingleVertexArrayFirstGroup::SingleVertexArrayFirstGroup (Context& context, Array::InputType type)
    264 	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
    265 	, m_type		(type)
    266 {
    267 }
    268 
    269 SingleVertexArrayFirstGroup::~SingleVertexArrayFirstGroup (void)
    270 {
    271 }
    272 
    273 void SingleVertexArrayFirstGroup::init (void)
    274 {
    275 	int					counts[]		= {5, 256};
    276 	int					firsts[]		= {6, 24};
    277 	int					offsets[]		= {1, 16, 17};
    278 	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
    279 
    280 	for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
    281 	{
    282 		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
    283 		{
    284 			for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
    285 			{
    286 				for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); firstNdx++)
    287 				{
    288 					const bool	packed			= m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
    289 					const int	componentCount	= (packed) ? (4) : (2);
    290 					const int	stride			= (strides[strideNdx] < 0) ? ((packed) ? (8) : (Array::inputTypeSize(m_type) * componentCount)) : (strides[strideNdx]);
    291 					const int	alignment		= (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
    292 					const bool	aligned			= ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0);
    293 					std::string name			= "first" + typeToString(firsts[firstNdx]) + "_offset" + typeToString(offsets[offsetNdx]) + "_stride" + typeToString(stride) + "_quads" + typeToString(counts[countNdx]);
    294 
    295 					MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
    296 																	Array::OUTPUTTYPE_VEC2,
    297 																	Array::STORAGE_BUFFER,
    298 																	Array::USAGE_DYNAMIC_DRAW,
    299 																	componentCount,
    300 																	offsets[offsetNdx],
    301 																	stride,
    302 																	false,
    303 																	GLValue::getMinValue(m_type),
    304 																	GLValue::getMaxValue(m_type));
    305 
    306 					MultiVertexArrayTest::Spec spec;
    307 					spec.primitive	= Array::PRIMITIVE_TRIANGLES;
    308 					spec.drawCount	= counts[countNdx];
    309 					spec.first		= firsts[firstNdx];
    310 					spec.arrays.push_back(arraySpec);
    311 
    312 					if (aligned)
    313 						addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
    314 				}
    315 			}
    316 		}
    317 	}
    318 }
    319 
    320 class SingleVertexArrayFirstTests : public TestCaseGroup
    321 {
    322 public:
    323 									SingleVertexArrayFirstTests	(Context& context);
    324 	virtual							~SingleVertexArrayFirstTests	(void);
    325 
    326 	virtual void					init							(void);
    327 
    328 private:
    329 									SingleVertexArrayFirstTests	(const SingleVertexArrayFirstTests& other);
    330 	SingleVertexArrayFirstTests&	operator=						(const SingleVertexArrayFirstTests& other);
    331 };
    332 
    333 SingleVertexArrayFirstTests::SingleVertexArrayFirstTests (Context& context)
    334 	: TestCaseGroup(context, "first", "Single vertex attribute, different first values to drawArrays")
    335 {
    336 }
    337 
    338 SingleVertexArrayFirstTests::~SingleVertexArrayFirstTests (void)
    339 {
    340 }
    341 
    342 void SingleVertexArrayFirstTests::init (void)
    343 {
    344 	// Test offset with different input types, component counts and storage, Usage(?)
    345 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_INT_2_10_10_10 };
    346 
    347 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
    348 	{
    349 		addChild(new SingleVertexArrayFirstGroup(m_context, inputTypes[inputTypeNdx]));
    350 	}
    351 }
    352 
    353 class SingleVertexArrayOffsetGroup : public TestCaseGroup
    354 {
    355 public:
    356 									SingleVertexArrayOffsetGroup	(Context& context, Array::InputType type);
    357 	virtual							~SingleVertexArrayOffsetGroup	(void);
    358 
    359 	virtual void					init							(void);
    360 
    361 private:
    362 									SingleVertexArrayOffsetGroup	(const SingleVertexArrayOffsetGroup& other);
    363 	SingleVertexArrayOffsetGroup&	operator=						(const SingleVertexArrayOffsetGroup& other);
    364 	Array::InputType				m_type;
    365 };
    366 
    367 SingleVertexArrayOffsetGroup::SingleVertexArrayOffsetGroup (Context& context, Array::InputType type)
    368 	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
    369 	, m_type		(type)
    370 {
    371 }
    372 
    373 SingleVertexArrayOffsetGroup::~SingleVertexArrayOffsetGroup (void)
    374 {
    375 }
    376 
    377 void SingleVertexArrayOffsetGroup::init (void)
    378 {
    379 	int					counts[]		= {1, 256};
    380 	int					offsets[]		= {1, 4, 17, 32};
    381 	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
    382 
    383 	for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
    384 	{
    385 		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
    386 		{
    387 			for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
    388 			{
    389 				const bool			packed			= m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
    390 				const int			componentCount	= (packed) ? (4) : (2);
    391 				const int			stride			= (strides[strideNdx] < 0 ? Array::inputTypeSize(m_type) * componentCount : strides[strideNdx]);
    392 				const int			alignment		= (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
    393 				const bool			aligned			= ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0);
    394 				const std::string	name			= "offset" + typeToString(offsets[offsetNdx]) + "_stride" + typeToString(stride) + "_quads" + typeToString(counts[countNdx]);
    395 
    396 				MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
    397 																Array::OUTPUTTYPE_VEC2,
    398 																Array::STORAGE_BUFFER,
    399 																Array::USAGE_DYNAMIC_DRAW,
    400 																componentCount,
    401 																offsets[offsetNdx],
    402 																stride,
    403 																false,
    404 																GLValue::getMinValue(m_type),
    405 																GLValue::getMaxValue(m_type));
    406 
    407 				MultiVertexArrayTest::Spec spec;
    408 				spec.primitive	= Array::PRIMITIVE_TRIANGLES;
    409 				spec.drawCount	= counts[countNdx];
    410 				spec.first		= 0;
    411 				spec.arrays.push_back(arraySpec);
    412 
    413 				if (aligned)
    414 					addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
    415 			}
    416 		}
    417 	}
    418 }
    419 
    420 class SingleVertexArrayOffsetTests : public TestCaseGroup
    421 {
    422 public:
    423 									SingleVertexArrayOffsetTests	(Context& context);
    424 	virtual							~SingleVertexArrayOffsetTests	(void);
    425 
    426 	virtual void					init							(void);
    427 
    428 private:
    429 									SingleVertexArrayOffsetTests	(const SingleVertexArrayOffsetTests& other);
    430 	SingleVertexArrayOffsetTests&	operator=						(const SingleVertexArrayOffsetTests& other);
    431 };
    432 
    433 SingleVertexArrayOffsetTests::SingleVertexArrayOffsetTests (Context& context)
    434 	: TestCaseGroup(context, "offset", "Single vertex atribute offset element")
    435 {
    436 }
    437 
    438 SingleVertexArrayOffsetTests::~SingleVertexArrayOffsetTests (void)
    439 {
    440 }
    441 
    442 void SingleVertexArrayOffsetTests::init (void)
    443 {
    444 	// Test offset with different input types, component counts and storage, Usage(?)
    445 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_INT_2_10_10_10 };
    446 
    447 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
    448 	{
    449 		addChild(new SingleVertexArrayOffsetGroup(m_context, inputTypes[inputTypeNdx]));
    450 	}
    451 }
    452 
    453 class SingleVertexArrayNormalizeGroup : public TestCaseGroup
    454 {
    455 public:
    456 										SingleVertexArrayNormalizeGroup		(Context& context, Array::InputType type);
    457 	virtual								~SingleVertexArrayNormalizeGroup	(void);
    458 
    459 	virtual void						init								(void);
    460 
    461 private:
    462 										SingleVertexArrayNormalizeGroup		(const SingleVertexArrayNormalizeGroup& other);
    463 	SingleVertexArrayNormalizeGroup&	operator=							(const SingleVertexArrayNormalizeGroup& other);
    464 	Array::InputType					m_type;
    465 };
    466 
    467 SingleVertexArrayNormalizeGroup::SingleVertexArrayNormalizeGroup (Context& context, Array::InputType type)
    468 	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
    469 	, m_type		(type)
    470 {
    471 }
    472 
    473 SingleVertexArrayNormalizeGroup::~SingleVertexArrayNormalizeGroup (void)
    474 {
    475 }
    476 
    477 void SingleVertexArrayNormalizeGroup::init (void)
    478 {
    479 	int					counts[]		= {1, 256};
    480 
    481 	for (int componentCount = 2; componentCount < 5; componentCount++)
    482 	{
    483 		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
    484 		{
    485 			if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && componentCount != 4)
    486 				continue;
    487 
    488 			std::string name = "components" + typeToString(componentCount) + "_quads" + typeToString(counts[countNdx]);
    489 
    490 			MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
    491 															Array::OUTPUTTYPE_VEC4,
    492 															Array::STORAGE_USER,
    493 															Array::USAGE_DYNAMIC_DRAW,
    494 															componentCount,
    495 															0,
    496 															0,
    497 															true,
    498 															GLValue::getMinValue(m_type),
    499 															GLValue::getMaxValue(m_type));
    500 
    501 			MultiVertexArrayTest::Spec spec;
    502 			spec.primitive	= Array::PRIMITIVE_TRIANGLES;
    503 			spec.drawCount	= counts[countNdx];
    504 			spec.first		= 0;
    505 			spec.arrays.push_back(arraySpec);
    506 
    507 			addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
    508 		}
    509 	}
    510 }
    511 
    512 class SingleVertexArrayNormalizeTests : public TestCaseGroup
    513 {
    514 public:
    515 										SingleVertexArrayNormalizeTests		(Context& context);
    516 	virtual								~SingleVertexArrayNormalizeTests	(void);
    517 
    518 	virtual void						init								(void);
    519 
    520 private:
    521 										SingleVertexArrayNormalizeTests		(const SingleVertexArrayNormalizeTests& other);
    522 	SingleVertexArrayNormalizeTests&	operator=							(const SingleVertexArrayNormalizeTests& other);
    523 };
    524 
    525 SingleVertexArrayNormalizeTests::SingleVertexArrayNormalizeTests (Context& context)
    526 	: TestCaseGroup(context, "normalize", "Single normalize vertex atribute")
    527 {
    528 }
    529 
    530 SingleVertexArrayNormalizeTests::~SingleVertexArrayNormalizeTests (void)
    531 {
    532 }
    533 
    534 void SingleVertexArrayNormalizeTests::init (void)
    535 {
    536 	// Test normalization with different input types, component counts and storage
    537 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_UNSIGNED_INT, Array::INPUTTYPE_INT, Array::INPUTTYPE_HALF , Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10, Array::INPUTTYPE_INT_2_10_10_10 };
    538 
    539 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
    540 	{
    541 		addChild(new SingleVertexArrayNormalizeGroup(m_context, inputTypes[inputTypeNdx]));
    542 	}
    543 }
    544 
    545 class SingleVertexArrayOutputTypeGroup : public TestCaseGroup
    546 {
    547 public:
    548 										SingleVertexArrayOutputTypeGroup	(Context& context, Array::InputType type);
    549 	virtual								~SingleVertexArrayOutputTypeGroup	(void);
    550 
    551 	virtual void						init								(void);
    552 
    553 private:
    554 										SingleVertexArrayOutputTypeGroup	(const SingleVertexArrayOutputTypeGroup& other);
    555 	SingleVertexArrayOutputTypeGroup&	operator=							(const SingleVertexArrayOutputTypeGroup& other);
    556 	Array::InputType					m_type;
    557 };
    558 
    559 SingleVertexArrayOutputTypeGroup::SingleVertexArrayOutputTypeGroup (Context& context, Array::InputType type)
    560 	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
    561 	, m_type		(type)
    562 {
    563 }
    564 
    565 SingleVertexArrayOutputTypeGroup::~SingleVertexArrayOutputTypeGroup (void)
    566 {
    567 }
    568 
    569 void SingleVertexArrayOutputTypeGroup::init (void)
    570 {
    571 	Array::OutputType	outputTypes[]	= {Array::OUTPUTTYPE_VEC2, Array::OUTPUTTYPE_VEC3, Array::OUTPUTTYPE_VEC4, Array::OUTPUTTYPE_IVEC2, Array::OUTPUTTYPE_IVEC3, Array::OUTPUTTYPE_IVEC4, Array::OUTPUTTYPE_UVEC2, Array::OUTPUTTYPE_UVEC3, Array::OUTPUTTYPE_UVEC4 };
    572 	Array::Storage		storages[]		= {Array::STORAGE_USER};
    573 	int					counts[]		= {1, 256};
    574 
    575 	for (int outputTypeNdx = 0; outputTypeNdx < DE_LENGTH_OF_ARRAY(outputTypes); outputTypeNdx++)
    576 	{
    577 		for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
    578 		{
    579 			for (int componentCount = 2; componentCount < 5; componentCount++)
    580 			{
    581 				for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
    582 				{
    583 					std::string name = "components" + typeToString(componentCount) + "_" + Array::outputTypeToString(outputTypes[outputTypeNdx]) + "_quads" + typeToString(counts[countNdx]);
    584 
    585 					const bool inputIsSignedInteger		= m_type == Array::INPUTTYPE_INT || m_type == Array::INPUTTYPE_SHORT || m_type == Array::INPUTTYPE_BYTE;
    586 					const bool inputIsUnignedInteger	= m_type == Array::INPUTTYPE_UNSIGNED_INT || m_type == Array::INPUTTYPE_UNSIGNED_SHORT || m_type == Array::INPUTTYPE_UNSIGNED_BYTE;
    587 					const bool outputIsSignedInteger	= outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC2 || outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC3 || outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC4;
    588 					const bool outputIsUnsignedInteger	= outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC2 || outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC3 || outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC4;
    589 
    590 					// If input type is float type and output type is int type skip
    591 					if ((m_type == Array::INPUTTYPE_FLOAT ||  m_type == Array::INPUTTYPE_HALF || m_type == Array::INPUTTYPE_FIXED) && (outputTypes[outputTypeNdx] >= Array::OUTPUTTYPE_INT))
    592 						continue;
    593 
    594 					if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && (outputTypes[outputTypeNdx] >= Array::OUTPUTTYPE_INT))
    595 						continue;
    596 
    597 					if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && componentCount != 4)
    598 						continue;
    599 
    600 					// Loading signed data as unsigned causes undefined values and vice versa
    601 					if (inputIsSignedInteger && outputIsUnsignedInteger)
    602 						continue;
    603 					if (inputIsUnignedInteger && outputIsSignedInteger)
    604 						continue;
    605 
    606 					MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
    607 																	outputTypes[outputTypeNdx],
    608 																	storages[storageNdx],
    609 																	Array::USAGE_DYNAMIC_DRAW,
    610 																	componentCount,
    611 																	0,
    612 																	0,
    613 																	false,
    614 																	GLValue::getMinValue(m_type),
    615 																	GLValue::getMaxValue(m_type));
    616 
    617 					MultiVertexArrayTest::Spec spec;
    618 					spec.primitive	= Array::PRIMITIVE_TRIANGLES;
    619 					spec.drawCount	= counts[countNdx];
    620 					spec.first		= 0;
    621 					spec.arrays.push_back(arraySpec);
    622 
    623 					addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
    624 				}
    625 			}
    626 		}
    627 	}
    628 }
    629 
    630 class SingleVertexArrayOutputTypeTests : public TestCaseGroup
    631 {
    632 public:
    633 										SingleVertexArrayOutputTypeTests	(Context& context);
    634 	virtual								~SingleVertexArrayOutputTypeTests	(void);
    635 
    636 	virtual void						init								(void);
    637 
    638 private:
    639 										SingleVertexArrayOutputTypeTests	(const SingleVertexArrayOutputTypeTests& other);
    640 	SingleVertexArrayOutputTypeTests&	operator=							(const SingleVertexArrayOutputTypeTests& other);
    641 };
    642 
    643 SingleVertexArrayOutputTypeTests::SingleVertexArrayOutputTypeTests (Context& context)
    644 	: TestCaseGroup(context, "output_types", "Single output type vertex atribute")
    645 {
    646 }
    647 
    648 SingleVertexArrayOutputTypeTests::~SingleVertexArrayOutputTypeTests (void)
    649 {
    650 }
    651 
    652 void SingleVertexArrayOutputTypeTests::init (void)
    653 {
    654 	// Test output types with different input types, component counts and storage, Usage?, Precision?, float?
    655 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_UNSIGNED_INT, Array::INPUTTYPE_INT, Array::INPUTTYPE_HALF, Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10, Array::INPUTTYPE_INT_2_10_10_10 };
    656 
    657 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
    658 	{
    659 		addChild(new SingleVertexArrayOutputTypeGroup(m_context, inputTypes[inputTypeNdx]));
    660 	}
    661 }
    662 
    663 
    664 class SingleVertexArrayTestGroup : public TestCaseGroup
    665 {
    666 public:
    667 									SingleVertexArrayTestGroup	(Context& context);
    668 	virtual							~SingleVertexArrayTestGroup	(void);
    669 
    670 	virtual void					init						(void);
    671 
    672 private:
    673 									SingleVertexArrayTestGroup	(const SingleVertexArrayTestGroup& other);
    674 	SingleVertexArrayTestGroup&		operator=					(const SingleVertexArrayTestGroup& other);
    675 };
    676 
    677 SingleVertexArrayTestGroup::SingleVertexArrayTestGroup (Context& context)
    678 	: TestCaseGroup(context, "single_attribute", "Single vertex atribute")
    679 {
    680 }
    681 
    682 SingleVertexArrayTestGroup::~SingleVertexArrayTestGroup (void)
    683 {
    684 }
    685 
    686 void SingleVertexArrayTestGroup::init (void)
    687 {
    688 	addChild(new SingleVertexArrayStrideTests(m_context));
    689 	addChild(new SingleVertexArrayNormalizeTests(m_context));
    690 	addChild(new SingleVertexArrayOutputTypeTests(m_context));
    691 	addChild(new SingleVertexArrayUsageTests(m_context));
    692 	addChild(new SingleVertexArrayOffsetTests(m_context));
    693 	addChild(new SingleVertexArrayFirstTests(m_context));
    694 }
    695 
    696 class MultiVertexArrayCountTests : public TestCaseGroup
    697 {
    698 public:
    699 									MultiVertexArrayCountTests	(Context& context);
    700 	virtual							~MultiVertexArrayCountTests	(void);
    701 
    702 	virtual void					init						(void);
    703 
    704 private:
    705 									MultiVertexArrayCountTests	(const MultiVertexArrayCountTests& other);
    706 	MultiVertexArrayCountTests&		operator=					(const MultiVertexArrayCountTests& other);
    707 
    708 	std::string						getTestName					(const MultiVertexArrayTest::Spec& spec);
    709 };
    710 
    711 MultiVertexArrayCountTests::MultiVertexArrayCountTests (Context& context)
    712 	: TestCaseGroup(context, "attribute_count", "Attribute counts")
    713 {
    714 }
    715 
    716 MultiVertexArrayCountTests::~MultiVertexArrayCountTests (void)
    717 {
    718 }
    719 
    720 std::string MultiVertexArrayCountTests::getTestName (const MultiVertexArrayTest::Spec& spec)
    721 {
    722 	std::stringstream name;
    723 	name
    724 		<< spec.arrays.size();
    725 
    726 	return name.str();
    727 }
    728 
    729 void MultiVertexArrayCountTests::init (void)
    730 {
    731 	// Test attribute counts
    732 	int arrayCounts[] = {2, 3, 4, 5, 6, 7, 8};
    733 
    734 	for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
    735 	{
    736 		MultiVertexArrayTest::Spec spec;
    737 
    738 		spec.primitive	= Array::PRIMITIVE_TRIANGLES;
    739 		spec.drawCount	= 256;
    740 		spec.first		= 0;
    741 
    742 		for (int arrayNdx = 0; arrayNdx < arrayCounts[arrayCountNdx]; arrayNdx++)
    743 		{
    744 			MultiVertexArrayTest::Spec::ArraySpec arraySpec(Array::INPUTTYPE_FLOAT,
    745 															Array::OUTPUTTYPE_VEC2,
    746 															Array::STORAGE_USER,
    747 															Array::USAGE_DYNAMIC_DRAW,
    748 															2,
    749 															0,
    750 															0,
    751 															false,
    752 															GLValue::getMinValue(Array::INPUTTYPE_FLOAT),
    753 															GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));
    754 
    755 			spec.arrays.push_back(arraySpec);
    756 		}
    757 
    758 		std::string name = getTestName(spec);
    759 		std::string desc = getTestName(spec);
    760 
    761 		addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
    762 	}
    763 }
    764 
    765 class MultiVertexArrayStorageTests : public TestCaseGroup
    766 {
    767 public:
    768 									MultiVertexArrayStorageTests	(Context& context);
    769 	virtual							~MultiVertexArrayStorageTests	(void);
    770 
    771 	virtual void					init							(void);
    772 
    773 private:
    774 									MultiVertexArrayStorageTests	(const MultiVertexArrayStorageTests& other);
    775 	MultiVertexArrayStorageTests&	operator=						(const MultiVertexArrayStorageTests& other);
    776 
    777 	void							addStorageCases 				(MultiVertexArrayTest::Spec spec, int depth);
    778 	std::string						getTestName						(const MultiVertexArrayTest::Spec& spec);
    779 };
    780 
    781 MultiVertexArrayStorageTests::MultiVertexArrayStorageTests (Context& context)
    782 	: TestCaseGroup(context, "storage", "Attribute storages")
    783 {
    784 }
    785 
    786 MultiVertexArrayStorageTests::~MultiVertexArrayStorageTests (void)
    787 {
    788 }
    789 
    790 std::string MultiVertexArrayStorageTests::getTestName (const MultiVertexArrayTest::Spec& spec)
    791 {
    792 	std::stringstream name;
    793 	name
    794 		<< spec.arrays.size();
    795 
    796 	for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
    797 	{
    798 		name
    799 			<< "_"
    800 			<< Array::storageToString(spec.arrays[arrayNdx].storage);
    801 	}
    802 
    803 	return name.str();
    804 }
    805 
    806 void MultiVertexArrayStorageTests::addStorageCases (MultiVertexArrayTest::Spec spec, int depth)
    807 {
    808 	if (depth == 0)
    809 	{
    810 		// Skip trivial case, used elsewhere
    811 		bool ok = false;
    812 		for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
    813 		{
    814 			if (spec.arrays[arrayNdx].storage != Array::STORAGE_USER)
    815 			{
    816 				ok = true;
    817 				break;
    818 			}
    819 		}
    820 
    821 		if (!ok)
    822 			return;
    823 
    824 		std::string name = getTestName(spec);
    825 		std::string desc = getTestName(spec);
    826 
    827 		addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
    828 		return;
    829 	}
    830 
    831 	Array::Storage storages[] = {Array::STORAGE_USER, Array::STORAGE_BUFFER};
    832 	for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
    833 	{
    834 		MultiVertexArrayTest::Spec::ArraySpec arraySpec(Array::INPUTTYPE_FLOAT,
    835 														Array::OUTPUTTYPE_VEC2,
    836 														storages[storageNdx],
    837 														Array::USAGE_DYNAMIC_DRAW,
    838 														2,
    839 														0,
    840 														0,
    841 														false,
    842 														GLValue::getMinValue(Array::INPUTTYPE_FLOAT),
    843 														GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));
    844 
    845 		MultiVertexArrayTest::Spec _spec = spec;
    846 		_spec.arrays.push_back(arraySpec);
    847 		addStorageCases(_spec, depth-1);
    848 	}
    849 }
    850 
    851 
    852 void MultiVertexArrayStorageTests::init (void)
    853 {
    854 	// Test different storages
    855 	int arrayCounts[] = {3};
    856 
    857 	MultiVertexArrayTest::Spec spec;
    858 
    859 	spec.primitive	= Array::PRIMITIVE_TRIANGLES;
    860 	spec.drawCount	= 256;
    861 	spec.first		= 0;
    862 
    863 	for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
    864 		addStorageCases(spec, arrayCounts[arrayCountNdx]);
    865 }
    866 
    867 class MultiVertexArrayStrideTests : public TestCaseGroup
    868 {
    869 public:
    870 									MultiVertexArrayStrideTests		(Context& context);
    871 	virtual							~MultiVertexArrayStrideTests	(void);
    872 
    873 	virtual void					init							(void);
    874 
    875 private:
    876 									MultiVertexArrayStrideTests		(const MultiVertexArrayStrideTests& other);
    877 	MultiVertexArrayStrideTests&	operator=						(const MultiVertexArrayStrideTests& other);
    878 
    879 	void							addStrideCases 					(MultiVertexArrayTest::Spec spec, int depth);
    880 	std::string						getTestName						(const MultiVertexArrayTest::Spec& spec);
    881 };
    882 
    883 MultiVertexArrayStrideTests::MultiVertexArrayStrideTests (Context& context)
    884 	: TestCaseGroup(context, "stride", "Strides")
    885 {
    886 }
    887 
    888 MultiVertexArrayStrideTests::~MultiVertexArrayStrideTests (void)
    889 {
    890 }
    891 
    892 std::string MultiVertexArrayStrideTests::getTestName (const MultiVertexArrayTest::Spec& spec)
    893 {
    894 	std::stringstream name;
    895 
    896 	name
    897 		<< spec.arrays.size();
    898 
    899 	for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
    900 	{
    901 		name
    902 			<< "_"
    903 			<< Array::inputTypeToString(spec.arrays[arrayNdx].inputType)
    904 			<< spec.arrays[arrayNdx].componentCount << "_"
    905 			<< spec.arrays[arrayNdx].stride;
    906 	}
    907 
    908 	return name.str();
    909 }
    910 
    911 void MultiVertexArrayStrideTests::init (void)
    912 {
    913 	// Test different strides, with multiple arrays, input types??
    914 	int arrayCounts[] = {3};
    915 
    916 	MultiVertexArrayTest::Spec spec;
    917 
    918 	spec.primitive	= Array::PRIMITIVE_TRIANGLES;
    919 	spec.drawCount	= 256;
    920 	spec.first		= 0;
    921 
    922 	for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
    923 		addStrideCases(spec, arrayCounts[arrayCountNdx]);
    924 }
    925 
    926 void MultiVertexArrayStrideTests::addStrideCases (MultiVertexArrayTest::Spec spec, int depth)
    927 {
    928 	if (depth == 0)
    929 	{
    930 		std::string name = getTestName(spec);
    931 		std::string desc = getTestName(spec);
    932 		addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
    933 		return;
    934 	}
    935 
    936 	int strides[]	= {0, -1, 17, 32};
    937 
    938 	for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
    939 	{
    940 		const int componentCount = 2;
    941 		MultiVertexArrayTest::Spec::ArraySpec arraySpec(Array::INPUTTYPE_FLOAT,
    942 														Array::OUTPUTTYPE_VEC2,
    943 														Array::STORAGE_USER,
    944 														Array::USAGE_DYNAMIC_DRAW,
    945 														componentCount,
    946 														0,
    947 														(strides[strideNdx] >= 0 ? strides[strideNdx] : componentCount * Array::inputTypeSize(Array::INPUTTYPE_FLOAT)),
    948 														false,
    949 														GLValue::getMinValue(Array::INPUTTYPE_FLOAT),
    950 														GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));
    951 
    952 		MultiVertexArrayTest::Spec _spec = spec;
    953 		_spec.arrays.push_back(arraySpec);
    954 		addStrideCases(_spec, depth-1);
    955 	}
    956 }
    957 
    958 class MultiVertexArrayOutputTests : public TestCaseGroup
    959 {
    960 public:
    961 										MultiVertexArrayOutputTests		(Context& context);
    962 	virtual								~MultiVertexArrayOutputTests	(void);
    963 
    964 	virtual void						init								(void);
    965 
    966 private:
    967 										MultiVertexArrayOutputTests		(const MultiVertexArrayOutputTests& other);
    968 	MultiVertexArrayOutputTests&	operator=							(const MultiVertexArrayOutputTests& other);
    969 
    970 	void								addInputTypeCases 					(MultiVertexArrayTest::Spec spec, int depth);
    971 	std::string							getTestName							(const MultiVertexArrayTest::Spec& spec);
    972 };
    973 
    974 MultiVertexArrayOutputTests::MultiVertexArrayOutputTests (Context& context)
    975 	: TestCaseGroup(context, "input_types", "input types")
    976 {
    977 }
    978 
    979 MultiVertexArrayOutputTests::~MultiVertexArrayOutputTests (void)
    980 {
    981 }
    982 
    983 std::string MultiVertexArrayOutputTests::getTestName (const MultiVertexArrayTest::Spec& spec)
    984 {
    985 	std::stringstream name;
    986 
    987 	name
    988 		<< spec.arrays.size();
    989 
    990 	for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
    991 	{
    992 		name
    993 			<< "_"
    994 			<< Array::inputTypeToString(spec.arrays[arrayNdx].inputType)
    995 			<< spec.arrays[arrayNdx].componentCount << "_"
    996 			<< Array::outputTypeToString(spec.arrays[arrayNdx].outputType);
    997 	}
    998 
    999 	return name.str();
   1000 }
   1001 
   1002 void MultiVertexArrayOutputTests::init (void)
   1003 {
   1004 	// Test different input types, with multiple arrays
   1005 	int arrayCounts[] = {3};
   1006 
   1007 	MultiVertexArrayTest::Spec spec;
   1008 
   1009 	spec.primitive	= Array::PRIMITIVE_TRIANGLES;
   1010 	spec.drawCount	= 256;
   1011 	spec.first		= 0;
   1012 
   1013 	for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
   1014 		addInputTypeCases(spec, arrayCounts[arrayCountNdx]);
   1015 }
   1016 
   1017 void MultiVertexArrayOutputTests::addInputTypeCases (MultiVertexArrayTest::Spec spec, int depth)
   1018 {
   1019 	if (depth == 0)
   1020 	{
   1021 		std::string name = getTestName(spec);
   1022 		std::string desc = getTestName(spec);
   1023 		addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
   1024 		return;
   1025 	}
   1026 
   1027 	Array::InputType inputTypes[] = {Array::INPUTTYPE_FIXED, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_UNSIGNED_SHORT};
   1028 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
   1029 	{
   1030 		MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
   1031 														Array::OUTPUTTYPE_VEC2,
   1032 														Array::STORAGE_USER,
   1033 														Array::USAGE_DYNAMIC_DRAW,
   1034 														2,
   1035 														0,
   1036 														0,
   1037 														false,
   1038 														GLValue::getMinValue(inputTypes[inputTypeNdx]),
   1039 														GLValue::getMaxValue(inputTypes[inputTypeNdx]));
   1040 
   1041 		MultiVertexArrayTest::Spec _spec = spec;
   1042 		_spec.arrays.push_back(arraySpec);
   1043 		addInputTypeCases(_spec, depth-1);
   1044 	}
   1045 }
   1046 
   1047 class MultiVertexArrayTestGroup : public TestCaseGroup
   1048 {
   1049 public:
   1050 									MultiVertexArrayTestGroup	(Context& context);
   1051 	virtual							~MultiVertexArrayTestGroup	(void);
   1052 
   1053 	virtual void					init						(void);
   1054 
   1055 private:
   1056 									MultiVertexArrayTestGroup	(const MultiVertexArrayTestGroup& other);
   1057 	MultiVertexArrayTestGroup&		operator=					(const MultiVertexArrayTestGroup& other);
   1058 };
   1059 
   1060 MultiVertexArrayTestGroup::MultiVertexArrayTestGroup (Context& context)
   1061 	: TestCaseGroup(context, "multiple_attributes", "Multiple vertex atributes")
   1062 {
   1063 }
   1064 
   1065 MultiVertexArrayTestGroup::~MultiVertexArrayTestGroup (void)
   1066 {
   1067 }
   1068 
   1069 void MultiVertexArrayTestGroup::init (void)
   1070 {
   1071 	addChild(new MultiVertexArrayCountTests(m_context));
   1072 	addChild(new MultiVertexArrayStorageTests(m_context));
   1073 	addChild(new MultiVertexArrayStrideTests(m_context));
   1074 	addChild(new MultiVertexArrayOutputTests(m_context));
   1075 }
   1076 
   1077 VertexArrayTestGroup::VertexArrayTestGroup (Context& context)
   1078 	: TestCaseGroup(context, "vertex_arrays", "Vertex array and array tests")
   1079 {
   1080 }
   1081 
   1082 VertexArrayTestGroup::~VertexArrayTestGroup (void)
   1083 {
   1084 }
   1085 
   1086 void VertexArrayTestGroup::init (void)
   1087 {
   1088 	addChild(new SingleVertexArrayTestGroup(m_context));
   1089 	addChild(new MultiVertexArrayTestGroup(m_context));
   1090 }
   1091 
   1092 } // Functional
   1093 } // gles3
   1094 } // deqp
   1095