• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
41 using std::vector;
42 using std::string;
43 using tcu::TestLog;
44 
45 using namespace glw;
46 
47 namespace deqp
48 {
49 namespace gles31
50 {
51 namespace Functional
52 {
53 namespace
54 {
55 
56 enum 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 
getElementCount(gls::DrawTestSpec::Primitive primitive,size_t primitiveCount)64 static 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 
addRangeElementsToSpec(gls::DrawTestSpec & spec)85 static 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 
addTestIterations(gls::DrawTest * test,gls::DrawTestSpec & spec,TestIterationType type)94 static 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 
genBasicSpec(gls::DrawTestSpec & spec,gls::DrawTestSpec::DrawMethod method)128 static 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 
170 class VertexIDCase : public TestCase
171 {
172 public:
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 
183 private:
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 
VertexIDCase(Context & context,gls::DrawTestSpec::DrawMethod drawMethod)203 VertexIDCase::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 
~VertexIDCase(void)214 VertexIDCase::~VertexIDCase (void)
215 {
216 	VertexIDCase::deinit();
217 }
218 
init(void)219 void 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 
deinit(void)260 void 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 
draw(GLenum mode,GLsizei count,GLenum type,GLvoid * indices,GLint baseVertex)278 void 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 
verifyImage(const tcu::Surface & image)303 void 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 
iterate(void)351 VertexIDCase::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 
426 class BuiltInVariableGroup : public TestCaseGroup
427 {
428 public:
429 									BuiltInVariableGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
430 									~BuiltInVariableGroup		(void);
431 
432 	void							init						(void);
433 
434 private:
435 	gls::DrawTestSpec::DrawMethod	m_method;
436 };
437 
BuiltInVariableGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)438 BuiltInVariableGroup::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 
~BuiltInVariableGroup(void)444 BuiltInVariableGroup::~BuiltInVariableGroup (void)
445 {
446 }
447 
init(void)448 void BuiltInVariableGroup::init (void)
449 {
450 	addChild(new VertexIDCase(m_context, m_method));
451 }
452 
453 class IndexGroup : public TestCaseGroup
454 {
455 public:
456 									IndexGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
457 									~IndexGroup		(void);
458 
459 	void							init			(void);
460 
461 private:
462 	gls::DrawTestSpec::DrawMethod	m_method;
463 };
464 
IndexGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)465 IndexGroup::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 
~IndexGroup(void)471 IndexGroup::~IndexGroup (void)
472 {
473 }
474 
init(void)475 void 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 
516 class BaseVertexGroup : public TestCaseGroup
517 {
518 public:
519 									BaseVertexGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
520 									~BaseVertexGroup	(void);
521 
522 	void							init				(void);
523 
524 private:
525 	gls::DrawTestSpec::DrawMethod	m_method;
526 };
527 
BaseVertexGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)528 BaseVertexGroup::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 
~BaseVertexGroup(void)534 BaseVertexGroup::~BaseVertexGroup (void)
535 {
536 }
537 
init(void)538 void 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 			// spec.indexMin + spec.baseVertex can not be a negative value
577 			if (spec.indexMin + spec.baseVertex < 0)
578 			{
579 				spec.indexMax -= (spec.indexMin + spec.baseVertex);
580 				spec.indexMin -= (spec.indexMin + spec.baseVertex);
581 			}
582 			test->addIteration(spec, iterationDesc.c_str());
583 		}
584 
585 		addChild(test);
586 	}
587 }
588 
589 class AttributeGroup : public TestCaseGroup
590 {
591 public:
592 									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);
593 									~AttributeGroup	(void);
594 
595 	void							init			(void);
596 
597 private:
598 	gls::DrawTestSpec::DrawMethod	m_method;
599 	gls::DrawTestSpec::Primitive	m_primitive;
600 	gls::DrawTestSpec::IndexType	m_indexType;
601 	gls::DrawTestSpec::Storage		m_indexStorage;
602 };
603 
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)604 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)
605 	: TestCaseGroup		(context, name, descr)
606 	, m_method			(drawMethod)
607 	, m_primitive		(primitive)
608 	, m_indexType		(indexType)
609 	, m_indexStorage	(indexStorage)
610 {
611 }
612 
~AttributeGroup(void)613 AttributeGroup::~AttributeGroup (void)
614 {
615 }
616 
init(void)617 void AttributeGroup::init (void)
618 {
619 	// Single attribute
620 	{
621 		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
622 		gls::DrawTestSpec	spec;
623 
624 		spec.apiType							= glu::ApiType::es(3,1);
625 		spec.primitive							= m_primitive;
626 		spec.primitiveCount						= 5;
627 		spec.drawMethod							= m_method;
628 		spec.indexType							= m_indexType;
629 		spec.indexPointerOffset					= 0;
630 		spec.indexStorage						= m_indexStorage;
631 		spec.first								= 0;
632 		spec.indexMin							= 0;
633 		spec.indexMax							= 0;
634 		spec.instanceCount						= 1;
635 		spec.indirectOffset						= 0;
636 
637 		spec.attribs.resize(1);
638 
639 		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
640 		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
641 		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
642 		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
643 		spec.attribs[0].componentCount			= 2;
644 		spec.attribs[0].offset					= 0;
645 		spec.attribs[0].stride					= 0;
646 		spec.attribs[0].normalize				= false;
647 		spec.attribs[0].instanceDivisor			= 0;
648 		spec.attribs[0].useDefaultAttribute		= false;
649 
650 		addTestIterations(test, spec, TYPE_DRAW_COUNT);
651 
652 		this->addChild(test);
653 	}
654 
655 	// Multiple attribute
656 	{
657 		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays.");
658 		gls::DrawTestSpec	spec;
659 
660 		spec.apiType							= glu::ApiType::es(3,1);
661 		spec.primitive							= m_primitive;
662 		spec.primitiveCount						= 5;
663 		spec.drawMethod							= m_method;
664 		spec.indexType							= m_indexType;
665 		spec.indexPointerOffset					= 0;
666 		spec.indexStorage						= m_indexStorage;
667 		spec.first								= 0;
668 		spec.indexMin							= 0;
669 		spec.indexMax							= 0;
670 		spec.instanceCount						= 1;
671 		spec.indirectOffset						= 0;
672 
673 		spec.attribs.resize(2);
674 
675 		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
676 		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
677 		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
678 		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
679 		spec.attribs[0].componentCount			= 4;
680 		spec.attribs[0].offset					= 0;
681 		spec.attribs[0].stride					= 0;
682 		spec.attribs[0].normalize				= false;
683 		spec.attribs[0].instanceDivisor			= 0;
684 		spec.attribs[0].useDefaultAttribute		= false;
685 
686 		spec.attribs[1].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
687 		spec.attribs[1].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
688 		spec.attribs[1].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
689 		spec.attribs[1].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
690 		spec.attribs[1].componentCount			= 2;
691 		spec.attribs[1].offset					= 0;
692 		spec.attribs[1].stride					= 0;
693 		spec.attribs[1].normalize				= false;
694 		spec.attribs[1].instanceDivisor			= 0;
695 		spec.attribs[1].useDefaultAttribute		= false;
696 
697 		addTestIterations(test, spec, TYPE_DRAW_COUNT);
698 
699 		this->addChild(test);
700 	}
701 
702 	// Multiple attribute, second one divided
703 	{
704 		gls::DrawTest*		test					= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "instanced_attributes", "Instanced attribute array.");
705 		gls::DrawTestSpec	spec;
706 
707 		spec.apiType								= glu::ApiType::es(3,1);
708 		spec.primitive								= m_primitive;
709 		spec.primitiveCount							= 5;
710 		spec.drawMethod								= m_method;
711 		spec.indexType								= m_indexType;
712 		spec.indexPointerOffset						= 0;
713 		spec.indexStorage							= m_indexStorage;
714 		spec.first									= 0;
715 		spec.indexMin								= 0;
716 		spec.indexMax								= 0;
717 		spec.instanceCount							= 1;
718 		spec.indirectOffset							= 0;
719 
720 		spec.attribs.resize(3);
721 
722 		spec.attribs[0].inputType					= gls::DrawTestSpec::INPUTTYPE_FLOAT;
723 		spec.attribs[0].outputType					= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
724 		spec.attribs[0].storage						= gls::DrawTestSpec::STORAGE_BUFFER;
725 		spec.attribs[0].usage						= gls::DrawTestSpec::USAGE_STATIC_DRAW;
726 		spec.attribs[0].componentCount				= 4;
727 		spec.attribs[0].offset						= 0;
728 		spec.attribs[0].stride						= 0;
729 		spec.attribs[0].normalize					= false;
730 		spec.attribs[0].instanceDivisor				= 0;
731 		spec.attribs[0].useDefaultAttribute			= false;
732 
733 		// Add another position component so the instances wont be drawn on each other
734 		spec.attribs[1].inputType					= gls::DrawTestSpec::INPUTTYPE_FLOAT;
735 		spec.attribs[1].outputType					= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
736 		spec.attribs[1].storage						= gls::DrawTestSpec::STORAGE_BUFFER;
737 		spec.attribs[1].usage						= gls::DrawTestSpec::USAGE_STATIC_DRAW;
738 		spec.attribs[1].componentCount				= 2;
739 		spec.attribs[1].offset						= 0;
740 		spec.attribs[1].stride						= 0;
741 		spec.attribs[1].normalize					= false;
742 		spec.attribs[1].instanceDivisor				= 1;
743 		spec.attribs[1].useDefaultAttribute			= false;
744 		spec.attribs[1].additionalPositionAttribute	= true;
745 
746 		// Instanced color
747 		spec.attribs[2].inputType					= gls::DrawTestSpec::INPUTTYPE_FLOAT;
748 		spec.attribs[2].outputType					= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
749 		spec.attribs[2].storage						= gls::DrawTestSpec::STORAGE_BUFFER;
750 		spec.attribs[2].usage						= gls::DrawTestSpec::USAGE_STATIC_DRAW;
751 		spec.attribs[2].componentCount				= 3;
752 		spec.attribs[2].offset						= 0;
753 		spec.attribs[2].stride						= 0;
754 		spec.attribs[2].normalize					= false;
755 		spec.attribs[2].instanceDivisor				= 1;
756 		spec.attribs[2].useDefaultAttribute			= false;
757 
758 		addTestIterations(test, spec, TYPE_INSTANCE_COUNT);
759 
760 		this->addChild(test);
761 	}
762 
763 	// Multiple attribute, second one default
764 	{
765 		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*.");
766 		gls::DrawTestSpec	spec;
767 
768 		spec.apiType							= glu::ApiType::es(3,1);
769 		spec.primitive							= m_primitive;
770 		spec.primitiveCount						= 5;
771 		spec.drawMethod							= m_method;
772 		spec.indexType							= m_indexType;
773 		spec.indexPointerOffset					= 0;
774 		spec.indexStorage						= m_indexStorage;
775 		spec.first								= 0;
776 		spec.indexMin							= 0;
777 		spec.indexMax							= 0;
778 		spec.instanceCount						= 1;
779 		spec.indirectOffset						= 0;
780 
781 		spec.attribs.resize(2);
782 
783 		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
784 		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
785 		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
786 		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
787 		spec.attribs[0].componentCount			= 2;
788 		spec.attribs[0].offset					= 0;
789 		spec.attribs[0].stride					= 0;
790 		spec.attribs[0].normalize				= false;
791 		spec.attribs[0].instanceDivisor			= 0;
792 		spec.attribs[0].useDefaultAttribute		= false;
793 
794 		struct IOPair
795 		{
796 			gls::DrawTestSpec::InputType  input;
797 			gls::DrawTestSpec::OutputType output;
798 			int							  componentCount;
799 		} iopairs[] =
800 		{
801 			{ gls::DrawTestSpec::INPUTTYPE_FLOAT,		 gls::DrawTestSpec::OUTPUTTYPE_VEC2,  4 },
802 			{ gls::DrawTestSpec::INPUTTYPE_FLOAT,		 gls::DrawTestSpec::OUTPUTTYPE_VEC4,  2 },
803 			{ gls::DrawTestSpec::INPUTTYPE_INT,			 gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 4 },
804 			{ gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 4 },
805 		};
806 
807 		for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
808 		{
809 			const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
810 
811 			spec.attribs[1].inputType			= iopairs[ioNdx].input;
812 			spec.attribs[1].outputType			= iopairs[ioNdx].output;
813 			spec.attribs[1].storage				= gls::DrawTestSpec::STORAGE_BUFFER;
814 			spec.attribs[1].usage				= gls::DrawTestSpec::USAGE_STATIC_DRAW;
815 			spec.attribs[1].componentCount		= iopairs[ioNdx].componentCount;
816 			spec.attribs[1].offset				= 0;
817 			spec.attribs[1].stride				= 0;
818 			spec.attribs[1].normalize			= false;
819 			spec.attribs[1].instanceDivisor		= 0;
820 			spec.attribs[1].useDefaultAttribute	= true;
821 
822 			test->addIteration(spec, desc.c_str());
823 		}
824 
825 		this->addChild(test);
826 	}
827 }
828 
829 class MethodGroup : public TestCaseGroup
830 {
831 public:
832 									MethodGroup			(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
833 									~MethodGroup		(void);
834 
835 	void							init				(void);
836 
837 private:
838 	gls::DrawTestSpec::DrawMethod	m_method;
839 };
840 
MethodGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)841 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
842 	: TestCaseGroup		(context, name, descr)
843 	, m_method			(drawMethod)
844 {
845 }
846 
~MethodGroup(void)847 MethodGroup::~MethodGroup (void)
848 {
849 }
850 
init(void)851 void MethodGroup::init (void)
852 {
853 	const bool indexed		=	(m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX)
854 							||	(m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
855 							||	(m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX);
856 
857 	const gls::DrawTestSpec::Primitive primitive[] =
858 	{
859 		gls::DrawTestSpec::PRIMITIVE_POINTS,
860 		gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
861 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
862 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
863 		gls::DrawTestSpec::PRIMITIVE_LINES,
864 		gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
865 		gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
866 	};
867 
868 	if (indexed)
869 	{
870 		// Index-tests
871 		this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
872 		this->addChild(new BaseVertexGroup(m_context, "base_vertex", "Base vertex tests", m_method));
873 		this->addChild(new BuiltInVariableGroup(m_context, "builtin_variable", "Built in shader variable tests", m_method));
874 	}
875 
876 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
877 	{
878 		const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
879 		const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
880 
881 		this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
882 	}
883 }
884 
885 } // anonymous
886 
DrawElementsBaseVertexTests(Context & context)887 DrawElementsBaseVertexTests::DrawElementsBaseVertexTests (Context& context)
888 	: TestCaseGroup(context, "draw_base_vertex", "Base vertex extension drawing tests")
889 {
890 }
891 
~DrawElementsBaseVertexTests(void)892 DrawElementsBaseVertexTests::~DrawElementsBaseVertexTests (void)
893 {
894 }
895 
init(void)896 void DrawElementsBaseVertexTests::init (void)
897 {
898 	const gls::DrawTestSpec::DrawMethod basicMethods[] =
899 	{
900 		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX,
901 		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX,
902 		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX,
903 	};
904 
905 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
906 	{
907 		const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
908 		const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
909 
910 		this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
911 	}
912 }
913 
914 } // Functional
915 } // gles31
916 } // deqp
917