1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.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 "es2fDrawTests.hpp"
25#include "glsDrawTest.hpp"
26#include "tcuRenderTarget.hpp"
27#include "deRandom.hpp"
28#include "deStringUtil.hpp"
29#include "deUniquePtr.hpp"
30#include "deSTLUtil.hpp"
31
32#include "glwEnums.hpp"
33
34#include <set>
35
36namespace deqp
37{
38namespace gles2
39{
40namespace Functional
41{
42namespace
43{
44
45enum TestIterationType
46{
47	TYPE_DRAW_COUNT,		// !< test with 1, 5, and 25 primitives
48
49	TYPE_LAST
50};
51
52static void addTestIterations (gls::DrawTest* test, const gls::DrawTestSpec& baseSpec, TestIterationType type)
53{
54	gls::DrawTestSpec spec(baseSpec);
55
56	if (type == TYPE_DRAW_COUNT)
57	{
58		spec.primitiveCount = 1;
59		test->addIteration(spec, "draw count = 1");
60
61		spec.primitiveCount = 5;
62		test->addIteration(spec, "draw count = 5");
63
64		spec.primitiveCount = 25;
65		test->addIteration(spec, "draw count = 25");
66	}
67	else
68		DE_ASSERT(false);
69}
70
71static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method)
72{
73	spec.apiType							= glu::ApiType::es(2,0);
74	spec.primitive							= gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
75	spec.primitiveCount						= 5;
76	spec.drawMethod							= method;
77	spec.indexType							= gls::DrawTestSpec::INDEXTYPE_LAST;
78	spec.indexPointerOffset					= 0;
79	spec.indexStorage						= gls::DrawTestSpec::STORAGE_LAST;
80	spec.first								= 0;
81	spec.indexMin							= 0;
82	spec.indexMax							= 0;
83	spec.instanceCount						= 1;
84
85	spec.attribs.resize(2);
86
87	spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
88	spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
89	spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
90	spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
91	spec.attribs[0].componentCount			= 4;
92	spec.attribs[0].offset					= 0;
93	spec.attribs[0].stride					= 0;
94	spec.attribs[0].normalize				= false;
95	spec.attribs[0].instanceDivisor			= 0;
96	spec.attribs[0].useDefaultAttribute		= false;
97
98	spec.attribs[1].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
99	spec.attribs[1].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
100	spec.attribs[1].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
101	spec.attribs[1].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
102	spec.attribs[1].componentCount			= 2;
103	spec.attribs[1].offset					= 0;
104	spec.attribs[1].stride					= 0;
105	spec.attribs[1].normalize				= false;
106	spec.attribs[1].instanceDivisor			= 0;
107	spec.attribs[1].useDefaultAttribute		= false;
108}
109
110
111class AttributeGroup : public TestCaseGroup
112{
113public:
114									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);
115									~AttributeGroup	(void);
116
117	void							init			(void);
118
119private:
120	gls::DrawTestSpec::DrawMethod	m_method;
121	gls::DrawTestSpec::Primitive	m_primitive;
122	gls::DrawTestSpec::IndexType	m_indexType;
123	gls::DrawTestSpec::Storage		m_indexStorage;
124};
125
126AttributeGroup::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)
127	: TestCaseGroup		(context, name, descr)
128	, m_method			(drawMethod)
129	, m_primitive		(primitive)
130	, m_indexType		(indexType)
131	, m_indexStorage	(indexStorage)
132{
133}
134
135AttributeGroup::~AttributeGroup (void)
136{
137}
138
139void AttributeGroup::init (void)
140{
141	// Single attribute
142	{
143		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
144		gls::DrawTestSpec	spec;
145
146		spec.apiType							= glu::ApiType::es(2,0);
147		spec.primitive							= m_primitive;
148		spec.primitiveCount						= 0;
149		spec.drawMethod							= m_method;
150		spec.indexType							= m_indexType;
151		spec.indexPointerOffset					= 0;
152		spec.indexStorage						= m_indexStorage;
153		spec.first								= 0;
154		spec.indexMin							= 0;
155		spec.indexMax							= 0;
156		spec.instanceCount						= 1;
157
158		spec.attribs.resize(1);
159
160		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
161		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
162		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
163		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
164		spec.attribs[0].componentCount			= 2;
165		spec.attribs[0].offset					= 0;
166		spec.attribs[0].stride					= 0;
167		spec.attribs[0].normalize				= false;
168		spec.attribs[0].instanceDivisor			= 0;
169		spec.attribs[0].useDefaultAttribute		= false;
170
171		addTestIterations(test, spec, TYPE_DRAW_COUNT);
172
173		this->addChild(test);
174	}
175
176	// Multiple attribute
177	{
178		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays");
179		gls::DrawTestSpec	spec;
180
181		spec.apiType							= glu::ApiType::es(2,0);
182		spec.primitive							= m_primitive;
183		spec.primitiveCount						= 0;
184		spec.drawMethod							= m_method;
185		spec.indexType							= m_indexType;
186		spec.indexPointerOffset					= 0;
187		spec.indexStorage						= m_indexStorage;
188		spec.first								= 0;
189		spec.indexMin							= 0;
190		spec.indexMax							= 0;
191		spec.instanceCount						= 1;
192
193		spec.attribs.resize(2);
194
195		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
196		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
197		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
198		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
199		spec.attribs[0].componentCount			= 4;
200		spec.attribs[0].offset					= 0;
201		spec.attribs[0].stride					= 0;
202		spec.attribs[0].normalize				= false;
203		spec.attribs[0].instanceDivisor			= 0;
204		spec.attribs[0].useDefaultAttribute		= false;
205
206		spec.attribs[1].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
207		spec.attribs[1].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
208		spec.attribs[1].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
209		spec.attribs[1].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
210		spec.attribs[1].componentCount			= 2;
211		spec.attribs[1].offset					= 0;
212		spec.attribs[1].stride					= 0;
213		spec.attribs[1].normalize				= false;
214		spec.attribs[1].instanceDivisor			= 0;
215		spec.attribs[1].useDefaultAttribute		= false;
216
217		addTestIterations(test, spec, TYPE_DRAW_COUNT);
218
219		this->addChild(test);
220	}
221
222	// Multiple attribute, second one default.
223	{
224		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*.");
225		gls::DrawTestSpec	spec;
226
227		spec.apiType							= glu::ApiType::es(2,0);
228		spec.primitive							= m_primitive;
229		spec.primitiveCount						= 5;
230		spec.drawMethod							= m_method;
231		spec.indexType							= m_indexType;
232		spec.indexPointerOffset					= 0;
233		spec.indexStorage						= m_indexStorage;
234		spec.first								= 0;
235		spec.indexMin							= 0;
236		spec.indexMax							= 0;
237		spec.instanceCount						= 1;
238
239		spec.attribs.resize(2);
240
241		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
242		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
243		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
244		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
245		spec.attribs[0].componentCount			= 2;
246		spec.attribs[0].offset					= 0;
247		spec.attribs[0].stride					= 0;
248		spec.attribs[0].normalize				= false;
249		spec.attribs[0].instanceDivisor			= 0;
250		spec.attribs[0].useDefaultAttribute		= false;
251
252		struct IOPair
253		{
254			gls::DrawTestSpec::InputType  input;
255			gls::DrawTestSpec::OutputType output;
256			int							  componentCount;
257		} iopairs[] =
258		{
259			{ gls::DrawTestSpec::INPUTTYPE_FLOAT,        gls::DrawTestSpec::OUTPUTTYPE_VEC2,  4 },
260			{ gls::DrawTestSpec::INPUTTYPE_FLOAT,        gls::DrawTestSpec::OUTPUTTYPE_VEC4,  2 },
261		};
262
263		for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
264		{
265			const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
266
267			spec.attribs[1].inputType			= iopairs[ioNdx].input;
268			spec.attribs[1].outputType			= iopairs[ioNdx].output;
269			spec.attribs[1].storage				= gls::DrawTestSpec::STORAGE_BUFFER;
270			spec.attribs[1].usage				= gls::DrawTestSpec::USAGE_STATIC_DRAW;
271			spec.attribs[1].componentCount		= iopairs[ioNdx].componentCount;
272			spec.attribs[1].offset				= 0;
273			spec.attribs[1].stride				= 0;
274			spec.attribs[1].normalize			= false;
275			spec.attribs[1].instanceDivisor		= 0;
276			spec.attribs[1].useDefaultAttribute	= true;
277
278			test->addIteration(spec, desc.c_str());
279		}
280
281		this->addChild(test);
282	}
283}
284
285class IndexGroup : public TestCaseGroup
286{
287public:
288									IndexGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
289									~IndexGroup		(void);
290
291	void							init			(void);
292
293private:
294	gls::DrawTestSpec::DrawMethod	m_method;
295};
296
297IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
298	: TestCaseGroup		(context, name, descr)
299	, m_method			(drawMethod)
300{
301}
302
303IndexGroup::~IndexGroup (void)
304{
305}
306
307void IndexGroup::init (void)
308{
309	struct IndexTest
310	{
311		gls::DrawTestSpec::Storage		storage;
312		gls::DrawTestSpec::IndexType	type;
313		bool							aligned;
314		int								offsets[3];
315	};
316
317	const IndexTest tests[] =
318	{
319		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_BYTE,	true,	{ 0, 1, -1 } },
320		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_SHORT,	true,	{ 0, 2, -1 } },
321
322		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_SHORT,	false,	{ 1, 3, -1 } },
323
324		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_BYTE,	true,	{ 0, 1, -1 } },
325		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_SHORT,	true,	{ 0, 2, -1 } },
326
327		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_SHORT,	false,	{ 1, 3, -1 } },
328	};
329
330	gls::DrawTestSpec spec;
331
332	tcu::TestCaseGroup* userPtrGroup			= new tcu::TestCaseGroup(m_testCtx, "user_ptr", "user pointer");
333	tcu::TestCaseGroup* unalignedUserPtrGroup	= new tcu::TestCaseGroup(m_testCtx, "unaligned_user_ptr", "unaligned user pointer");
334	tcu::TestCaseGroup* bufferGroup				= new tcu::TestCaseGroup(m_testCtx, "buffer", "buffer");
335	tcu::TestCaseGroup* unalignedBufferGroup	= new tcu::TestCaseGroup(m_testCtx, "unaligned_buffer", "unaligned buffer");
336
337	genBasicSpec(spec, m_method);
338
339	this->addChild(userPtrGroup);
340	this->addChild(unalignedUserPtrGroup);
341	this->addChild(bufferGroup);
342	this->addChild(unalignedBufferGroup);
343
344	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
345	{
346		const IndexTest&				indexTest	= tests[testNdx];
347		tcu::TestCaseGroup*				group		= (indexTest.storage == gls::DrawTestSpec::STORAGE_USER) ? ((indexTest.aligned) ? (userPtrGroup) : (unalignedUserPtrGroup)) : ((indexTest.aligned) ? (bufferGroup) : (unalignedBufferGroup));
348
349		const std::string				name		= std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
350		const std::string				desc		= std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage);
351		de::MovePtr<gls::DrawTest>		test		(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()));
352
353		spec.indexType			= indexTest.type;
354		spec.indexStorage		= indexTest.storage;
355
356		for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
357		{
358			const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]);
359			spec.indexPointerOffset	= indexTest.offsets[iterationNdx];
360			test->addIteration(spec, iterationDesc.c_str());
361		}
362
363		if (spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET &&
364			spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
365			group->addChild(test.release());
366	}
367}
368
369
370class FirstGroup : public TestCaseGroup
371{
372public:
373									FirstGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
374									~FirstGroup		(void);
375
376	void							init			(void);
377
378private:
379	gls::DrawTestSpec::DrawMethod	m_method;
380};
381
382FirstGroup::FirstGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
383	: TestCaseGroup		(context, name, descr)
384	, m_method			(drawMethod)
385{
386}
387
388FirstGroup::~FirstGroup (void)
389{
390}
391
392void FirstGroup::init (void)
393{
394	const int firsts[] =
395	{
396		0, 1, 17
397	};
398
399	gls::DrawTestSpec spec;
400	genBasicSpec(spec, m_method);
401
402	for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); ++firstNdx)
403	{
404		const std::string	name = std::string("first_") + de::toString(firsts[firstNdx]);
405		const std::string	desc = std::string("first ") + de::toString(firsts[firstNdx]);
406		gls::DrawTest*		test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
407
408		spec.first = firsts[firstNdx];
409
410		addTestIterations(test, spec, TYPE_DRAW_COUNT);
411
412		this->addChild(test);
413	}
414}
415
416class MethodGroup : public TestCaseGroup
417{
418public:
419									MethodGroup			(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
420									~MethodGroup		(void);
421
422	void							init				(void);
423
424private:
425	gls::DrawTestSpec::DrawMethod	m_method;
426};
427
428MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
429	: TestCaseGroup		(context, name, descr)
430	, m_method			(drawMethod)
431{
432}
433
434MethodGroup::~MethodGroup (void)
435{
436}
437
438void MethodGroup::init (void)
439{
440	const bool indexed		= (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
441	const bool hasFirst		= (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED);
442
443	const gls::DrawTestSpec::Primitive primitive[] =
444	{
445		gls::DrawTestSpec::PRIMITIVE_POINTS,
446		gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
447		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
448		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
449		gls::DrawTestSpec::PRIMITIVE_LINES,
450		gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
451		gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
452	};
453
454	if (hasFirst)
455	{
456		// First-tests
457		this->addChild(new FirstGroup(m_context, "first", "First tests", m_method));
458	}
459
460	if (indexed)
461	{
462		// Index-tests
463		if (m_method != gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED)
464			this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
465	}
466
467	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
468	{
469		const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
470		const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
471
472		this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
473	}
474}
475
476class RandomGroup : public TestCaseGroup
477{
478public:
479									RandomGroup		(Context& context, const char* name, const char* descr);
480									~RandomGroup	(void);
481
482	void							init			(void);
483};
484
485template <int SIZE>
486struct UniformWeightArray
487{
488	float weights[SIZE];
489
490	UniformWeightArray (void)
491	{
492		for (int i=0; i<SIZE; ++i)
493			weights[i] = 1.0f;
494	}
495};
496
497RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
498	: TestCaseGroup	(context, name, descr)
499{
500}
501
502RandomGroup::~RandomGroup (void)
503{
504}
505
506void RandomGroup::init (void)
507{
508	const int			numAttempts				= 100;
509
510	static const int	attribCounts[]			= { 1, 2, 5 };
511	static const float	attribWeights[]			= { 30, 10, 1 };
512	static const int	primitiveCounts[]		= { 1, 5, 64 };
513	static const float	primitiveCountWeights[]	= { 20, 10, 1 };
514	static const int	indexOffsets[]			= { 0, 7, 13 };
515	static const float	indexOffsetWeights[]	= { 20, 20, 1 };
516	static const int	firsts[]				= { 0, 7, 13 };
517	static const float	firstWeights[]			= { 20, 20, 1 };
518	static const int	offsets[]				= { 0, 1, 5, 12 };
519	static const float	offsetWeights[]			= { 50, 10, 10, 10 };
520	static const int	strides[]				= { 0, 7, 16, 17 };
521	static const float	strideWeights[]			= { 50, 10, 10, 10 };
522
523	static const gls::DrawTestSpec::Primitive primitives[] =
524	{
525		gls::DrawTestSpec::PRIMITIVE_POINTS,
526		gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
527		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
528		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
529		gls::DrawTestSpec::PRIMITIVE_LINES,
530		gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
531		gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
532	};
533	const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
534
535	static const gls::DrawTestSpec::DrawMethod drawMethods[] =
536	{
537		gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
538		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
539	};
540	const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
541
542	static const gls::DrawTestSpec::IndexType indexTypes[] =
543	{
544		gls::DrawTestSpec::INDEXTYPE_BYTE,
545		gls::DrawTestSpec::INDEXTYPE_SHORT,
546	};
547	const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
548
549	static const gls::DrawTestSpec::Storage storages[] =
550	{
551		gls::DrawTestSpec::STORAGE_USER,
552		gls::DrawTestSpec::STORAGE_BUFFER,
553	};
554	const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights;
555
556	static const gls::DrawTestSpec::InputType inputTypes[] =
557	{
558		gls::DrawTestSpec::INPUTTYPE_FLOAT,
559		gls::DrawTestSpec::INPUTTYPE_FIXED,
560		gls::DrawTestSpec::INPUTTYPE_BYTE,
561		gls::DrawTestSpec::INPUTTYPE_SHORT,
562		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
563		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT
564	};
565	const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
566
567	static const gls::DrawTestSpec::OutputType outputTypes[] =
568	{
569		gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
570		gls::DrawTestSpec::OUTPUTTYPE_VEC2,
571		gls::DrawTestSpec::OUTPUTTYPE_VEC3,
572		gls::DrawTestSpec::OUTPUTTYPE_VEC4,
573	};
574	const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
575
576	static const gls::DrawTestSpec::Usage usages[] =
577	{
578		gls::DrawTestSpec::USAGE_STATIC_DRAW,
579		gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
580		gls::DrawTestSpec::USAGE_STREAM_DRAW,
581	};
582	const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
583
584	static const deUint32 blacklistedCases[]=
585	{
586		3153,	//!< extremely narrow triangle, results depend on sample positions
587	};
588
589	std::set<deUint32>	insertedHashes;
590	size_t				insertedCount = 0;
591
592	for (int ndx = 0; ndx < numAttempts; ++ndx)
593	{
594		de::Random random(0xc551393 + ndx); // random does not depend on previous cases
595
596		int					attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
597		gls::DrawTestSpec	spec;
598
599		spec.apiType				= glu::ApiType::es(2,0);
600		spec.primitive				= random.chooseWeighted<gls::DrawTestSpec::Primitive>	(DE_ARRAY_BEGIN(primitives),		DE_ARRAY_END(primitives),		primitiveWeights.weights);
601		spec.primitiveCount			= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(primitiveCounts),	DE_ARRAY_END(primitiveCounts),	primitiveCountWeights);
602		spec.drawMethod				= random.chooseWeighted<gls::DrawTestSpec::DrawMethod>	(DE_ARRAY_BEGIN(drawMethods),		DE_ARRAY_END(drawMethods),		drawMethodWeights.weights);
603		spec.indexType				= random.chooseWeighted<gls::DrawTestSpec::IndexType>	(DE_ARRAY_BEGIN(indexTypes),		DE_ARRAY_END(indexTypes),		indexTypeWeights.weights);
604		spec.indexPointerOffset		= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indexOffsets),		DE_ARRAY_END(indexOffsets),		indexOffsetWeights);
605		spec.indexStorage			= random.chooseWeighted<gls::DrawTestSpec::Storage>		(DE_ARRAY_BEGIN(storages),			DE_ARRAY_END(storages),			storageWeights.weights);
606		spec.first					= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(firsts),			DE_ARRAY_END(firsts),			firstWeights);
607		spec.indexMin				= 0;
608		spec.indexMax				= 0;
609		spec.instanceCount			= 0;
610
611		// check spec is legal
612		if (!spec.valid())
613			continue;
614
615		for (int attrNdx = 0; attrNdx < attributeCount;)
616		{
617			bool valid;
618			gls::DrawTestSpec::AttributeSpec attribSpec;
619
620			attribSpec.inputType			= random.chooseWeighted<gls::DrawTestSpec::InputType>	(DE_ARRAY_BEGIN(inputTypes),		DE_ARRAY_END(inputTypes),		inputTypeWeights.weights);
621			attribSpec.outputType			= random.chooseWeighted<gls::DrawTestSpec::OutputType>	(DE_ARRAY_BEGIN(outputTypes),		DE_ARRAY_END(outputTypes),		outputTypeWeights.weights);
622			attribSpec.storage				= random.chooseWeighted<gls::DrawTestSpec::Storage>		(DE_ARRAY_BEGIN(storages),			DE_ARRAY_END(storages),			storageWeights.weights);
623			attribSpec.usage				= random.chooseWeighted<gls::DrawTestSpec::Usage>		(DE_ARRAY_BEGIN(usages),			DE_ARRAY_END(usages),			usageWeights.weights);
624			attribSpec.componentCount		= random.getInt(1, 4);
625			attribSpec.offset				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
626			attribSpec.stride				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
627			attribSpec.normalize			= random.getBool();
628			attribSpec.instanceDivisor		= 0;
629			attribSpec.useDefaultAttribute	= random.getBool();
630
631			// check spec is legal
632			valid = attribSpec.valid(spec.apiType);
633
634			// we do not want interleaved elements. (Might result in some weird floating point values)
635			if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
636				valid = false;
637
638			// try again if not valid
639			if (valid)
640			{
641				spec.attribs.push_back(attribSpec);
642				++attrNdx;
643			}
644		}
645
646		// Do not collapse all vertex positions to a single positions
647		if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
648			spec.attribs[0].instanceDivisor = 0;
649
650		// Is render result meaningful?
651		{
652			// Only one vertex
653			if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
654				continue;
655			if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
656				continue;
657
658			// Triangle only on one axis
659			if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
660			{
661				if (spec.attribs[0].componentCount == 1)
662					continue;
663				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)
664					continue;
665				if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
666					continue;
667			}
668		}
669
670		// Add case
671		{
672			deUint32 hash = spec.hash();
673			for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
674				hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash();
675
676			if (insertedHashes.find(hash) == insertedHashes.end() &&
677				!de::contains(DE_ARRAY_BEGIN(blacklistedCases), DE_ARRAY_END(blacklistedCases), hash))
678			{
679				// Only aligned cases
680				if (spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET &&
681					spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
682					this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
683				insertedHashes.insert(hash);
684
685				++insertedCount;
686			}
687		}
688	}
689}
690
691} // anonymous
692
693DrawTests::DrawTests (Context& context)
694	: TestCaseGroup(context, "draw", "Drawing tests")
695{
696}
697
698DrawTests::~DrawTests (void)
699{
700}
701
702void DrawTests::init (void)
703{
704	// Basic
705	{
706		const gls::DrawTestSpec::DrawMethod basicMethods[] =
707		{
708			gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
709			gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
710		};
711
712		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
713		{
714			std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
715			std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
716
717			this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
718		}
719	}
720
721	// Random
722
723	this->addChild(new RandomGroup(m_context, "random", "random draw commands."));
724}
725
726} // Functional
727} // gles2
728} // deqp
729