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