es31fDrawElementsBaseVertexTests.cpp revision 3c865084eb27036bf9fd43a41a7eae277a6ee170
1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2017 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 GL_EXT_draw_elements_base_vertex tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es31fDrawElementsBaseVertexTests.hpp"
25#include "deRandom.hpp"
26#include "deStringUtil.hpp"
27#include "tcuRenderTarget.hpp"
28#include "tcuVectorUtil.hpp"
29#include "sglrGLContext.hpp"
30#include "glsDrawTest.hpp"
31#include "gluStrUtil.hpp"
32#include "gluPixelTransfer.hpp"
33#include "gluContextInfo.hpp"
34
35#include "glwEnums.hpp"
36#include "glwFunctions.hpp"
37
38#include <string>
39#include <set>
40
41using std::vector;
42using std::string;
43using tcu::TestLog;
44
45using namespace glw;
46
47namespace deqp
48{
49namespace gles31
50{
51namespace Functional
52{
53namespace
54{
55
56enum TestIterationType
57{
58	TYPE_DRAW_COUNT,		// !< test with 1, 5, and 25 primitives
59	TYPE_INSTANCE_COUNT,	// !< test with 1, 4, and 11 instances
60
61	TYPE_LAST
62};
63
64static size_t getElementCount (gls::DrawTestSpec::Primitive primitive, size_t primitiveCount)
65{
66	switch (primitive)
67	{
68		case gls::DrawTestSpec::PRIMITIVE_POINTS:						return primitiveCount;
69		case gls::DrawTestSpec::PRIMITIVE_TRIANGLES:					return primitiveCount * 3;
70		case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN:					return primitiveCount + 2;
71		case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP:				return primitiveCount + 2;
72		case gls::DrawTestSpec::PRIMITIVE_LINES:						return primitiveCount * 2;
73		case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP:					return primitiveCount + 1;
74		case gls::DrawTestSpec::PRIMITIVE_LINE_LOOP:					return (primitiveCount==1) ? (2) : (primitiveCount);
75		case gls::DrawTestSpec::PRIMITIVE_LINES_ADJACENCY:				return primitiveCount * 4;
76		case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY:			return primitiveCount + 3;
77		case gls::DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY:			return primitiveCount * 6;
78		case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY:		return primitiveCount * 2 + 4;
79		default:
80			DE_ASSERT(false);
81			return 0;
82	}
83}
84
85static void addRangeElementsToSpec (gls::DrawTestSpec& spec)
86{
87	if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
88	{
89		spec.indexMin = 0;
90		spec.indexMax = (int)getElementCount(spec.primitive, spec.primitiveCount);
91	}
92}
93
94static void addTestIterations (gls::DrawTest* test, gls::DrawTestSpec& spec, TestIterationType type)
95{
96	if (type == TYPE_DRAW_COUNT)
97	{
98		spec.primitiveCount = 1;
99		addRangeElementsToSpec(spec);
100		test->addIteration(spec, "draw count = 1");
101
102		spec.primitiveCount = 5;
103		addRangeElementsToSpec(spec);
104		test->addIteration(spec, "draw count = 5");
105
106		spec.primitiveCount = 25;
107		addRangeElementsToSpec(spec);
108		test->addIteration(spec, "draw count = 25");
109	}
110	else if (type == TYPE_INSTANCE_COUNT)
111	{
112		spec.instanceCount = 1;
113		addRangeElementsToSpec(spec);
114		test->addIteration(spec, "instance count = 1");
115
116		spec.instanceCount = 4;
117		addRangeElementsToSpec(spec);
118		test->addIteration(spec, "instance count = 4");
119
120		spec.instanceCount = 11;
121		addRangeElementsToSpec(spec);
122		test->addIteration(spec, "instance count = 11");
123	}
124	else
125		DE_ASSERT(false);
126}
127
128static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method)
129{
130	spec.apiType							= glu::ApiType::es(3,1);
131	spec.primitive							= gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
132	spec.primitiveCount						= 5;
133	spec.drawMethod							= method;
134	spec.indexType							= gls::DrawTestSpec::INDEXTYPE_LAST;
135	spec.indexPointerOffset					= 0;
136	spec.indexStorage						= gls::DrawTestSpec::STORAGE_LAST;
137	spec.first								= 0;
138	spec.indexMin							= 0;
139	spec.indexMax							= 0;
140	spec.instanceCount						= 1;
141	spec.indirectOffset						= 0;
142
143	spec.attribs.resize(2);
144
145	spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
146	spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
147	spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
148	spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
149	spec.attribs[0].componentCount			= 4;
150	spec.attribs[0].offset					= 0;
151	spec.attribs[0].stride					= 0;
152	spec.attribs[0].normalize				= false;
153	spec.attribs[0].instanceDivisor			= 0;
154	spec.attribs[0].useDefaultAttribute		= false;
155
156	spec.attribs[1].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
157	spec.attribs[1].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
158	spec.attribs[1].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
159	spec.attribs[1].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
160	spec.attribs[1].componentCount			= 2;
161	spec.attribs[1].offset					= 0;
162	spec.attribs[1].stride					= 0;
163	spec.attribs[1].normalize				= false;
164	spec.attribs[1].instanceDivisor			= 0;
165	spec.attribs[1].useDefaultAttribute		= false;
166
167	addRangeElementsToSpec(spec);
168}
169
170class VertexIDCase : public TestCase
171{
172public:
173									VertexIDCase			(Context& context, gls::DrawTestSpec::DrawMethod drawMethod);
174									~VertexIDCase			(void);
175
176	void							init					(void);
177	void							deinit					(void);
178	IterateResult					iterate					(void);
179
180	void							draw					(GLenum mode, GLsizei count, GLenum type, GLvoid* indices, GLint baseVertex);
181	void							verifyImage				(const tcu::Surface& image);
182
183private:
184	const glw::Functions&			m_gl;
185	glu::ShaderProgram*				m_program;
186	GLuint							m_coordinatesBuffer;
187	GLuint							m_elementsBuffer;
188	int								m_iterNdx;
189	gls::DrawTestSpec::DrawMethod	m_method;
190
191	enum
192	{
193		VIEWPORT_WIDTH = 64,
194		VIEWPORT_HEIGHT = 64
195	};
196
197	enum
198	{
199		MAX_VERTICES = 2*3	//!< 2 triangles, totals 6 vertices
200	};
201};
202
203VertexIDCase::VertexIDCase (Context& context,  gls::DrawTestSpec::DrawMethod drawMethod)
204	: TestCase				(context, "vertex_id", "gl_VertexID Test")
205	, m_gl					(m_context.getRenderContext().getFunctions())
206	, m_program				(DE_NULL)
207	, m_coordinatesBuffer	(0)
208	, m_elementsBuffer		(0)
209	, m_iterNdx				(0)
210	, m_method				(drawMethod)
211{
212}
213
214VertexIDCase::~VertexIDCase (void)
215{
216	VertexIDCase::deinit();
217}
218
219void VertexIDCase::init (void)
220{
221	m_testCtx.getLog()	<< TestLog::Message
222						<< "gl_VertexID should be the index of the vertex that is being passed to the shader. i.e. indices[i] + basevertex"
223						<< TestLog::EndMessage;
224
225	DE_ASSERT(!m_program);
226	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(
227		"#version 310 es\n"
228		"in highp vec4 a_position;\n"
229		"out mediump vec4 v_color;\n"
230		"uniform highp vec4 u_colors[8];\n"
231		"void main (void)\n"
232		"{\n"
233		"	gl_Position = a_position;\n"
234		"	v_color = u_colors[gl_VertexID];\n"
235		"}\n",
236
237		"#version 310 es\n"
238		"in mediump vec4 v_color;\n"
239		"layout(location = 0) out mediump vec4 o_color;\n"
240		"void main (void)\n"
241		"{\n"
242		"	o_color = v_color;\n"
243		"}\n"));
244
245	m_testCtx.getLog() << *m_program;
246
247	if (!m_program->isOk())
248	{
249		delete m_program;
250		m_program = DE_NULL;
251		TCU_FAIL("Failed to compile shader program");
252	}
253
254	GLU_CHECK_GLW_CALL(m_gl, useProgram(m_program->getProgram()));
255
256	GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer));
257	GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_elementsBuffer));
258}
259
260void VertexIDCase::deinit (void)
261{
262	delete m_program;
263	m_program = DE_NULL;
264
265	if (m_elementsBuffer)
266	{
267		GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_elementsBuffer));
268		m_elementsBuffer = 0;
269	}
270
271	if (m_coordinatesBuffer)
272	{
273		GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer));
274		m_coordinatesBuffer = 0;
275	}
276}
277
278void VertexIDCase::draw (GLenum mode, GLsizei count, GLenum type, GLvoid* indices, GLint baseVertex)
279{
280	switch (m_method)
281	{
282		case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX:
283			GLU_CHECK_GLW_CALL(m_gl, drawElementsBaseVertex(mode, count, type, indices, baseVertex));
284			break;
285
286		case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX:
287		{
288			GLint maxElementsVertices = 0;
289			GLU_CHECK_GLW_CALL(m_gl, getIntegerv(GL_MAX_ELEMENTS_VERTICES, &maxElementsVertices));
290			GLU_CHECK_GLW_CALL(m_gl, drawRangeElementsBaseVertex(mode, 0, maxElementsVertices, count, type, indices, baseVertex));
291			break;
292		}
293
294		case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX:
295				GLU_CHECK_GLW_CALL(m_gl, drawElementsInstancedBaseVertex(mode, count, type, indices, 1, baseVertex));
296				break;
297
298		default:
299			DE_FATAL("Draw method not supported");
300	}
301}
302
303void VertexIDCase::verifyImage (const tcu::Surface& image)
304{
305	tcu::TestLog&	log				= m_testCtx.getLog();
306	bool			isOk			= true;
307
308	const int		colorThreshold	= 0; // expect perfect match
309	tcu::Surface	error			(image.getWidth(), image.getHeight());
310
311	for (int y = 0; y < image.getHeight(); y++)
312	for (int x = 0; x < image.getWidth(); x++)
313	{
314		const tcu::RGBA pixel = image.getPixel(x, y);
315		bool pixelOk = true;
316
317		// Ignore pixels not drawn with basevertex
318		if ((x < image.getWidth()* 1/4) || (x > image.getWidth()  * 3/4)
319			|| (y < image.getHeight() * 1/4) || (y > image.getHeight() * 3/4))
320			continue;
321
322		// Any pixel with !(B ~= 255) is faulty
323		if (de::abs(pixel.getBlue() - 255) > colorThreshold)
324			pixelOk = false;
325
326		error.setPixel(x, y, (pixelOk) ? (tcu::RGBA(0, 255, 0, 255)) : (tcu::RGBA(255, 0, 0, 255)));
327		isOk = isOk && pixelOk;
328	}
329
330	if (!isOk)
331	{
332		log << TestLog::Message << "Image verification failed." << TestLog::EndMessage;
333		log << TestLog::ImageSet("Verification result", "Result of rendering")
334			<< TestLog::Image("Result",		"Result",		image)
335			<< TestLog::Image("Error Mask",	"Error mask",	error)
336			<< TestLog::EndImageSet;
337	}
338	else
339	{
340		log << TestLog::ImageSet("Verification result", "Result of rendering")
341			<< TestLog::Image("Result", "Result", image)
342			<< TestLog::EndImageSet;
343	}
344
345	if (isOk)
346		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
347	else
348		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result image invalid");
349}
350
351VertexIDCase::IterateResult VertexIDCase::iterate (void)
352{
353	const GLuint			drawCount			= 6;
354	const GLuint			baseVertex			= 4;
355	const GLuint			coordLocation		= m_gl.getAttribLocation(m_program->getProgram(), "a_position");
356	const GLuint			colorLocation		= m_gl.getUniformLocation(m_program->getProgram(), "u_colors[0]");
357
358	tcu::Surface			surface(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
359
360	const GLfloat coords[] =
361	{
362		// full viewport quad
363		-1.0f, -1.0f,
364		+1.0f, -1.0f,
365		+1.0f, +1.0f,
366		-1.0f, +1.0f,
367
368		// half viewport quad centred
369		-0.5f, -0.5f,
370		+0.5f, -0.5f,
371		+0.5f, +0.5f,
372		-0.5f, +0.5f,
373	};
374
375	const GLushort indices[] =
376	{
377		0, 1, 2, 2, 3, 0,
378	};
379
380	const GLfloat colors[] =
381	{
382		0.0f, 0.0f, 0.0f, 1.0f,
383		0.5f, 1.0f, 0.5f, 1.0f,
384		0.0f, 0.5f, 1.0f, 1.0f,
385		0.0f, 1.0f, 0.0f, 1.0f,
386
387		0.0f, 0.0f, 1.0f, 1.0f, // blue
388		0.0f, 0.0f, 1.0f, 1.0f, // blue
389		0.0f, 0.0f, 1.0f, 1.0f, // blue
390		0.0f, 0.0f, 1.0f, 1.0f, // blue
391	};
392
393	GLU_CHECK_GLW_CALL(m_gl, viewport(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT));
394	GLU_CHECK_GLW_CALL(m_gl, clearColor(1.0f, 1.0f, 1.0f, 1.0f)); // white
395	GLU_CHECK_GLW_CALL(m_gl, clear(GL_COLOR_BUFFER_BIT));
396
397	GLU_CHECK_GLW_CALL(m_gl, uniform4fv(colorLocation, DE_LENGTH_OF_ARRAY(colors), &colors[0]));
398
399	GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer));
400	GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW));
401	GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(coordLocation));
402	GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL));
403
404	if (m_iterNdx == 0)
405	{
406		tcu::ScopedLogSection	logSection	(m_testCtx.getLog(), "Iter0", "Indices in client-side array");
407		draw(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, (GLvoid*)indices, baseVertex);
408	}
409
410	if (m_iterNdx == 1)
411	{
412		tcu::ScopedLogSection	logSection	(m_testCtx.getLog(), "Iter1", "Indices in element array buffer");
413		GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementsBuffer));
414		GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)sizeof(indices), &indices[0], GL_STATIC_DRAW));
415		draw(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, DE_NULL, baseVertex);
416	}
417
418	glu::readPixels(m_context.getRenderContext(), 0, 0, surface.getAccess());
419	verifyImage(surface);
420
421	m_iterNdx += 1;
422
423	return (m_iterNdx < 2) ? CONTINUE : STOP;
424}
425
426class BuiltInVariableGroup : public TestCaseGroup
427{
428public:
429									BuiltInVariableGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
430									~BuiltInVariableGroup		(void);
431
432	void							init						(void);
433
434private:
435	gls::DrawTestSpec::DrawMethod	m_method;
436};
437
438BuiltInVariableGroup::BuiltInVariableGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
439	: TestCaseGroup		(context, name, descr)
440	, m_method			(drawMethod)
441{
442}
443
444BuiltInVariableGroup::~BuiltInVariableGroup (void)
445{
446}
447
448void BuiltInVariableGroup::init (void)
449{
450	addChild(new VertexIDCase(m_context, m_method));
451}
452
453class IndexGroup : public TestCaseGroup
454{
455public:
456									IndexGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
457									~IndexGroup		(void);
458
459	void							init			(void);
460
461private:
462	gls::DrawTestSpec::DrawMethod	m_method;
463};
464
465IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
466	: TestCaseGroup		(context, name, descr)
467	, m_method			(drawMethod)
468{
469}
470
471IndexGroup::~IndexGroup (void)
472{
473}
474
475void IndexGroup::init (void)
476{
477	struct IndexTest
478	{
479		gls::DrawTestSpec::IndexType	type;
480		int								offsets[3];
481	};
482
483	const IndexTest tests[] =
484	{
485		{ gls::DrawTestSpec::INDEXTYPE_BYTE,	{ 0, 1, -1 } },
486		{ gls::DrawTestSpec::INDEXTYPE_SHORT,	{ 0, 2, -1 } },
487		{ gls::DrawTestSpec::INDEXTYPE_INT,		{ 0, 4, -1 } },
488	};
489
490	gls::DrawTestSpec spec;
491	genBasicSpec(spec, m_method);
492
493	spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER;
494
495	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
496	{
497		const IndexTest&	indexTest	= tests[testNdx];
498
499		const std::string	name		= std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
500		const std::string	desc		= std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
501		gls::DrawTest*		test		= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
502
503		spec.indexType			= indexTest.type;
504
505		for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
506		{
507			const std::string iterationDesc = std::string("first vertex ") + de::toString(indexTest.offsets[iterationNdx] / gls::DrawTestSpec::indexTypeSize(indexTest.type));
508			spec.indexPointerOffset	= indexTest.offsets[iterationNdx];
509			test->addIteration(spec, iterationDesc.c_str());
510		}
511
512		addChild(test);
513	}
514}
515
516class BaseVertexGroup : public TestCaseGroup
517{
518public:
519									BaseVertexGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
520									~BaseVertexGroup	(void);
521
522	void							init				(void);
523
524private:
525	gls::DrawTestSpec::DrawMethod	m_method;
526};
527
528BaseVertexGroup::BaseVertexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
529	: TestCaseGroup		(context, name, descr)
530	, m_method			(drawMethod)
531{
532}
533
534BaseVertexGroup::~BaseVertexGroup (void)
535{
536}
537
538void BaseVertexGroup::init (void)
539{
540	struct IndexTest
541	{
542		bool							positiveBase;
543		gls::DrawTestSpec::IndexType	type;
544		int								baseVertex[2];
545	};
546
547	const IndexTest tests[] =
548	{
549		{ true,  gls::DrawTestSpec::INDEXTYPE_BYTE,		{  1,  2 } },
550		{ true,  gls::DrawTestSpec::INDEXTYPE_SHORT,	{  1,  2 } },
551		{ true,  gls::DrawTestSpec::INDEXTYPE_INT,		{  1,  2 } },
552		{ false, gls::DrawTestSpec::INDEXTYPE_BYTE,		{ -1, -2 } },
553		{ false, gls::DrawTestSpec::INDEXTYPE_SHORT,	{ -1, -2 } },
554		{ false, gls::DrawTestSpec::INDEXTYPE_INT,		{ -1, -2 } },
555	};
556
557	gls::DrawTestSpec spec;
558	genBasicSpec(spec, m_method);
559
560	spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER;
561
562	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
563	{
564		const IndexTest&	indexTest	= tests[testNdx];
565
566		const std::string	name		= std::string("index_") + (indexTest.positiveBase ? "" : "neg_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
567		const std::string	desc		= std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
568		gls::DrawTest*		test		= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
569
570		spec.indexType			= indexTest.type;
571
572		for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.baseVertex); ++iterationNdx)
573		{
574			const std::string iterationDesc = std::string("base vertex ") + de::toString(indexTest.baseVertex[iterationNdx]);
575			spec.baseVertex	= indexTest.baseVertex[iterationNdx];
576			test->addIteration(spec, iterationDesc.c_str());
577		}
578
579		addChild(test);
580	}
581}
582
583class AttributeGroup : public TestCaseGroup
584{
585public:
586									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);
587									~AttributeGroup	(void);
588
589	void							init			(void);
590
591private:
592	gls::DrawTestSpec::DrawMethod	m_method;
593	gls::DrawTestSpec::Primitive	m_primitive;
594	gls::DrawTestSpec::IndexType	m_indexType;
595	gls::DrawTestSpec::Storage		m_indexStorage;
596};
597
598AttributeGroup::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)
599	: TestCaseGroup		(context, name, descr)
600	, m_method			(drawMethod)
601	, m_primitive		(primitive)
602	, m_indexType		(indexType)
603	, m_indexStorage	(indexStorage)
604{
605}
606
607AttributeGroup::~AttributeGroup (void)
608{
609}
610
611void AttributeGroup::init (void)
612{
613	// Single attribute
614	{
615		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
616		gls::DrawTestSpec	spec;
617
618		spec.apiType							= glu::ApiType::es(3,1);
619		spec.primitive							= m_primitive;
620		spec.primitiveCount						= 5;
621		spec.drawMethod							= m_method;
622		spec.indexType							= m_indexType;
623		spec.indexPointerOffset					= 0;
624		spec.indexStorage						= m_indexStorage;
625		spec.first								= 0;
626		spec.indexMin							= 0;
627		spec.indexMax							= 0;
628		spec.instanceCount						= 1;
629		spec.indirectOffset						= 0;
630
631		spec.attribs.resize(1);
632
633		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
634		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
635		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
636		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
637		spec.attribs[0].componentCount			= 2;
638		spec.attribs[0].offset					= 0;
639		spec.attribs[0].stride					= 0;
640		spec.attribs[0].normalize				= false;
641		spec.attribs[0].instanceDivisor			= 0;
642		spec.attribs[0].useDefaultAttribute		= false;
643
644		addTestIterations(test, spec, TYPE_DRAW_COUNT);
645
646		this->addChild(test);
647	}
648
649	// Multiple attribute
650	{
651		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays.");
652		gls::DrawTestSpec	spec;
653
654		spec.apiType							= glu::ApiType::es(3,1);
655		spec.primitive							= m_primitive;
656		spec.primitiveCount						= 5;
657		spec.drawMethod							= m_method;
658		spec.indexType							= m_indexType;
659		spec.indexPointerOffset					= 0;
660		spec.indexStorage						= m_indexStorage;
661		spec.first								= 0;
662		spec.indexMin							= 0;
663		spec.indexMax							= 0;
664		spec.instanceCount						= 1;
665		spec.indirectOffset						= 0;
666
667		spec.attribs.resize(2);
668
669		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
670		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
671		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
672		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
673		spec.attribs[0].componentCount			= 4;
674		spec.attribs[0].offset					= 0;
675		spec.attribs[0].stride					= 0;
676		spec.attribs[0].normalize				= false;
677		spec.attribs[0].instanceDivisor			= 0;
678		spec.attribs[0].useDefaultAttribute		= false;
679
680		spec.attribs[1].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
681		spec.attribs[1].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
682		spec.attribs[1].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
683		spec.attribs[1].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
684		spec.attribs[1].componentCount			= 2;
685		spec.attribs[1].offset					= 0;
686		spec.attribs[1].stride					= 0;
687		spec.attribs[1].normalize				= false;
688		spec.attribs[1].instanceDivisor			= 0;
689		spec.attribs[1].useDefaultAttribute		= false;
690
691		addTestIterations(test, spec, TYPE_DRAW_COUNT);
692
693		this->addChild(test);
694	}
695
696	// Multiple attribute, second one divided
697	{
698		gls::DrawTest*		test					= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "instanced_attributes", "Instanced attribute array.");
699		gls::DrawTestSpec	spec;
700
701		spec.apiType								= glu::ApiType::es(3,1);
702		spec.primitive								= m_primitive;
703		spec.primitiveCount							= 5;
704		spec.drawMethod								= m_method;
705		spec.indexType								= m_indexType;
706		spec.indexPointerOffset						= 0;
707		spec.indexStorage							= m_indexStorage;
708		spec.first									= 0;
709		spec.indexMin								= 0;
710		spec.indexMax								= 0;
711		spec.instanceCount							= 1;
712		spec.indirectOffset							= 0;
713
714		spec.attribs.resize(3);
715
716		spec.attribs[0].inputType					= gls::DrawTestSpec::INPUTTYPE_FLOAT;
717		spec.attribs[0].outputType					= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
718		spec.attribs[0].storage						= gls::DrawTestSpec::STORAGE_BUFFER;
719		spec.attribs[0].usage						= gls::DrawTestSpec::USAGE_STATIC_DRAW;
720		spec.attribs[0].componentCount				= 4;
721		spec.attribs[0].offset						= 0;
722		spec.attribs[0].stride						= 0;
723		spec.attribs[0].normalize					= false;
724		spec.attribs[0].instanceDivisor				= 0;
725		spec.attribs[0].useDefaultAttribute			= false;
726
727		// Add another position component so the instances wont be drawn on each other
728		spec.attribs[1].inputType					= gls::DrawTestSpec::INPUTTYPE_FLOAT;
729		spec.attribs[1].outputType					= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
730		spec.attribs[1].storage						= gls::DrawTestSpec::STORAGE_BUFFER;
731		spec.attribs[1].usage						= gls::DrawTestSpec::USAGE_STATIC_DRAW;
732		spec.attribs[1].componentCount				= 2;
733		spec.attribs[1].offset						= 0;
734		spec.attribs[1].stride						= 0;
735		spec.attribs[1].normalize					= false;
736		spec.attribs[1].instanceDivisor				= 1;
737		spec.attribs[1].useDefaultAttribute			= false;
738		spec.attribs[1].additionalPositionAttribute	= true;
739
740		// Instanced color
741		spec.attribs[2].inputType					= gls::DrawTestSpec::INPUTTYPE_FLOAT;
742		spec.attribs[2].outputType					= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
743		spec.attribs[2].storage						= gls::DrawTestSpec::STORAGE_BUFFER;
744		spec.attribs[2].usage						= gls::DrawTestSpec::USAGE_STATIC_DRAW;
745		spec.attribs[2].componentCount				= 3;
746		spec.attribs[2].offset						= 0;
747		spec.attribs[2].stride						= 0;
748		spec.attribs[2].normalize					= false;
749		spec.attribs[2].instanceDivisor				= 1;
750		spec.attribs[2].useDefaultAttribute			= false;
751
752		addTestIterations(test, spec, TYPE_INSTANCE_COUNT);
753
754		this->addChild(test);
755	}
756
757	// Multiple attribute, second one default
758	{
759		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*.");
760		gls::DrawTestSpec	spec;
761
762		spec.apiType							= glu::ApiType::es(3,1);
763		spec.primitive							= m_primitive;
764		spec.primitiveCount						= 5;
765		spec.drawMethod							= m_method;
766		spec.indexType							= m_indexType;
767		spec.indexPointerOffset					= 0;
768		spec.indexStorage						= m_indexStorage;
769		spec.first								= 0;
770		spec.indexMin							= 0;
771		spec.indexMax							= 0;
772		spec.instanceCount						= 1;
773		spec.indirectOffset						= 0;
774
775		spec.attribs.resize(2);
776
777		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
778		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
779		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
780		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
781		spec.attribs[0].componentCount			= 2;
782		spec.attribs[0].offset					= 0;
783		spec.attribs[0].stride					= 0;
784		spec.attribs[0].normalize				= false;
785		spec.attribs[0].instanceDivisor			= 0;
786		spec.attribs[0].useDefaultAttribute		= false;
787
788		struct IOPair
789		{
790			gls::DrawTestSpec::InputType  input;
791			gls::DrawTestSpec::OutputType output;
792			int							  componentCount;
793		} iopairs[] =
794		{
795			{ gls::DrawTestSpec::INPUTTYPE_FLOAT,		 gls::DrawTestSpec::OUTPUTTYPE_VEC2,  4 },
796			{ gls::DrawTestSpec::INPUTTYPE_FLOAT,		 gls::DrawTestSpec::OUTPUTTYPE_VEC4,  2 },
797			{ gls::DrawTestSpec::INPUTTYPE_INT,			 gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 4 },
798			{ gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 4 },
799		};
800
801		for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
802		{
803			const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
804
805			spec.attribs[1].inputType			= iopairs[ioNdx].input;
806			spec.attribs[1].outputType			= iopairs[ioNdx].output;
807			spec.attribs[1].storage				= gls::DrawTestSpec::STORAGE_BUFFER;
808			spec.attribs[1].usage				= gls::DrawTestSpec::USAGE_STATIC_DRAW;
809			spec.attribs[1].componentCount		= iopairs[ioNdx].componentCount;
810			spec.attribs[1].offset				= 0;
811			spec.attribs[1].stride				= 0;
812			spec.attribs[1].normalize			= false;
813			spec.attribs[1].instanceDivisor		= 0;
814			spec.attribs[1].useDefaultAttribute	= true;
815
816			test->addIteration(spec, desc.c_str());
817		}
818
819		this->addChild(test);
820	}
821}
822
823class MethodGroup : public TestCaseGroup
824{
825public:
826									MethodGroup			(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
827									~MethodGroup		(void);
828
829	void							init				(void);
830
831private:
832	gls::DrawTestSpec::DrawMethod	m_method;
833};
834
835MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
836	: TestCaseGroup		(context, name, descr)
837	, m_method			(drawMethod)
838{
839}
840
841MethodGroup::~MethodGroup (void)
842{
843}
844
845void MethodGroup::init (void)
846{
847	const bool indexed		=	(m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX)
848							||	(m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
849							||	(m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX);
850
851	const gls::DrawTestSpec::Primitive primitive[] =
852	{
853		gls::DrawTestSpec::PRIMITIVE_POINTS,
854		gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
855		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
856		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
857		gls::DrawTestSpec::PRIMITIVE_LINES,
858		gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
859		gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
860	};
861
862	if (indexed)
863	{
864		// Index-tests
865		this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
866		this->addChild(new BaseVertexGroup(m_context, "base_vertex", "Base vertex tests", m_method));
867		this->addChild(new BuiltInVariableGroup(m_context, "builtin_variable", "Built in shader variable tests", m_method));
868	}
869
870	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
871	{
872		const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
873		const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
874
875		this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
876	}
877}
878
879} // anonymous
880
881DrawElementsBaseVertexTests::DrawElementsBaseVertexTests (Context& context)
882	: TestCaseGroup(context, "draw_base_vertex", "Base vertex extension drawing tests")
883{
884}
885
886DrawElementsBaseVertexTests::~DrawElementsBaseVertexTests (void)
887{
888}
889
890void DrawElementsBaseVertexTests::init (void)
891{
892	const gls::DrawTestSpec::DrawMethod basicMethods[] =
893	{
894		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX,
895		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX,
896		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX,
897	};
898
899	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
900	{
901		const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
902		const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
903
904		this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
905	}
906}
907
908} // Functional
909} // gles31
910} // deqp
911