• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
36 namespace deqp
37 {
38 namespace gles2
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 
49 	TYPE_LAST
50 };
51 
addTestIterations(gls::DrawTest * test,const gls::DrawTestSpec & baseSpec,TestIterationType type)52 static 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 
genBasicSpec(gls::DrawTestSpec & spec,gls::DrawTestSpec::DrawMethod method)71 static 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 
111 class AttributeGroup : public TestCaseGroup
112 {
113 public:
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 
119 private:
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 
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)126 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)
127 	: TestCaseGroup		(context, name, descr)
128 	, m_method			(drawMethod)
129 	, m_primitive		(primitive)
130 	, m_indexType		(indexType)
131 	, m_indexStorage	(indexStorage)
132 {
133 }
134 
~AttributeGroup(void)135 AttributeGroup::~AttributeGroup (void)
136 {
137 }
138 
init(void)139 void 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 
285 class IndexGroup : public TestCaseGroup
286 {
287 public:
288 									IndexGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
289 									~IndexGroup		(void);
290 
291 	void							init			(void);
292 
293 private:
294 	gls::DrawTestSpec::DrawMethod	m_method;
295 };
296 
IndexGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)297 IndexGroup::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 
~IndexGroup(void)303 IndexGroup::~IndexGroup (void)
304 {
305 }
306 
init(void)307 void 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 
328 	gls::DrawTestSpec spec;
329 
330 	tcu::TestCaseGroup* userPtrGroup			= new tcu::TestCaseGroup(m_testCtx, "user_ptr", "user pointer");
331 	tcu::TestCaseGroup* unalignedUserPtrGroup	= new tcu::TestCaseGroup(m_testCtx, "unaligned_user_ptr", "unaligned user pointer");
332 	tcu::TestCaseGroup* bufferGroup				= new tcu::TestCaseGroup(m_testCtx, "buffer", "buffer");
333 
334 	genBasicSpec(spec, m_method);
335 
336 	this->addChild(userPtrGroup);
337 	this->addChild(unalignedUserPtrGroup);
338 	this->addChild(bufferGroup);
339 
340 	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
341 	{
342 		const IndexTest&				indexTest	= tests[testNdx];
343 		tcu::TestCaseGroup*				group		= (indexTest.storage == gls::DrawTestSpec::STORAGE_USER)
344 													? ((indexTest.aligned) ? (userPtrGroup) : (unalignedUserPtrGroup))
345 													: ((indexTest.aligned) ? (bufferGroup) : (DE_NULL));
346 
347 		const std::string				name		= std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
348 		const std::string				desc		= std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage);
349 		de::MovePtr<gls::DrawTest>		test		(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()));
350 
351 		spec.indexType			= indexTest.type;
352 		spec.indexStorage		= indexTest.storage;
353 
354 		for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
355 		{
356 			const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]);
357 			spec.indexPointerOffset	= indexTest.offsets[iterationNdx];
358 			test->addIteration(spec, iterationDesc.c_str());
359 		}
360 
361 		DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET);
362 		DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE);
363 		group->addChild(test.release());
364 	}
365 }
366 
367 
368 class FirstGroup : public TestCaseGroup
369 {
370 public:
371 									FirstGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
372 									~FirstGroup		(void);
373 
374 	void							init			(void);
375 
376 private:
377 	gls::DrawTestSpec::DrawMethod	m_method;
378 };
379 
FirstGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)380 FirstGroup::FirstGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
381 	: TestCaseGroup		(context, name, descr)
382 	, m_method			(drawMethod)
383 {
384 }
385 
~FirstGroup(void)386 FirstGroup::~FirstGroup (void)
387 {
388 }
389 
init(void)390 void FirstGroup::init (void)
391 {
392 	const int firsts[] =
393 	{
394 		0, 1, 17
395 	};
396 
397 	gls::DrawTestSpec spec;
398 	genBasicSpec(spec, m_method);
399 
400 	for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); ++firstNdx)
401 	{
402 		const std::string	name = std::string("first_") + de::toString(firsts[firstNdx]);
403 		const std::string	desc = std::string("first ") + de::toString(firsts[firstNdx]);
404 		gls::DrawTest*		test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
405 
406 		spec.first = firsts[firstNdx];
407 
408 		addTestIterations(test, spec, TYPE_DRAW_COUNT);
409 
410 		this->addChild(test);
411 	}
412 }
413 
414 class MethodGroup : public TestCaseGroup
415 {
416 public:
417 									MethodGroup			(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
418 									~MethodGroup		(void);
419 
420 	void							init				(void);
421 
422 private:
423 	gls::DrawTestSpec::DrawMethod	m_method;
424 };
425 
MethodGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)426 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
427 	: TestCaseGroup		(context, name, descr)
428 	, m_method			(drawMethod)
429 {
430 }
431 
~MethodGroup(void)432 MethodGroup::~MethodGroup (void)
433 {
434 }
435 
init(void)436 void MethodGroup::init (void)
437 {
438 	const bool indexed		= (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
439 	const bool hasFirst		= (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED);
440 
441 	const gls::DrawTestSpec::Primitive primitive[] =
442 	{
443 		gls::DrawTestSpec::PRIMITIVE_POINTS,
444 		gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
445 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
446 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
447 		gls::DrawTestSpec::PRIMITIVE_LINES,
448 		gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
449 		gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
450 	};
451 
452 	if (hasFirst)
453 	{
454 		// First-tests
455 		this->addChild(new FirstGroup(m_context, "first", "First tests", m_method));
456 	}
457 
458 	if (indexed)
459 	{
460 		// Index-tests
461 		if (m_method != gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED)
462 			this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
463 	}
464 
465 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
466 	{
467 		const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
468 		const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
469 
470 		this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
471 	}
472 }
473 
474 class RandomGroup : public TestCaseGroup
475 {
476 public:
477 									RandomGroup		(Context& context, const char* name, const char* descr);
478 									~RandomGroup	(void);
479 
480 	void							init			(void);
481 };
482 
483 template <int SIZE>
484 struct UniformWeightArray
485 {
486 	float weights[SIZE];
487 
UniformWeightArraydeqp::gles2::Functional::__anon7e97bc810111::UniformWeightArray488 	UniformWeightArray (void)
489 	{
490 		for (int i=0; i<SIZE; ++i)
491 			weights[i] = 1.0f;
492 	}
493 };
494 
RandomGroup(Context & context,const char * name,const char * descr)495 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
496 	: TestCaseGroup	(context, name, descr)
497 {
498 }
499 
~RandomGroup(void)500 RandomGroup::~RandomGroup (void)
501 {
502 }
503 
init(void)504 void RandomGroup::init (void)
505 {
506 	const int			numAttempts				= 100;
507 
508 	static const int	attribCounts[]			= { 1, 2, 5 };
509 	static const float	attribWeights[]			= { 30, 10, 1 };
510 	static const int	primitiveCounts[]		= { 1, 5, 64 };
511 	static const float	primitiveCountWeights[]	= { 20, 10, 1 };
512 	static const int	indexOffsets[]			= { 0, 7, 13 };
513 	static const float	indexOffsetWeights[]	= { 20, 20, 1 };
514 	static const int	firsts[]				= { 0, 7, 13 };
515 	static const float	firstWeights[]			= { 20, 20, 1 };
516 	static const int	offsets[]				= { 0, 1, 5, 12 };
517 	static const float	offsetWeights[]			= { 50, 10, 10, 10 };
518 	static const int	strides[]				= { 0, 7, 16, 17 };
519 	static const float	strideWeights[]			= { 50, 10, 10, 10 };
520 
521 	static const gls::DrawTestSpec::Primitive primitives[] =
522 	{
523 		gls::DrawTestSpec::PRIMITIVE_POINTS,
524 		gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
525 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
526 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
527 		gls::DrawTestSpec::PRIMITIVE_LINES,
528 		gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
529 		gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
530 	};
531 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
532 
533 	static const gls::DrawTestSpec::DrawMethod drawMethods[] =
534 	{
535 		gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
536 		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
537 	};
538 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
539 
540 	static const gls::DrawTestSpec::IndexType indexTypes[] =
541 	{
542 		gls::DrawTestSpec::INDEXTYPE_BYTE,
543 		gls::DrawTestSpec::INDEXTYPE_SHORT,
544 	};
545 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
546 
547 	static const gls::DrawTestSpec::Storage storages[] =
548 	{
549 		gls::DrawTestSpec::STORAGE_USER,
550 		gls::DrawTestSpec::STORAGE_BUFFER,
551 	};
552 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights;
553 
554 	static const gls::DrawTestSpec::InputType inputTypes[] =
555 	{
556 		gls::DrawTestSpec::INPUTTYPE_FLOAT,
557 		gls::DrawTestSpec::INPUTTYPE_FIXED,
558 		gls::DrawTestSpec::INPUTTYPE_BYTE,
559 		gls::DrawTestSpec::INPUTTYPE_SHORT,
560 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
561 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT
562 	};
563 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
564 
565 	static const gls::DrawTestSpec::OutputType outputTypes[] =
566 	{
567 		gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
568 		gls::DrawTestSpec::OUTPUTTYPE_VEC2,
569 		gls::DrawTestSpec::OUTPUTTYPE_VEC3,
570 		gls::DrawTestSpec::OUTPUTTYPE_VEC4,
571 	};
572 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
573 
574 	static const gls::DrawTestSpec::Usage usages[] =
575 	{
576 		gls::DrawTestSpec::USAGE_STATIC_DRAW,
577 		gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
578 		gls::DrawTestSpec::USAGE_STREAM_DRAW,
579 	};
580 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
581 
582 	static const deUint32 blacklistedCases[]=
583 	{
584 		3153,	//!< extremely narrow triangle, results depend on sample positions
585 	};
586 
587 	std::set<deUint32>	insertedHashes;
588 	size_t				insertedCount = 0;
589 
590 	for (int ndx = 0; ndx < numAttempts; ++ndx)
591 	{
592 		de::Random random(0xc551393 + ndx); // random does not depend on previous cases
593 
594 		int					attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
595 		gls::DrawTestSpec	spec;
596 
597 		spec.apiType				= glu::ApiType::es(2,0);
598 		spec.primitive				= random.chooseWeighted<gls::DrawTestSpec::Primitive>	(DE_ARRAY_BEGIN(primitives),		DE_ARRAY_END(primitives),		primitiveWeights.weights);
599 		spec.primitiveCount			= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(primitiveCounts),	DE_ARRAY_END(primitiveCounts),	primitiveCountWeights);
600 		spec.drawMethod				= random.chooseWeighted<gls::DrawTestSpec::DrawMethod>	(DE_ARRAY_BEGIN(drawMethods),		DE_ARRAY_END(drawMethods),		drawMethodWeights.weights);
601 		spec.indexType				= random.chooseWeighted<gls::DrawTestSpec::IndexType>	(DE_ARRAY_BEGIN(indexTypes),		DE_ARRAY_END(indexTypes),		indexTypeWeights.weights);
602 		spec.indexPointerOffset		= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indexOffsets),		DE_ARRAY_END(indexOffsets),		indexOffsetWeights);
603 		spec.indexStorage			= random.chooseWeighted<gls::DrawTestSpec::Storage>		(DE_ARRAY_BEGIN(storages),			DE_ARRAY_END(storages),			storageWeights.weights);
604 		spec.first					= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(firsts),			DE_ARRAY_END(firsts),			firstWeights);
605 		spec.indexMin				= 0;
606 		spec.indexMax				= 0;
607 		spec.instanceCount			= 0;
608 
609 		// check spec is legal
610 		if (!spec.valid())
611 			continue;
612 
613 		for (int attrNdx = 0; attrNdx < attributeCount;)
614 		{
615 			bool valid;
616 			gls::DrawTestSpec::AttributeSpec attribSpec;
617 
618 			attribSpec.inputType			= random.chooseWeighted<gls::DrawTestSpec::InputType>	(DE_ARRAY_BEGIN(inputTypes),		DE_ARRAY_END(inputTypes),		inputTypeWeights.weights);
619 			attribSpec.outputType			= random.chooseWeighted<gls::DrawTestSpec::OutputType>	(DE_ARRAY_BEGIN(outputTypes),		DE_ARRAY_END(outputTypes),		outputTypeWeights.weights);
620 			attribSpec.storage				= random.chooseWeighted<gls::DrawTestSpec::Storage>		(DE_ARRAY_BEGIN(storages),			DE_ARRAY_END(storages),			storageWeights.weights);
621 			attribSpec.usage				= random.chooseWeighted<gls::DrawTestSpec::Usage>		(DE_ARRAY_BEGIN(usages),			DE_ARRAY_END(usages),			usageWeights.weights);
622 			attribSpec.componentCount		= random.getInt(1, 4);
623 			attribSpec.offset				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
624 			attribSpec.stride				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
625 			attribSpec.normalize			= random.getBool();
626 			attribSpec.instanceDivisor		= 0;
627 			attribSpec.useDefaultAttribute	= random.getBool();
628 
629 			// check spec is legal
630 			valid = attribSpec.valid(spec.apiType);
631 
632 			// we do not want interleaved elements. (Might result in some weird floating point values)
633 			if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
634 				valid = false;
635 
636 			// try again if not valid
637 			if (valid)
638 			{
639 				spec.attribs.push_back(attribSpec);
640 				++attrNdx;
641 			}
642 		}
643 
644 		// Do not collapse all vertex positions to a single positions
645 		if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
646 			spec.attribs[0].instanceDivisor = 0;
647 
648 		// Is render result meaningful?
649 		{
650 			// Only one vertex
651 			if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
652 				continue;
653 			if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
654 				continue;
655 
656 			// Triangle only on one axis
657 			if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
658 			{
659 				if (spec.attribs[0].componentCount == 1)
660 					continue;
661 				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)
662 					continue;
663 				if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
664 					continue;
665 			}
666 		}
667 
668 		// Add case
669 		{
670 			deUint32 hash = spec.hash();
671 			for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
672 				hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash();
673 
674 			if (insertedHashes.find(hash) == insertedHashes.end() &&
675 				!de::contains(DE_ARRAY_BEGIN(blacklistedCases), DE_ARRAY_END(blacklistedCases), hash))
676 			{
677 				// Only aligned cases
678 				if (spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET &&
679 					spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
680 					this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
681 				insertedHashes.insert(hash);
682 
683 				++insertedCount;
684 			}
685 		}
686 	}
687 }
688 
689 } // anonymous
690 
DrawTests(Context & context)691 DrawTests::DrawTests (Context& context)
692 	: TestCaseGroup(context, "draw", "Drawing tests")
693 {
694 }
695 
~DrawTests(void)696 DrawTests::~DrawTests (void)
697 {
698 }
699 
init(void)700 void DrawTests::init (void)
701 {
702 	// Basic
703 	{
704 		const gls::DrawTestSpec::DrawMethod basicMethods[] =
705 		{
706 			gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
707 			gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
708 		};
709 
710 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
711 		{
712 			std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
713 			std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
714 
715 			this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
716 		}
717 	}
718 
719 	// Random
720 
721 	this->addChild(new RandomGroup(m_context, "random", "random draw commands."));
722 }
723 
724 } // Functional
725 } // gles2
726 } // deqp
727