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 Drawing tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es3fDrawTests.hpp"
     25 #include "glsDrawTest.hpp"
     26 #include "tcuRenderTarget.hpp"
     27 #include "sglrGLContext.hpp"
     28 #include "glwEnums.hpp"
     29 #include "deRandom.hpp"
     30 #include "deStringUtil.hpp"
     31 #include "deUniquePtr.hpp"
     32 #include "deSTLUtil.hpp"
     33 
     34 #include <set>
     35 
     36 namespace deqp
     37 {
     38 namespace gles3
     39 {
     40 namespace Functional
     41 {
     42 namespace
     43 {
     44 
     45 enum TestIterationType
     46 {
     47 	TYPE_DRAW_COUNT,		// !< test with 1, 5, and 25 primitives
     48 	TYPE_INSTANCE_COUNT,	// !< test with 1, 4, and 11 instances
     49 	TYPE_INDEX_RANGE,		// !< test with index range of [0, 23], [23, 40], and [5, 5]
     50 
     51 	TYPE_LAST
     52 };
     53 
     54 static void addTestIterations (gls::DrawTest* test, const gls::DrawTestSpec& baseSpec, TestIterationType type)
     55 {
     56 	gls::DrawTestSpec spec(baseSpec);
     57 
     58 	if (type == TYPE_DRAW_COUNT)
     59 	{
     60 		spec.primitiveCount = 1;
     61 		test->addIteration(spec, "draw count = 1");
     62 
     63 		spec.primitiveCount = 5;
     64 		test->addIteration(spec, "draw count = 5");
     65 
     66 		spec.primitiveCount = 25;
     67 		test->addIteration(spec, "draw count = 25");
     68 	}
     69 	else if (type == TYPE_INSTANCE_COUNT)
     70 	{
     71 		spec.instanceCount = 1;
     72 		test->addIteration(spec, "instance count = 1");
     73 
     74 		spec.instanceCount = 4;
     75 		test->addIteration(spec, "instance count = 4");
     76 
     77 		spec.instanceCount = 11;
     78 		test->addIteration(spec, "instance count = 11");
     79 	}
     80 	else if (type == TYPE_INDEX_RANGE)
     81 	{
     82 		spec.indexMin = 0;
     83 		spec.indexMax = 23;
     84 		test->addIteration(spec, "index range = [0, 23]");
     85 
     86 		spec.indexMin = 23;
     87 		spec.indexMax = 40;
     88 		test->addIteration(spec, "index range = [23, 40]");
     89 
     90 		// Only makes sense with points
     91 		if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_POINTS)
     92 		{
     93 			spec.indexMin = 5;
     94 			spec.indexMax = 5;
     95 			test->addIteration(spec, "index range = [5, 5]");
     96 		}
     97 	}
     98 	else
     99 		DE_ASSERT(false);
    100 }
    101 
    102 static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method)
    103 {
    104 	spec.apiType				= glu::ApiType::es(3,0);
    105 	spec.primitive				= gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
    106 	spec.primitiveCount			= 5;
    107 	spec.drawMethod				= method;
    108 	spec.indexType				= gls::DrawTestSpec::INDEXTYPE_LAST;
    109 	spec.indexPointerOffset		= 0;
    110 	spec.indexStorage			= gls::DrawTestSpec::STORAGE_LAST;
    111 	spec.first					= 0;
    112 	spec.indexMin				= 0;
    113 	spec.indexMax				= 0;
    114 	spec.instanceCount			= 1;
    115 
    116 	spec.attribs.resize(2);
    117 
    118 	spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    119 	spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    120 	spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
    121 	spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    122 	spec.attribs[0].componentCount			= 4;
    123 	spec.attribs[0].offset					= 0;
    124 	spec.attribs[0].stride					= 0;
    125 	spec.attribs[0].normalize				= false;
    126 	spec.attribs[0].instanceDivisor			= 0;
    127 	spec.attribs[0].useDefaultAttribute		= false;
    128 
    129 	spec.attribs[1].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    130 	spec.attribs[1].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    131 	spec.attribs[1].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
    132 	spec.attribs[1].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    133 	spec.attribs[1].componentCount			= 2;
    134 	spec.attribs[1].offset					= 0;
    135 	spec.attribs[1].stride					= 0;
    136 	spec.attribs[1].normalize				= false;
    137 	spec.attribs[1].instanceDivisor			= 0;
    138 	spec.attribs[1].useDefaultAttribute		= false;
    139 }
    140 
    141 class AttributeGroup : public TestCaseGroup
    142 {
    143 public:
    144 									AttributeGroup	(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod, gls::DrawTestSpec::Primitive primitive, gls::DrawTestSpec::IndexType indexType, gls::DrawTestSpec::Storage indexStorage);
    145 									~AttributeGroup	(void);
    146 
    147 	void							init			(void);
    148 
    149 private:
    150 	gls::DrawTestSpec::DrawMethod	m_method;
    151 	gls::DrawTestSpec::Primitive	m_primitive;
    152 	gls::DrawTestSpec::IndexType	m_indexType;
    153 	gls::DrawTestSpec::Storage		m_indexStorage;
    154 };
    155 
    156 AttributeGroup::AttributeGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod, gls::DrawTestSpec::Primitive primitive, gls::DrawTestSpec::IndexType indexType, gls::DrawTestSpec::Storage indexStorage)
    157 	: TestCaseGroup		(context, name, descr)
    158 	, m_method			(drawMethod)
    159 	, m_primitive		(primitive)
    160 	, m_indexType		(indexType)
    161 	, m_indexStorage	(indexStorage)
    162 {
    163 }
    164 
    165 AttributeGroup::~AttributeGroup (void)
    166 {
    167 }
    168 
    169 void AttributeGroup::init (void)
    170 {
    171 	// select test type
    172 	const bool				instanced			= (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED) ||
    173 												  (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED);
    174 	const bool				ranged				= (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
    175 	const TestIterationType	testType			= (instanced) ? (TYPE_INSTANCE_COUNT) : ((ranged) ? (TYPE_INDEX_RANGE) : (TYPE_DRAW_COUNT));
    176 
    177 	// Single attribute
    178 	{
    179 		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
    180 		gls::DrawTestSpec	spec;
    181 
    182 		spec.apiType							= glu::ApiType::es(3,0);
    183 		spec.primitive							= m_primitive;
    184 		spec.primitiveCount						= 5;
    185 		spec.drawMethod							= m_method;
    186 		spec.indexType							= m_indexType;
    187 		spec.indexPointerOffset					= 0;
    188 		spec.indexStorage						= m_indexStorage;
    189 		spec.first								= 0;
    190 		spec.indexMin							= 0;
    191 		spec.indexMax							= 0;
    192 		spec.instanceCount						= 1;
    193 
    194 		spec.attribs.resize(1);
    195 
    196 		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    197 		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    198 		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
    199 		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    200 		spec.attribs[0].componentCount			= 2;
    201 		spec.attribs[0].offset					= 0;
    202 		spec.attribs[0].stride					= 0;
    203 		spec.attribs[0].normalize				= false;
    204 		spec.attribs[0].instanceDivisor			= 0;
    205 		spec.attribs[0].useDefaultAttribute		= false;
    206 
    207 		addTestIterations(test, spec, testType);
    208 
    209 		this->addChild(test);
    210 	}
    211 
    212 	// Multiple attribute
    213 	{
    214 		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays.");
    215 		gls::DrawTestSpec	spec;
    216 
    217 		spec.apiType							= glu::ApiType::es(3,0);
    218 		spec.primitive							= m_primitive;
    219 		spec.primitiveCount						= 5;
    220 		spec.drawMethod							= m_method;
    221 		spec.indexType							= m_indexType;
    222 		spec.indexPointerOffset					= 0;
    223 		spec.indexStorage						= m_indexStorage;
    224 		spec.first								= 0;
    225 		spec.indexMin							= 0;
    226 		spec.indexMax							= 0;
    227 		spec.instanceCount						= 1;
    228 
    229 		spec.attribs.resize(2);
    230 
    231 		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    232 		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    233 		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
    234 		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    235 		spec.attribs[0].componentCount			= 4;
    236 		spec.attribs[0].offset					= 0;
    237 		spec.attribs[0].stride					= 0;
    238 		spec.attribs[0].normalize				= false;
    239 		spec.attribs[0].instanceDivisor			= 0;
    240 		spec.attribs[0].useDefaultAttribute		= false;
    241 
    242 		spec.attribs[1].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    243 		spec.attribs[1].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    244 		spec.attribs[1].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
    245 		spec.attribs[1].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    246 		spec.attribs[1].componentCount			= 2;
    247 		spec.attribs[1].offset					= 0;
    248 		spec.attribs[1].stride					= 0;
    249 		spec.attribs[1].normalize				= false;
    250 		spec.attribs[1].instanceDivisor			= 0;
    251 		spec.attribs[1].useDefaultAttribute		= false;
    252 
    253 		addTestIterations(test, spec, testType);
    254 
    255 		this->addChild(test);
    256 	}
    257 
    258 	// Multiple attribute, second one divided
    259 	{
    260 		gls::DrawTest*		test					= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "instanced_attributes", "Instanced attribute array.");
    261 		gls::DrawTestSpec	spec;
    262 
    263 		spec.apiType								= glu::ApiType::es(3,0);
    264 		spec.primitive								= m_primitive;
    265 		spec.primitiveCount							= 5;
    266 		spec.drawMethod								= m_method;
    267 		spec.indexType								= m_indexType;
    268 		spec.indexPointerOffset						= 0;
    269 		spec.indexStorage							= m_indexStorage;
    270 		spec.first									= 0;
    271 		spec.indexMin								= 0;
    272 		spec.indexMax								= 0;
    273 		spec.instanceCount							= 1;
    274 
    275 		spec.attribs.resize(3);
    276 
    277 		spec.attribs[0].inputType					= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    278 		spec.attribs[0].outputType					= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    279 		spec.attribs[0].storage						= gls::DrawTestSpec::STORAGE_BUFFER;
    280 		spec.attribs[0].usage						= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    281 		spec.attribs[0].componentCount				= 4;
    282 		spec.attribs[0].offset						= 0;
    283 		spec.attribs[0].stride						= 0;
    284 		spec.attribs[0].normalize					= false;
    285 		spec.attribs[0].instanceDivisor				= 0;
    286 		spec.attribs[0].useDefaultAttribute			= false;
    287 
    288 		// Add another position component so the instances wont be drawn on each other
    289 		spec.attribs[1].inputType					= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    290 		spec.attribs[1].outputType					= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    291 		spec.attribs[1].storage						= gls::DrawTestSpec::STORAGE_BUFFER;
    292 		spec.attribs[1].usage						= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    293 		spec.attribs[1].componentCount				= 2;
    294 		spec.attribs[1].offset						= 0;
    295 		spec.attribs[1].stride						= 0;
    296 		spec.attribs[1].normalize					= false;
    297 		spec.attribs[1].instanceDivisor				= 1;
    298 		spec.attribs[1].useDefaultAttribute			= false;
    299 		spec.attribs[1].additionalPositionAttribute	= true;
    300 
    301 		// Instanced color
    302 		spec.attribs[2].inputType					= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    303 		spec.attribs[2].outputType					= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    304 		spec.attribs[2].storage						= gls::DrawTestSpec::STORAGE_BUFFER;
    305 		spec.attribs[2].usage						= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    306 		spec.attribs[2].componentCount				= 3;
    307 		spec.attribs[2].offset						= 0;
    308 		spec.attribs[2].stride						= 0;
    309 		spec.attribs[2].normalize					= false;
    310 		spec.attribs[2].instanceDivisor				= 1;
    311 		spec.attribs[2].useDefaultAttribute			= false;
    312 
    313 		addTestIterations(test, spec, testType);
    314 
    315 		this->addChild(test);
    316 	}
    317 
    318 	// Multiple attribute, second one default
    319 	{
    320 		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*.");
    321 		gls::DrawTestSpec	spec;
    322 
    323 		spec.apiType							= glu::ApiType::es(3,0);
    324 		spec.primitive							= m_primitive;
    325 		spec.primitiveCount						= 5;
    326 		spec.drawMethod							= m_method;
    327 		spec.indexType							= m_indexType;
    328 		spec.indexPointerOffset					= 0;
    329 		spec.indexStorage						= m_indexStorage;
    330 		spec.first								= 0;
    331 		spec.indexMin							= 0;
    332 		spec.indexMax							= 20; // \note addTestIterations is not called for the spec, so we must ensure [indexMin, indexMax] is a good range
    333 		spec.instanceCount						= 1;
    334 
    335 		spec.attribs.resize(2);
    336 
    337 		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    338 		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    339 		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
    340 		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    341 		spec.attribs[0].componentCount			= 2;
    342 		spec.attribs[0].offset					= 0;
    343 		spec.attribs[0].stride					= 0;
    344 		spec.attribs[0].normalize				= false;
    345 		spec.attribs[0].instanceDivisor			= 0;
    346 		spec.attribs[0].useDefaultAttribute		= false;
    347 
    348 		struct IOPair
    349 		{
    350 			gls::DrawTestSpec::InputType  input;
    351 			gls::DrawTestSpec::OutputType output;
    352 			int							  componentCount;
    353 		} iopairs[] =
    354 		{
    355 			{ gls::DrawTestSpec::INPUTTYPE_FLOAT,        gls::DrawTestSpec::OUTPUTTYPE_VEC2,  4 },
    356 			{ gls::DrawTestSpec::INPUTTYPE_FLOAT,        gls::DrawTestSpec::OUTPUTTYPE_VEC4,  2 },
    357 			{ gls::DrawTestSpec::INPUTTYPE_INT,          gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 4 },
    358 			{ gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 4 },
    359 		};
    360 
    361 		for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
    362 		{
    363 			const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
    364 
    365 			spec.attribs[1].inputType			= iopairs[ioNdx].input;
    366 			spec.attribs[1].outputType			= iopairs[ioNdx].output;
    367 			spec.attribs[1].storage				= gls::DrawTestSpec::STORAGE_BUFFER;
    368 			spec.attribs[1].usage				= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    369 			spec.attribs[1].componentCount		= iopairs[ioNdx].componentCount;
    370 			spec.attribs[1].offset				= 0;
    371 			spec.attribs[1].stride				= 0;
    372 			spec.attribs[1].normalize			= false;
    373 			spec.attribs[1].instanceDivisor		= 0;
    374 			spec.attribs[1].useDefaultAttribute	= true;
    375 
    376 			test->addIteration(spec, desc.c_str());
    377 		}
    378 
    379 		this->addChild(test);
    380 	}
    381 }
    382 
    383 class IndexGroup : public TestCaseGroup
    384 {
    385 public:
    386 									IndexGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
    387 									~IndexGroup		(void);
    388 
    389 	void							init			(void);
    390 
    391 private:
    392 	gls::DrawTestSpec::DrawMethod	m_method;
    393 };
    394 
    395 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
    396 	: TestCaseGroup		(context, name, descr)
    397 	, m_method			(drawMethod)
    398 {
    399 }
    400 
    401 IndexGroup::~IndexGroup (void)
    402 {
    403 }
    404 
    405 void IndexGroup::init (void)
    406 {
    407 	struct IndexTest
    408 	{
    409 		gls::DrawTestSpec::Storage		storage;
    410 		gls::DrawTestSpec::IndexType	type;
    411 		bool							aligned;
    412 		int								offsets[3];
    413 	};
    414 
    415 	const IndexTest tests[] =
    416 	{
    417 		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_BYTE,	true,	{ 0, 1, -1 } },
    418 		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_SHORT,	true,	{ 0, 2, -1 } },
    419 		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_INT,	true,	{ 0, 4, -1 } },
    420 
    421 		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_SHORT,	false,	{ 1, 3, -1 } },
    422 		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_INT,	false,	{ 2, 3, -1 } },
    423 
    424 		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_BYTE,	true,	{ 0, 1, -1 } },
    425 		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_SHORT,	true,	{ 0, 2, -1 } },
    426 		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_INT,	true,	{ 0, 4, -1 } },
    427 	};
    428 
    429 	gls::DrawTestSpec spec;
    430 
    431 	tcu::TestCaseGroup* userPtrGroup			= new tcu::TestCaseGroup(m_testCtx, "user_ptr", "user pointer");
    432 	tcu::TestCaseGroup* unalignedUserPtrGroup	= new tcu::TestCaseGroup(m_testCtx, "unaligned_user_ptr", "unaligned user pointer");
    433 	tcu::TestCaseGroup* bufferGroup				= new tcu::TestCaseGroup(m_testCtx, "buffer", "buffer");
    434 
    435 	genBasicSpec(spec, m_method);
    436 
    437 	this->addChild(userPtrGroup);
    438 	this->addChild(unalignedUserPtrGroup);
    439 	this->addChild(bufferGroup);
    440 
    441 	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
    442 	{
    443 		const IndexTest&				indexTest	= tests[testNdx];
    444 		tcu::TestCaseGroup*				group		= (indexTest.storage == gls::DrawTestSpec::STORAGE_USER)
    445 													? ((indexTest.aligned) ? (userPtrGroup) : (unalignedUserPtrGroup))
    446 													: ((indexTest.aligned) ? (bufferGroup) : (DE_NULL));
    447 
    448 		const std::string				name		= std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
    449 		const std::string				desc		= std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage);
    450 		de::MovePtr<gls::DrawTest>		test		(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()));
    451 
    452 		spec.indexType			= indexTest.type;
    453 		spec.indexStorage		= indexTest.storage;
    454 
    455 		for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
    456 		{
    457 			const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]);
    458 			spec.indexPointerOffset	= indexTest.offsets[iterationNdx];
    459 			test->addIteration(spec, iterationDesc.c_str());
    460 		}
    461 
    462 		DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET);
    463 		DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE);
    464 		group->addChild(test.release());
    465 	}
    466 }
    467 
    468 
    469 class FirstGroup : public TestCaseGroup
    470 {
    471 public:
    472 									FirstGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
    473 									~FirstGroup		(void);
    474 
    475 	void							init			(void);
    476 
    477 private:
    478 	gls::DrawTestSpec::DrawMethod	m_method;
    479 };
    480 
    481 FirstGroup::FirstGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
    482 	: TestCaseGroup		(context, name, descr)
    483 	, m_method			(drawMethod)
    484 {
    485 }
    486 
    487 FirstGroup::~FirstGroup (void)
    488 {
    489 }
    490 
    491 void FirstGroup::init (void)
    492 {
    493 	const int firsts[] =
    494 	{
    495 		1, 3, 17
    496 	};
    497 
    498 	gls::DrawTestSpec spec;
    499 	genBasicSpec(spec, m_method);
    500 
    501 	for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); ++firstNdx)
    502 	{
    503 		const std::string	name = std::string("first_") + de::toString(firsts[firstNdx]);
    504 		const std::string	desc = std::string("first ") + de::toString(firsts[firstNdx]);
    505 		gls::DrawTest*		test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
    506 
    507 		spec.first = firsts[firstNdx];
    508 
    509 		addTestIterations(test, spec, TYPE_DRAW_COUNT);
    510 
    511 		this->addChild(test);
    512 	}
    513 }
    514 
    515 class MethodGroup : public TestCaseGroup
    516 {
    517 public:
    518 									MethodGroup			(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
    519 									~MethodGroup		(void);
    520 
    521 	void							init				(void);
    522 
    523 private:
    524 	gls::DrawTestSpec::DrawMethod	m_method;
    525 };
    526 
    527 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
    528 	: TestCaseGroup		(context, name, descr)
    529 	, m_method			(drawMethod)
    530 {
    531 }
    532 
    533 MethodGroup::~MethodGroup (void)
    534 {
    535 }
    536 
    537 void MethodGroup::init (void)
    538 {
    539 	const bool indexed		= (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
    540 	const bool hasFirst		= (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED);
    541 
    542 	const gls::DrawTestSpec::Primitive primitive[] =
    543 	{
    544 		gls::DrawTestSpec::PRIMITIVE_POINTS,
    545 		gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
    546 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
    547 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
    548 		gls::DrawTestSpec::PRIMITIVE_LINES,
    549 		gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
    550 		gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
    551 	};
    552 
    553 	if (hasFirst)
    554 	{
    555 		// First-tests
    556 		this->addChild(new FirstGroup(m_context, "first", "First tests", m_method));
    557 	}
    558 
    559 	if (indexed)
    560 	{
    561 		// Index-tests
    562 		if (m_method != gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED)
    563 			this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
    564 	}
    565 
    566 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
    567 	{
    568 		const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
    569 		const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
    570 
    571 		this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
    572 	}
    573 }
    574 
    575 class GridProgram : public sglr::ShaderProgram
    576 {
    577 public:
    578 			GridProgram		(void);
    579 
    580 	void	shadeVertices	(const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
    581 	void	shadeFragments	(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
    582 };
    583 
    584 GridProgram::GridProgram (void)
    585 	: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
    586 							<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
    587 							<< sglr::pdec::VertexAttribute("a_offset", rr::GENERICVECTYPE_FLOAT)
    588 							<< sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT)
    589 							<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
    590 							<< sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
    591 							<< sglr::pdec::VertexSource("#version 300 es\n"
    592 														"in highp vec4 a_position;\n"
    593 														"in highp vec4 a_offset;\n"
    594 														"in highp vec4 a_color;\n"
    595 														"out mediump vec4 v_color;\n"
    596 														"void main(void)\n"
    597 														"{\n"
    598 														"	gl_Position = a_position + a_offset;\n"
    599 														"	v_color = a_color;\n"
    600 														"}\n")
    601 							<< sglr::pdec::FragmentSource(
    602 														"#version 300 es\n"
    603 														"layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
    604 														"in mediump vec4 v_color;\n"
    605 														"void main(void)\n"
    606 														"{\n"
    607 														"	dEQP_FragColor = v_color;\n"
    608 														"}\n"))
    609 {
    610 }
    611 
    612 void GridProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
    613 {
    614 	for (int ndx = 0; ndx < numPackets; ++ndx)
    615 	{
    616 		packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx) + rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
    617 		packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[2], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
    618 	}
    619 }
    620 
    621 void GridProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
    622 {
    623 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
    624 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
    625 		rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx));
    626 }
    627 
    628 class InstancedGridRenderTest : public TestCase
    629 {
    630 public:
    631 					InstancedGridRenderTest		(Context& context, const char* name, const char* desc, int gridSide, bool useIndices);
    632 					~InstancedGridRenderTest	(void);
    633 
    634 	IterateResult	iterate						(void);
    635 
    636 private:
    637 	void			renderTo					(sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dst);
    638 	bool			verifyImage					(const tcu::Surface& image);
    639 
    640 	const int		m_gridSide;
    641 	const bool		m_useIndices;
    642 };
    643 
    644 InstancedGridRenderTest::InstancedGridRenderTest (Context& context, const char* name, const char* desc, int gridSide, bool useIndices)
    645 	: TestCase		(context, name, desc)
    646 	, m_gridSide	(gridSide)
    647 	, m_useIndices	(useIndices)
    648 {
    649 }
    650 
    651 InstancedGridRenderTest::~InstancedGridRenderTest (void)
    652 {
    653 }
    654 
    655 InstancedGridRenderTest::IterateResult InstancedGridRenderTest::iterate (void)
    656 {
    657 	const int renderTargetWidth  = de::min(1024, m_context.getRenderTarget().getWidth());
    658 	const int renderTargetHeight = de::min(1024, m_context.getRenderTarget().getHeight());
    659 
    660 	sglr::GLContext ctx		(m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(0, 0, renderTargetWidth, renderTargetHeight));
    661 	tcu::Surface	surface	(renderTargetWidth, renderTargetHeight);
    662 	GridProgram		program;
    663 
    664 	// render
    665 
    666 	renderTo(ctx, program, surface);
    667 
    668 	// verify image
    669 
    670 	if (verifyImage(surface))
    671 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    672 	else
    673 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rendering result");
    674 	return STOP;
    675 }
    676 
    677 void InstancedGridRenderTest::renderTo (sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dst)
    678 {
    679 	const tcu::Vec4 green	(0, 1, 0, 1);
    680 	const tcu::Vec4 yellow	(1, 1, 0, 1);
    681 
    682 	deUint32 positionBuf	= 0;
    683 	deUint32 offsetBuf		= 0;
    684 	deUint32 colorBuf		= 0;
    685 	deUint32 indexBuf		= 0;
    686 	deUint32 programID		= ctx.createProgram(&program);
    687 	deInt32 posLocation		= ctx.getAttribLocation(programID, "a_position");
    688 	deInt32 offsetLocation	= ctx.getAttribLocation(programID, "a_offset");
    689 	deInt32 colorLocation	= ctx.getAttribLocation(programID, "a_color");
    690 
    691 	float cellW	= 2.0f / (float)m_gridSide;
    692 	float cellH	= 2.0f / (float)m_gridSide;
    693 	const tcu::Vec4 vertexPositions[] =
    694 	{
    695 		tcu::Vec4(0,		0,		0, 1),
    696 		tcu::Vec4(cellW,	0,		0, 1),
    697 		tcu::Vec4(0,		cellH,	0, 1),
    698 
    699 		tcu::Vec4(0,		cellH,	0, 1),
    700 		tcu::Vec4(cellW,	0,		0, 1),
    701 		tcu::Vec4(cellW,	cellH,	0, 1),
    702 	};
    703 
    704 	const deUint16 indices[] =
    705 	{
    706 		0, 4, 3,
    707 		2, 1, 5
    708 	};
    709 
    710 	std::vector<tcu::Vec4> offsets;
    711 	for (int x = 0; x < m_gridSide; ++x)
    712 	for (int y = 0; y < m_gridSide; ++y)
    713 		offsets.push_back(tcu::Vec4((float)x * cellW - 1.0f, (float)y * cellW - 1.0f, 0, 0));
    714 
    715 	std::vector<tcu::Vec4> colors;
    716 	for (int x = 0; x < m_gridSide; ++x)
    717 	for (int y = 0; y < m_gridSide; ++y)
    718 		colors.push_back(((x + y) % 2 == 0) ? (green) : (yellow));
    719 
    720 	ctx.genBuffers(1, &positionBuf);
    721 	ctx.bindBuffer(GL_ARRAY_BUFFER, positionBuf);
    722 	ctx.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
    723 	ctx.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
    724 	ctx.vertexAttribDivisor(posLocation, 0);
    725 	ctx.enableVertexAttribArray(posLocation);
    726 
    727 	ctx.genBuffers(1, &offsetBuf);
    728 	ctx.bindBuffer(GL_ARRAY_BUFFER, offsetBuf);
    729 	ctx.bufferData(GL_ARRAY_BUFFER, offsets.size() * sizeof(tcu::Vec4), &offsets[0], GL_STATIC_DRAW);
    730 	ctx.vertexAttribPointer(offsetLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
    731 	ctx.vertexAttribDivisor(offsetLocation, 1);
    732 	ctx.enableVertexAttribArray(offsetLocation);
    733 
    734 	ctx.genBuffers(1, &colorBuf);
    735 	ctx.bindBuffer(GL_ARRAY_BUFFER, colorBuf);
    736 	ctx.bufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(tcu::Vec4), &colors[0], GL_STATIC_DRAW);
    737 	ctx.vertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
    738 	ctx.vertexAttribDivisor(colorLocation, 1);
    739 	ctx.enableVertexAttribArray(colorLocation);
    740 
    741 	if (m_useIndices)
    742 	{
    743 		ctx.genBuffers(1, &indexBuf);
    744 		ctx.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
    745 		ctx.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    746 	}
    747 
    748 	ctx.clearColor(0, 0, 0, 1);
    749 	ctx.clear(GL_COLOR_BUFFER_BIT);
    750 
    751 	ctx.viewport(0, 0, dst.getWidth(), dst.getHeight());
    752 
    753 	ctx.useProgram(programID);
    754 	if (m_useIndices)
    755 		ctx.drawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL, m_gridSide * m_gridSide);
    756 	else
    757 		ctx.drawArraysInstanced(GL_TRIANGLES, 0, 6, m_gridSide * m_gridSide);
    758 	ctx.useProgram(0);
    759 
    760 	if (m_useIndices)
    761 		ctx.deleteBuffers(1, &indexBuf);
    762 	ctx.deleteBuffers(1, &colorBuf);
    763 	ctx.deleteBuffers(1, &offsetBuf);
    764 	ctx.deleteBuffers(1, &positionBuf);
    765 	ctx.deleteProgram(programID);
    766 
    767 	ctx.finish();
    768 	ctx.readPixels(dst, 0, 0, dst.getWidth(), dst.getHeight());
    769 
    770 	glu::checkError(ctx.getError(), "", __FILE__, __LINE__);
    771 }
    772 
    773 bool InstancedGridRenderTest::verifyImage (const tcu::Surface& image)
    774 {
    775 	// \note the green/yellow pattern is only for clarity. The test will only verify that all instances were drawn by looking for anything non-green/yellow.
    776 	using tcu::TestLog;
    777 
    778 	const int colorThreshold	= 20;
    779 
    780 	tcu::Surface error			(image.getWidth(), image.getHeight());
    781 	bool isOk					= true;
    782 
    783 	for (int y = 0; y < image.getHeight(); y++)
    784 	for (int x = 0; x < image.getWidth(); x++)
    785 	{
    786 		if (x == 0 || y == 0 || y + 1 == image.getHeight() || x + 1 == image.getWidth())
    787 		{
    788 			// Background color might bleed in at the borders with msaa
    789 			error.setPixel(x, y, tcu::RGBA(0, 255, 0, 255));
    790 		}
    791 		else
    792 		{
    793 			const tcu::RGBA pixel = image.getPixel(x, y);
    794 			bool pixelOk = true;
    795 
    796 			// Any pixel with !(G ~= 255) is faulty (not a linear combinations of green and yellow)
    797 			if (de::abs(pixel.getGreen() - 255) > colorThreshold)
    798 				pixelOk = false;
    799 
    800 			// Any pixel with !(B ~= 0) is faulty (not a linear combinations of green and yellow)
    801 			if (de::abs(pixel.getBlue() - 0) > colorThreshold)
    802 				pixelOk = false;
    803 
    804 			error.setPixel(x, y, (pixelOk) ? (tcu::RGBA(0, 255, 0, 255)) : (tcu::RGBA(255, 0, 0, 255)));
    805 			isOk = isOk && pixelOk;
    806 		}
    807 	}
    808 
    809 	if (!isOk)
    810 	{
    811 		tcu::TestLog& log = m_testCtx.getLog();
    812 
    813 		log << TestLog::Message << "Image verification failed." << TestLog::EndMessage;
    814 		log << TestLog::ImageSet("Verfication result", "Result of rendering")
    815 			<< TestLog::Image("Result",		"Result",		image)
    816 			<< TestLog::Image("ErrorMask",	"Error mask",	error)
    817 			<< TestLog::EndImageSet;
    818 	}
    819 	else
    820 	{
    821 		tcu::TestLog& log = m_testCtx.getLog();
    822 
    823 		log << TestLog::ImageSet("Verfication result", "Result of rendering")
    824 			<< TestLog::Image("Result", "Result", image)
    825 			<< TestLog::EndImageSet;
    826 	}
    827 
    828 	return isOk;
    829 }
    830 
    831 class InstancingGroup : public TestCaseGroup
    832 {
    833 public:
    834 									InstancingGroup		(Context& context, const char* name, const char* descr);
    835 									~InstancingGroup	(void);
    836 
    837 	void							init				(void);
    838 };
    839 
    840 InstancingGroup::InstancingGroup (Context& context, const char* name, const char* descr)
    841 	: TestCaseGroup	(context, name, descr)
    842 {
    843 }
    844 
    845 InstancingGroup::~InstancingGroup (void)
    846 {
    847 }
    848 
    849 void InstancingGroup::init (void)
    850 {
    851 	const int gridWidths[] =
    852 	{
    853 		2,
    854 		5,
    855 		10,
    856 		32,
    857 		100,
    858 	};
    859 
    860 	// drawArrays
    861 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(gridWidths); ++ndx)
    862 	{
    863 		const std::string name = std::string("draw_arrays_instanced_grid_") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
    864 		const std::string desc = std::string("DrawArraysInstanced, Grid size ") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
    865 
    866 		this->addChild(new InstancedGridRenderTest(m_context, name.c_str(), desc.c_str(), gridWidths[ndx], false));
    867 	}
    868 
    869 	// drawElements
    870 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(gridWidths); ++ndx)
    871 	{
    872 		const std::string name = std::string("draw_elements_instanced_grid_") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
    873 		const std::string desc = std::string("DrawElementsInstanced, Grid size ") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
    874 
    875 		this->addChild(new InstancedGridRenderTest(m_context, name.c_str(), desc.c_str(), gridWidths[ndx], true));
    876 	}
    877 }
    878 
    879 class RandomGroup : public TestCaseGroup
    880 {
    881 public:
    882 									RandomGroup		(Context& context, const char* name, const char* descr);
    883 									~RandomGroup	(void);
    884 
    885 	void							init			(void);
    886 };
    887 
    888 template <int SIZE>
    889 struct UniformWeightArray
    890 {
    891 	float weights[SIZE];
    892 
    893 	UniformWeightArray (void)
    894 	{
    895 		for (int i=0; i<SIZE; ++i)
    896 			weights[i] = 1.0f;
    897 	}
    898 };
    899 
    900 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
    901 	: TestCaseGroup	(context, name, descr)
    902 {
    903 }
    904 
    905 RandomGroup::~RandomGroup (void)
    906 {
    907 }
    908 
    909 void RandomGroup::init (void)
    910 {
    911 	const int			numAttempts				= 300;
    912 
    913 	static const int	attribCounts[]			= { 1, 2, 5 };
    914 	static const float	attribWeights[]			= { 30, 10, 1 };
    915 	static const int	primitiveCounts[]		= { 1, 5, 64 };
    916 	static const float	primitiveCountWeights[]	= { 20, 10, 1 };
    917 	static const int	indexOffsets[]			= { 0, 7, 13 };
    918 	static const float	indexOffsetWeights[]	= { 20, 20, 1 };
    919 	static const int	firsts[]				= { 0, 7, 13 };
    920 	static const float	firstWeights[]			= { 20, 20, 1 };
    921 	static const int	instanceCounts[]		= { 1, 2, 16, 17 };
    922 	static const float	instanceWeights[]		= { 20, 10, 5, 1 };
    923 	static const int	indexMins[]				= { 0, 1, 3, 8 };
    924 	static const int	indexMaxs[]				= { 4, 8, 128, 257 };
    925 	static const float	indexWeights[]			= { 50, 50, 50, 50 };
    926 	static const int	offsets[]				= { 0, 1, 5, 12 };
    927 	static const float	offsetWeights[]			= { 50, 10, 10, 10 };
    928 	static const int	strides[]				= { 0, 7, 16, 17 };
    929 	static const float	strideWeights[]			= { 50, 10, 10, 10 };
    930 	static const int	instanceDivisors[]		= { 0, 1, 3, 129 };
    931 	static const float	instanceDivisorWeights[]= { 70, 30, 10, 10 };
    932 
    933 	static const gls::DrawTestSpec::Primitive primitives[] =
    934 	{
    935 		gls::DrawTestSpec::PRIMITIVE_POINTS,
    936 		gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
    937 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
    938 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
    939 		gls::DrawTestSpec::PRIMITIVE_LINES,
    940 		gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
    941 		gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
    942 	};
    943 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
    944 
    945 	static const gls::DrawTestSpec::DrawMethod drawMethods[] =
    946 	{
    947 		gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
    948 		gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED,
    949 		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
    950 		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED,
    951 		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED
    952 	};
    953 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
    954 
    955 	static const gls::DrawTestSpec::IndexType indexTypes[] =
    956 	{
    957 		gls::DrawTestSpec::INDEXTYPE_BYTE,
    958 		gls::DrawTestSpec::INDEXTYPE_SHORT,
    959 		gls::DrawTestSpec::INDEXTYPE_INT,
    960 	};
    961 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
    962 
    963 	static const gls::DrawTestSpec::Storage storages[] =
    964 	{
    965 		gls::DrawTestSpec::STORAGE_USER,
    966 		gls::DrawTestSpec::STORAGE_BUFFER,
    967 	};
    968 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights;
    969 
    970 	static const gls::DrawTestSpec::InputType inputTypes[] =
    971 	{
    972 		gls::DrawTestSpec::INPUTTYPE_FLOAT,
    973 		gls::DrawTestSpec::INPUTTYPE_FIXED,
    974 		gls::DrawTestSpec::INPUTTYPE_BYTE,
    975 		gls::DrawTestSpec::INPUTTYPE_SHORT,
    976 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
    977 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT,
    978 		gls::DrawTestSpec::INPUTTYPE_INT,
    979 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT,
    980 		gls::DrawTestSpec::INPUTTYPE_HALF,
    981 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10,
    982 		gls::DrawTestSpec::INPUTTYPE_INT_2_10_10_10,
    983 	};
    984 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
    985 
    986 	static const gls::DrawTestSpec::OutputType outputTypes[] =
    987 	{
    988 		gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
    989 		gls::DrawTestSpec::OUTPUTTYPE_VEC2,
    990 		gls::DrawTestSpec::OUTPUTTYPE_VEC3,
    991 		gls::DrawTestSpec::OUTPUTTYPE_VEC4,
    992 		gls::DrawTestSpec::OUTPUTTYPE_INT,
    993 		gls::DrawTestSpec::OUTPUTTYPE_UINT,
    994 		gls::DrawTestSpec::OUTPUTTYPE_IVEC2,
    995 		gls::DrawTestSpec::OUTPUTTYPE_IVEC3,
    996 		gls::DrawTestSpec::OUTPUTTYPE_IVEC4,
    997 		gls::DrawTestSpec::OUTPUTTYPE_UVEC2,
    998 		gls::DrawTestSpec::OUTPUTTYPE_UVEC3,
    999 		gls::DrawTestSpec::OUTPUTTYPE_UVEC4,
   1000 	};
   1001 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
   1002 
   1003 	static const gls::DrawTestSpec::Usage usages[] =
   1004 	{
   1005 		gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
   1006 		gls::DrawTestSpec::USAGE_STATIC_DRAW,
   1007 		gls::DrawTestSpec::USAGE_STREAM_DRAW,
   1008 		gls::DrawTestSpec::USAGE_STREAM_READ,
   1009 		gls::DrawTestSpec::USAGE_STREAM_COPY,
   1010 		gls::DrawTestSpec::USAGE_STATIC_READ,
   1011 		gls::DrawTestSpec::USAGE_STATIC_COPY,
   1012 		gls::DrawTestSpec::USAGE_DYNAMIC_READ,
   1013 		gls::DrawTestSpec::USAGE_DYNAMIC_COPY,
   1014 	};
   1015 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
   1016 
   1017 	static const deUint32 blacklistedCases[]=
   1018 	{
   1019 		544,	//!< extremely narrow triangle
   1020 	};
   1021 
   1022 	std::set<deUint32>	insertedHashes;
   1023 	size_t				insertedCount = 0;
   1024 
   1025 	for (int ndx = 0; ndx < numAttempts; ++ndx)
   1026 	{
   1027 		de::Random random(0xc551393 + ndx); // random does not depend on previous cases
   1028 
   1029 		int					attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
   1030 		gls::DrawTestSpec	spec;
   1031 
   1032 		spec.apiType				= glu::ApiType::es(3,0);
   1033 		spec.primitive				= random.chooseWeighted<gls::DrawTestSpec::Primitive>	(DE_ARRAY_BEGIN(primitives),		DE_ARRAY_END(primitives),		primitiveWeights.weights);
   1034 		spec.primitiveCount			= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(primitiveCounts),	DE_ARRAY_END(primitiveCounts),	primitiveCountWeights);
   1035 		spec.drawMethod				= random.chooseWeighted<gls::DrawTestSpec::DrawMethod>	(DE_ARRAY_BEGIN(drawMethods),		DE_ARRAY_END(drawMethods),		drawMethodWeights.weights);
   1036 		spec.indexType				= random.chooseWeighted<gls::DrawTestSpec::IndexType>	(DE_ARRAY_BEGIN(indexTypes),		DE_ARRAY_END(indexTypes),		indexTypeWeights.weights);
   1037 		spec.indexPointerOffset		= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indexOffsets),		DE_ARRAY_END(indexOffsets),		indexOffsetWeights);
   1038 		spec.indexStorage			= random.chooseWeighted<gls::DrawTestSpec::Storage>		(DE_ARRAY_BEGIN(storages),			DE_ARRAY_END(storages),			storageWeights.weights);
   1039 		spec.first					= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(firsts),			DE_ARRAY_END(firsts),			firstWeights);
   1040 		spec.indexMin				= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indexMins),			DE_ARRAY_END(indexMins),		indexWeights);
   1041 		spec.indexMax				= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indexMaxs),			DE_ARRAY_END(indexMaxs),		indexWeights);
   1042 		spec.instanceCount			= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(instanceCounts),	DE_ARRAY_END(instanceCounts),	instanceWeights);
   1043 
   1044 		// check spec is legal
   1045 		if (!spec.valid())
   1046 			continue;
   1047 
   1048 		for (int attrNdx = 0; attrNdx < attributeCount;)
   1049 		{
   1050 			bool valid;
   1051 			gls::DrawTestSpec::AttributeSpec attribSpec;
   1052 
   1053 			attribSpec.inputType			= random.chooseWeighted<gls::DrawTestSpec::InputType>	(DE_ARRAY_BEGIN(inputTypes),		DE_ARRAY_END(inputTypes),		inputTypeWeights.weights);
   1054 			attribSpec.outputType			= random.chooseWeighted<gls::DrawTestSpec::OutputType>	(DE_ARRAY_BEGIN(outputTypes),		DE_ARRAY_END(outputTypes),		outputTypeWeights.weights);
   1055 			attribSpec.storage				= random.chooseWeighted<gls::DrawTestSpec::Storage>		(DE_ARRAY_BEGIN(storages),			DE_ARRAY_END(storages),			storageWeights.weights);
   1056 			attribSpec.usage				= random.chooseWeighted<gls::DrawTestSpec::Usage>		(DE_ARRAY_BEGIN(usages),			DE_ARRAY_END(usages),			usageWeights.weights);
   1057 			attribSpec.componentCount		= random.getInt(1, 4);
   1058 			attribSpec.offset				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
   1059 			attribSpec.stride				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
   1060 			attribSpec.normalize			= random.getBool();
   1061 			attribSpec.instanceDivisor		= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(instanceDivisors), DE_ARRAY_END(instanceDivisors), instanceDivisorWeights);
   1062 			attribSpec.useDefaultAttribute	= random.getBool();
   1063 
   1064 			// check spec is legal
   1065 			valid = attribSpec.valid(spec.apiType);
   1066 
   1067 			// we do not want interleaved elements. (Might result in some weird floating point values)
   1068 			if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
   1069 				valid = false;
   1070 
   1071 			// try again if not valid
   1072 			if (valid)
   1073 			{
   1074 				spec.attribs.push_back(attribSpec);
   1075 				++attrNdx;
   1076 			}
   1077 		}
   1078 
   1079 		// Do not collapse all vertex positions to a single positions
   1080 		if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
   1081 			spec.attribs[0].instanceDivisor = 0;
   1082 
   1083 		// Is render result meaningful?
   1084 		{
   1085 			// Only one vertex
   1086 			if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
   1087 				continue;
   1088 			if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
   1089 				continue;
   1090 
   1091 			// Triangle only on one axis
   1092 			if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
   1093 			{
   1094 				if (spec.attribs[0].componentCount == 1)
   1095 					continue;
   1096 				if (spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_FLOAT || spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_INT || spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_UINT)
   1097 					continue;
   1098 				if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
   1099 					continue;
   1100 			}
   1101 		}
   1102 
   1103 		// Add case
   1104 		{
   1105 			deUint32 hash = spec.hash();
   1106 			for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
   1107 				hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash();
   1108 
   1109 			if (insertedHashes.find(hash) == insertedHashes.end())
   1110 			{
   1111 				// Only properly aligned and not blacklisted cases
   1112 				if (spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET			&&
   1113 					spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE			&&
   1114 					!de::contains(DE_ARRAY_BEGIN(blacklistedCases), DE_ARRAY_END(blacklistedCases), hash))
   1115 				{
   1116 					this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
   1117 				}
   1118 				insertedHashes.insert(hash);
   1119 
   1120 				++insertedCount;
   1121 			}
   1122 		}
   1123 	}
   1124 }
   1125 
   1126 } // anonymous
   1127 
   1128 DrawTests::DrawTests (Context& context)
   1129 	: TestCaseGroup(context, "draw", "Drawing tests")
   1130 {
   1131 }
   1132 
   1133 DrawTests::~DrawTests (void)
   1134 {
   1135 }
   1136 
   1137 void DrawTests::init (void)
   1138 {
   1139 	// Basic
   1140 	{
   1141 		const gls::DrawTestSpec::DrawMethod basicMethods[] =
   1142 		{
   1143 			gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
   1144 			gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
   1145 			gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED,
   1146 			gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED,
   1147 			gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED,
   1148 		};
   1149 
   1150 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
   1151 		{
   1152 			const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
   1153 			const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
   1154 
   1155 			this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
   1156 		}
   1157 	}
   1158 
   1159 	// extreme instancing
   1160 
   1161 	this->addChild(new InstancingGroup(m_context, "instancing", "draw tests with a large instance count."));
   1162 
   1163 	// Random
   1164 
   1165 	this->addChild(new RandomGroup(m_context, "random", "random draw commands."));
   1166 }
   1167 
   1168 } // Functional
   1169 } // gles3
   1170 } // deqp
   1171