• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
addTestIterations(gls::DrawTest * test,const gls::DrawTestSpec & baseSpec,TestIterationType type)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 
genBasicSpec(gls::DrawTestSpec & spec,gls::DrawTestSpec::DrawMethod method)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 
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)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 
~AttributeGroup(void)165 AttributeGroup::~AttributeGroup (void)
166 {
167 }
168 
init(void)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 
IndexGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)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 
~IndexGroup(void)401 IndexGroup::~IndexGroup (void)
402 {
403 }
404 
init(void)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 
FirstGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)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 
~FirstGroup(void)487 FirstGroup::~FirstGroup (void)
488 {
489 }
490 
init(void)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 
MethodGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)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 
~MethodGroup(void)533 MethodGroup::~MethodGroup (void)
534 {
535 }
536 
init(void)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 
GridProgram(void)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 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const612 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 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const621 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 
InstancedGridRenderTest(Context & context,const char * name,const char * desc,int gridSide,bool useIndices)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 
~InstancedGridRenderTest(void)651 InstancedGridRenderTest::~InstancedGridRenderTest (void)
652 {
653 }
654 
iterate(void)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 
renderTo(sglr::Context & ctx,sglr::ShaderProgram & program,tcu::Surface & dst)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 
verifyImage(const tcu::Surface & image)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 
InstancingGroup(Context & context,const char * name,const char * descr)840 InstancingGroup::InstancingGroup (Context& context, const char* name, const char* descr)
841 	: TestCaseGroup	(context, name, descr)
842 {
843 }
844 
~InstancingGroup(void)845 InstancingGroup::~InstancingGroup (void)
846 {
847 }
848 
init(void)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 
UniformWeightArraydeqp::gles3::Functional::__anonbb7885e30111::UniformWeightArray893 	UniformWeightArray (void)
894 	{
895 		for (int i=0; i<SIZE; ++i)
896 			weights[i] = 1.0f;
897 	}
898 };
899 
RandomGroup(Context & context,const char * name,const char * descr)900 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
901 	: TestCaseGroup	(context, name, descr)
902 {
903 }
904 
~RandomGroup(void)905 RandomGroup::~RandomGroup (void)
906 {
907 }
908 
init(void)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 
DrawTests(Context & context)1128 DrawTests::DrawTests (Context& context)
1129 	: TestCaseGroup(context, "draw", "Drawing tests")
1130 {
1131 }
1132 
~DrawTests(void)1133 DrawTests::~DrawTests (void)
1134 {
1135 }
1136 
init(void)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