• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Vertex array object tests
22  *//*--------------------------------------------------------------------*/
23 #include "es3fVertexArrayObjectTests.hpp"
24 
25 #include "gluShaderProgram.hpp"
26 #include "gluPixelTransfer.hpp"
27 #include "gluRenderContext.hpp"
28 
29 #include "tcuTestLog.hpp"
30 #include "tcuImageCompare.hpp"
31 #include "tcuSurface.hpp"
32 #include "tcuRenderTarget.hpp"
33 
34 #include "deRandom.hpp"
35 #include "deString.h"
36 #include "deMemory.h"
37 
38 #include <vector>
39 #include <string>
40 #include <memory>
41 
42 #include "glw.h"
43 
44 using std::vector;
45 using std::string;
46 
47 namespace deqp
48 {
49 namespace gles3
50 {
51 namespace Functional
52 {
53 
54 namespace
55 {
56 struct Attribute
57 {
58 				Attribute (void);
59 	GLboolean	enabled;
60 	GLint		size;
61 	GLint		stride;
62 	GLenum		type;
63 	GLboolean	integer;
64 	GLint		divisor;
65 	GLint		offset;
66 	GLboolean	normalized;
67 
68 	int			bufferNdx;
69 };
70 
71 struct VertexArrayState
72 {
73 						VertexArrayState	(void);
74 
75 	vector<Attribute>	attributes;
76 	int					elementArrayBuffer;
77 };
78 
VertexArrayState(void)79 VertexArrayState::VertexArrayState (void)
80 	: elementArrayBuffer(-1)
81 {
82 }
83 
Attribute(void)84 Attribute::Attribute (void)
85 	: enabled		(GL_FALSE)
86 	, size			(1)
87 	, stride		(0)
88 	, type			(GL_FLOAT)
89 	, integer		(GL_FALSE)
90 	, divisor		(0)
91 	, offset		(0)
92 	, normalized	(GL_FALSE)
93 	, bufferNdx		(0)
94 {
95 }
96 
97 struct BufferSpec
98 {
99 	int		count;
100 	int		size;
101 	int		componentCount;
102 	int		stride;
103 	int		offset;
104 
105 	GLenum	type;
106 
107 	int		intRangeMin;
108 	int		intRangeMax;
109 
110 	float	floatRangeMin;
111 	float	floatRangeMax;
112 };
113 
114 struct Spec
115 {
116 						Spec	(void);
117 
118 	int					count;
119 	int					instances;
120 	bool				useDrawElements;
121 	GLenum				indexType;
122 	int					indexOffset;
123 	int					indexRangeMin;
124 	int					indexRangeMax;
125 	int					indexCount;
126 	VertexArrayState	state;
127 	VertexArrayState	vao;
128 	vector<BufferSpec>	buffers;
129 };
130 
Spec(void)131 Spec::Spec (void)
132 	: count				(-1)
133 	, instances			(-1)
134 	, useDrawElements	(false)
135 	, indexType			(GL_NONE)
136 	, indexOffset		(-1)
137 	, indexRangeMin		(-1)
138 	, indexRangeMax		(-1)
139 	, indexCount		(-1)
140 {
141 }
142 
143 } // anonymous
144 
145 class VertexArrayObjectTest : public TestCase
146 {
147 public:
148 
149 							VertexArrayObjectTest	(Context& context, const Spec& spec, const char* name, const char* description);
150 							~VertexArrayObjectTest	(void);
151 	virtual void			init					(void);
152 	virtual void			deinit					(void);
153 	virtual IterateResult	iterate					(void);
154 
155 private:
156 	Spec					m_spec;
157 	tcu::TestLog&			m_log;
158 	vector<GLuint>			m_buffers;
159 	glu::ShaderProgram*		m_vaoProgram;
160 	glu::ShaderProgram*		m_stateProgram;
161 	de::Random				m_random;
162 	deUint8*				m_indices;
163 
164 	void					logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg);
165 	deUint8*				createRandomBufferData	(const BufferSpec& buffer);
166 	deUint8*				generateIndices			(void);
167 	glu::ShaderProgram*		createProgram			(const VertexArrayState& state);
168 	void					setState				(const VertexArrayState& state);
169 	void					render					(tcu::Surface& vaoResult, tcu::Surface& defaultResult);
170 	void					makeDrawCall			(const VertexArrayState& state);
171 	void					genReferences			(tcu::Surface& vaoRef, tcu::Surface& defaultRef);
172 
173 							VertexArrayObjectTest	(const VertexArrayObjectTest&);
174 	VertexArrayObjectTest&	operator=				(const VertexArrayObjectTest&);
175 };
176 
VertexArrayObjectTest(Context & context,const Spec & spec,const char * name,const char * description)177 VertexArrayObjectTest::VertexArrayObjectTest (Context& context, const Spec& spec, const char* name, const char* description)
178 	: TestCase			(context, name, description)
179 	, m_spec			(spec)
180 	, m_log				(context.getTestContext().getLog())
181 	, m_vaoProgram		(NULL)
182 	, m_stateProgram	(NULL)
183 	, m_random			(deStringHash(name))
184 	, m_indices			(NULL)
185 {
186 	// Makes zero to zero mapping for buffers
187 	m_buffers.push_back(0);
188 }
189 
~VertexArrayObjectTest(void)190 VertexArrayObjectTest::~VertexArrayObjectTest (void)
191 {
192 }
193 
logVertexArrayState(tcu::TestLog & log,const VertexArrayState & state,const std::string & msg)194 void VertexArrayObjectTest::logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg)
195 {
196 	std::stringstream message;
197 
198 	message << msg << "\n";
199 	message << "GL_ELEMENT_ARRAY_BUFFER : " << state.elementArrayBuffer << "\n";
200 
201 	for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
202 	{
203 		message
204 		<< "attribute : " << attribNdx << "\n"
205 		<< "\tGL_VERTEX_ATTRIB_ARRAY_ENABLED : " << (state.attributes[attribNdx].enabled ? "GL_TRUE" : "GL_FALSE") <<  "\n"
206 		<< "\tGL_VERTEX_ATTRIB_ARRAY_SIZE : " << state.attributes[attribNdx].size <<  "\n"
207 		<< "\tGL_VERTEX_ATTRIB_ARRAY_STRIDE : " << state.attributes[attribNdx].stride <<  "\n"
208 		<< "\tGL_VERTEX_ATTRIB_ARRAY_TYPE : " << state.attributes[attribNdx].type <<  "\n"
209 		<< "\tGL_VERTEX_ATTRIB_ARRAY_NORMALIZED : " << (state.attributes[attribNdx].normalized ? "GL_TRUE" : "GL_FALSE") <<  "\n"
210 		<< "\tGL_VERTEX_ATTRIB_ARRAY_INTEGER : " << (state.attributes[attribNdx].integer ? "GL_TRUE" : "GL_FALSE") <<  "\n"
211 		<< "\tGL_VERTEX_ATTRIB_ARRAY_DIVISOR : " << state.attributes[attribNdx].divisor <<  "\n"
212 		<< "\tGL_VERTEX_ATTRIB_ARRAY_POINTER : " << state.attributes[attribNdx].offset <<  "\n"
213 		<< "\tGL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : " << m_buffers[state.attributes[attribNdx].bufferNdx] <<  "\n";
214 	}
215 	log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
216 }
217 
218 
init(void)219 void VertexArrayObjectTest::init (void)
220 {
221 	// \note [mika] Index 0 is reserved for 0 buffer
222 	for (int bufferNdx = 0; bufferNdx < (int)m_spec.buffers.size(); bufferNdx++)
223 	{
224 		deUint8* data = createRandomBufferData(m_spec.buffers[bufferNdx]);
225 
226 		try
227 		{
228 			GLuint buffer;
229 			GLU_CHECK_CALL(glGenBuffers(1, &buffer));
230 			m_buffers.push_back(buffer);
231 
232 			GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, buffer));
233 			GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, m_spec.buffers[bufferNdx].size, data, GL_DYNAMIC_DRAW));
234 			GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
235 
236 		} catch (...) {
237 			delete[] data;
238 			throw;
239 		}
240 
241 		delete[] data;
242 	}
243 
244 	m_vaoProgram	= createProgram(m_spec.vao);
245 	m_log << tcu::TestLog::Message << "Program used with Vertex Array Object" << tcu::TestLog::EndMessage;
246 	m_log << *m_vaoProgram;
247 	m_stateProgram	= createProgram(m_spec.state);
248 	m_log << tcu::TestLog::Message << "Program used with Vertex Array State" << tcu::TestLog::EndMessage;
249 	m_log << *m_stateProgram;
250 
251 	if (!m_vaoProgram->isOk() || !m_stateProgram->isOk())
252 		TCU_FAIL("Failed to compile shaders");
253 
254 	if (m_spec.useDrawElements && (m_spec.vao.elementArrayBuffer == 0 || m_spec.state.elementArrayBuffer == 0))
255 		m_indices = generateIndices();
256 }
257 
deinit(void)258 void VertexArrayObjectTest::deinit (void)
259 {
260 	GLU_CHECK_CALL(glDeleteBuffers((GLsizei)m_buffers.size(), &(m_buffers[0])));
261 	m_buffers.clear();
262 	delete m_vaoProgram;
263 	delete m_stateProgram;
264 	delete[] m_indices;
265 }
266 
generateIndices(void)267 deUint8* VertexArrayObjectTest::generateIndices (void)
268 {
269 	int typeSize = 0;
270 	switch (m_spec.indexType)
271 	{
272 		case GL_UNSIGNED_INT:	typeSize = sizeof(GLuint);		break;
273 		case GL_UNSIGNED_SHORT:	typeSize = sizeof(GLushort);	break;
274 		case GL_UNSIGNED_BYTE:	typeSize = sizeof(GLubyte);		break;
275 		default:
276 			DE_ASSERT(false);
277 	}
278 
279 	deUint8* indices = new deUint8[m_spec.indexCount * typeSize];
280 
281 	for (int i = 0; i < m_spec.indexCount; i++)
282 	{
283 		deUint8* pos = indices + typeSize * i;
284 
285 		switch (m_spec.indexType)
286 		{
287 			case GL_UNSIGNED_INT:
288 			{
289 				GLuint v = (GLuint)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
290 				deMemcpy(pos, &v, sizeof(v));
291 				break;
292 			}
293 
294 			case GL_UNSIGNED_SHORT:
295 			{
296 				GLushort v = (GLushort)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
297 				deMemcpy(pos, &v, sizeof(v));
298 				break;
299 			}
300 
301 			case GL_UNSIGNED_BYTE:
302 			{
303 				GLubyte v = (GLubyte)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
304 				deMemcpy(pos, &v, sizeof(v));
305 				break;
306 			}
307 
308 			default:
309 				DE_ASSERT(false);
310 		}
311 	}
312 
313 	return indices;
314 }
315 
createRandomBufferData(const BufferSpec & buffer)316 deUint8* VertexArrayObjectTest::createRandomBufferData (const BufferSpec& buffer)
317 {
318 	deUint8* data = new deUint8[buffer.size];
319 
320 	int stride;
321 
322 	if (buffer.stride != 0)
323 	{
324 		stride = buffer.stride;
325 	}
326 	else
327 	{
328 		switch (buffer.type)
329 		{
330 			case GL_FLOAT:			stride = buffer.componentCount * (int)sizeof(GLfloat);	break;
331 			case GL_INT:			stride = buffer.componentCount * (int)sizeof(GLint);	break;
332 			case GL_UNSIGNED_INT:	stride = buffer.componentCount * (int)sizeof(GLuint);	break;
333 			case GL_SHORT:			stride = buffer.componentCount * (int)sizeof(GLshort);	break;
334 			case GL_UNSIGNED_SHORT:	stride = buffer.componentCount * (int)sizeof(GLushort);	break;
335 			case GL_BYTE:			stride = buffer.componentCount * (int)sizeof(GLbyte);	break;
336 			case GL_UNSIGNED_BYTE:	stride = buffer.componentCount * (int)sizeof(GLubyte);	break;
337 
338 			default:
339 				stride = 0;
340 				DE_ASSERT(DE_FALSE);
341 		}
342 	}
343 
344 	deUint8* itr = data;
345 
346 	for (int pos = 0; pos < buffer.count; pos++)
347 	{
348 		deUint8* componentItr = itr;
349 		for (int componentNdx = 0; componentNdx < buffer.componentCount; componentNdx++)
350 		{
351 			switch (buffer.type)
352 			{
353 				case GL_FLOAT:
354 				{
355 					float v = buffer.floatRangeMin + (buffer.floatRangeMax - buffer.floatRangeMin) * m_random.getFloat();
356 					deMemcpy(componentItr, &v, sizeof(v));
357 					componentItr += sizeof(v);
358 					break;
359 				}
360 
361 				case GL_INT:
362 				{
363 					GLint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
364 					deMemcpy(componentItr, &v, sizeof(v));
365 					componentItr += sizeof(v);
366 					break;
367 				}
368 
369 				case GL_UNSIGNED_INT:
370 				{
371 					GLuint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
372 					deMemcpy(componentItr, &v, sizeof(v));
373 					componentItr += sizeof(v);
374 					break;
375 				}
376 
377 				case GL_SHORT:
378 				{
379 					GLshort v = (GLshort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
380 					deMemcpy(componentItr, &v, sizeof(v));
381 					componentItr += sizeof(v);
382 					break;
383 				}
384 
385 				case GL_UNSIGNED_SHORT:
386 				{
387 					GLushort v = (GLushort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
388 					deMemcpy(componentItr, &v, sizeof(v));
389 					componentItr += sizeof(v);
390 					break;
391 				}
392 
393 				case GL_BYTE:
394 				{
395 					GLbyte v = (GLbyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
396 					deMemcpy(componentItr, &v, sizeof(v));
397 					componentItr += sizeof(v);
398 					break;
399 				}
400 
401 				case GL_UNSIGNED_BYTE:
402 				{
403 					GLubyte v = (GLubyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
404 					deMemcpy(componentItr, &v, sizeof(v));
405 					componentItr += sizeof(v);
406 					break;
407 				}
408 
409 				default:
410 					DE_ASSERT(false);
411 			}
412 		}
413 
414 		itr += stride;
415 	}
416 
417 	return data;
418 }
419 
createProgram(const VertexArrayState & state)420 glu::ShaderProgram* VertexArrayObjectTest::createProgram (const VertexArrayState& state)
421 {
422 	std::stringstream vertexShaderStream;
423 	std::stringstream value;
424 
425 	vertexShaderStream << "#version 300 es\n";
426 
427 	for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
428 	{
429 		if (state.attributes[attribNdx].integer)
430 			vertexShaderStream << "layout(location = " << attribNdx << ") in mediump ivec4 a_attrib" << attribNdx << ";\n";
431 		else
432 			vertexShaderStream << "layout(location = " << attribNdx << ") in mediump vec4 a_attrib" << attribNdx << ";\n";
433 
434 		if (state.attributes[attribNdx].integer)
435 		{
436 			float scale = 0.0f;
437 
438 			switch (state.attributes[0].type)
439 			{
440 				case GL_SHORT:			scale  = (1.0f/float((1u<<14)-1u));	break;
441 				case GL_UNSIGNED_SHORT:	scale  = (1.0f/float((1u<<15)-1u));	break;
442 				case GL_INT:			scale  = (1.0f/float((1u<<30)-1u));	break;
443 				case GL_UNSIGNED_INT:	scale  = (1.0f/float((1u<<31)-1u));	break;
444 				case GL_BYTE:			scale  = (1.0f/float((1u<<6)-1u));	break;
445 				case GL_UNSIGNED_BYTE:	scale  = (1.0f/float((1u<<7)-1u));	break;
446 
447 				default:
448 					DE_ASSERT(DE_FALSE);
449 			}
450 			value << (attribNdx != 0 ? " + " : "" ) << scale << " * vec4(a_attrib" << attribNdx << ")";
451 		}
452 		else if (state.attributes[attribNdx].type != GL_FLOAT && !state.attributes[attribNdx].normalized)
453 		{
454 			float scale = 0.0f;
455 
456 			switch (state.attributes[0].type)
457 			{
458 				case GL_SHORT:			scale  = (0.5f/float((1u<<14)-1u));	break;
459 				case GL_UNSIGNED_SHORT:	scale  = (0.5f/float((1u<<15)-1u));	break;
460 				case GL_INT:			scale  = (0.5f/float((1u<<30)-1u));	break;
461 				case GL_UNSIGNED_INT:	scale  = (0.5f/float((1u<<31)-1u));	break;
462 				case GL_BYTE:			scale  = (0.5f/float((1u<<6)-1u));	break;
463 				case GL_UNSIGNED_BYTE:	scale  = (0.5f/float((1u<<7)-1u));	break;
464 
465 				default:
466 					DE_ASSERT(DE_FALSE);
467 			}
468 			value << (attribNdx != 0 ? " + " : "" ) << scale << " * a_attrib" << attribNdx;
469 		}
470 		else
471 			value << (attribNdx != 0 ? " + " : "" ) << "a_attrib" << attribNdx;
472 	}
473 
474 	vertexShaderStream
475 		<< "out mediump vec4 v_value;\n"
476 		<< "void main (void)\n"
477 		<< "{\n"
478 		<< "\tv_value = " << value.str() << ";\n";
479 
480 	if (state.attributes[0].integer)
481 	{
482 		float scale = 0.0f;
483 
484 		switch (state.attributes[0].type)
485 		{
486 			case GL_SHORT:			scale  = (1.0f/float((1u<<14)-1u));	break;
487 			case GL_UNSIGNED_SHORT:	scale  = (1.0f/float((1u<<15)-1u));	break;
488 			case GL_INT:			scale  = (1.0f/float((1u<<30)-1u));	break;
489 			case GL_UNSIGNED_INT:	scale  = (1.0f/float((1u<<31)-1u));	break;
490 			case GL_BYTE:			scale  = (1.0f/float((1u<<6)-1u));	break;
491 			case GL_UNSIGNED_BYTE:	scale  = (1.0f/float((1u<<7)-1u));	break;
492 
493 			default:
494 				DE_ASSERT(DE_FALSE);
495 		}
496 
497 		vertexShaderStream
498 			<< "\tgl_Position = vec4(" << scale << " * " <<  "vec3(a_attrib0.xyz), 1.0);\n"
499 			<< "}";
500 	}
501 	else
502 	{
503 		if (state.attributes[0].normalized || state.attributes[0].type == GL_FLOAT)
504 		{
505 			vertexShaderStream
506 				<< "\tgl_Position = vec4(a_attrib0.xyz, 1.0);\n"
507 				<< "}";
508 		}
509 		else
510 		{
511 			float scale = 0.0f;
512 
513 			switch (state.attributes[0].type)
514 			{
515 				case GL_SHORT:			scale  = (1.0f/float((1u<<14)-1u));	break;
516 				case GL_UNSIGNED_SHORT:	scale  = (1.0f/float((1u<<15)-1u));	break;
517 				case GL_INT:			scale  = (1.0f/float((1u<<30)-1u));	break;
518 				case GL_UNSIGNED_INT:	scale  = (1.0f/float((1u<<31)-1u));	break;
519 				case GL_BYTE:			scale  = (1.0f/float((1u<<6)-1u));	break;
520 				case GL_UNSIGNED_BYTE:	scale  = (1.0f/float((1u<<7)-1u));	break;
521 
522 				default:
523 					DE_ASSERT(DE_FALSE);
524 			}
525 
526 			scale *= 0.5f;
527 
528 			vertexShaderStream
529 				<< "\tgl_Position = vec4(" << scale << " * " <<  "a_attrib0.xyz, 1.0);\n"
530 				<< "}";
531 		}
532 	}
533 
534 	const char* fragmentShader =
535 	"#version 300 es\n"
536 	"in mediump vec4 v_value;\n"
537 	"layout(location = 0) out mediump vec4 fragColor;\n"
538 	"void main (void)\n"
539 	"{\n"
540 	"\tfragColor = vec4(v_value.xyz, 1.0);\n"
541 	"}";
542 
543 	return new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderStream.str(), fragmentShader));
544 }
545 
setState(const VertexArrayState & state)546 void VertexArrayObjectTest::setState (const VertexArrayState& state)
547 {
548 	GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[state.elementArrayBuffer]));
549 
550 	for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
551 	{
552 		GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_buffers[state.attributes[attribNdx].bufferNdx]));
553 		if (state.attributes[attribNdx].enabled)
554 			GLU_CHECK_CALL(glEnableVertexAttribArray(attribNdx));
555 		else
556 			GLU_CHECK_CALL(glDisableVertexAttribArray(attribNdx));
557 
558 		if (state.attributes[attribNdx].integer)
559 			GLU_CHECK_CALL(glVertexAttribIPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
560 		else
561 			GLU_CHECK_CALL(glVertexAttribPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].normalized, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
562 
563 		GLU_CHECK_CALL(glVertexAttribDivisor(attribNdx, state.attributes[attribNdx].divisor));
564 	}
565 }
566 
makeDrawCall(const VertexArrayState & state)567 void VertexArrayObjectTest::makeDrawCall (const VertexArrayState& state)
568 {
569 	GLU_CHECK_CALL(glClearColor(0.7f, 0.7f, 0.7f, 1.0f));
570 	GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
571 
572 	for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
573 	{
574 		if (state.attributes[attribNdx].integer)
575 			glVertexAttribI4i(attribNdx, 0, 0, 0, 1);
576 		else
577 			glVertexAttrib4f(attribNdx, 0.0f, 0.0f, 0.0f, 1.0f);
578 	}
579 
580 	if (m_spec.useDrawElements)
581 	{
582 		if (state.elementArrayBuffer == 0)
583 		{
584 			if (m_spec.instances == 0)
585 				GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices));
586 			else
587 				GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices, m_spec.instances));
588 		}
589 		else
590 		{
591 			if (m_spec.instances == 0)
592 				GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset)));
593 			else
594 				GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset), m_spec.instances));
595 		}
596 	}
597 	else
598 	{
599 		if (m_spec.instances == 0)
600 			GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, m_spec.count));
601 		else
602 			GLU_CHECK_CALL(glDrawArraysInstanced(GL_TRIANGLES, 0, m_spec.count, m_spec.instances));
603 	}
604 }
605 
render(tcu::Surface & vaoResult,tcu::Surface & defaultResult)606 void VertexArrayObjectTest::render (tcu::Surface& vaoResult, tcu::Surface& defaultResult)
607 {
608 	GLuint vao = 0;
609 
610 	GLU_CHECK_CALL(glGenVertexArrays(1, &vao));
611 	GLU_CHECK_CALL(glBindVertexArray(vao));
612 	setState(m_spec.vao);
613 	GLU_CHECK_CALL(glBindVertexArray(0));
614 
615 	setState(m_spec.state);
616 
617 	GLU_CHECK_CALL(glBindVertexArray(vao));
618 	GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
619 	makeDrawCall(m_spec.vao);
620 	glu::readPixels(m_context.getRenderContext(), 0, 0, vaoResult.getAccess());
621 	setState(m_spec.vao);
622 	GLU_CHECK_CALL(glBindVertexArray(0));
623 
624 	GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
625 	makeDrawCall(m_spec.state);
626 	glu::readPixels(m_context.getRenderContext(), 0, 0, defaultResult.getAccess());
627 }
628 
genReferences(tcu::Surface & vaoRef,tcu::Surface & defaultRef)629 void VertexArrayObjectTest::genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef)
630 {
631 	setState(m_spec.vao);
632 	GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
633 	makeDrawCall(m_spec.vao);
634 	glu::readPixels(m_context.getRenderContext(), 0, 0, vaoRef.getAccess());
635 
636 	setState(m_spec.state);
637 	GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
638 	makeDrawCall(m_spec.state);
639 	glu::readPixels(m_context.getRenderContext(), 0, 0, defaultRef.getAccess());
640 }
641 
iterate(void)642 TestCase::IterateResult VertexArrayObjectTest::iterate (void)
643 {
644 	tcu::Surface	vaoReference	(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
645 	tcu::Surface	stateReference	(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
646 
647 	tcu::Surface	vaoResult		(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
648 	tcu::Surface	stateResult		(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
649 
650 	bool			isOk;
651 
652 	logVertexArrayState(m_log, m_spec.vao, "Vertex Array Object State");
653 	logVertexArrayState(m_log, m_spec.state, "OpenGL Vertex Array State");
654 	genReferences(stateReference, vaoReference);
655 	render(stateResult, vaoResult);
656 
657 	isOk = tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array State", stateReference, stateResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
658 	isOk = isOk && tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array Object", vaoReference, vaoResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
659 
660 	if (isOk)
661 	{
662 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
663 		return STOP;
664 	}
665 	else
666 	{
667 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
668 		return STOP;
669 	}
670 }
671 
672 class MultiVertexArrayObjectTest : public TestCase
673 {
674 public:
675 
676 							MultiVertexArrayObjectTest	(Context& context, const char* name, const char* description);
677 							~MultiVertexArrayObjectTest	(void);
678 	virtual void			init						(void);
679 	virtual void			deinit						(void);
680 	virtual IterateResult	iterate						(void);
681 
682 private:
683 	Spec					m_spec;
684 	tcu::TestLog&			m_log;
685 	vector<GLuint>			m_buffers;
686 	glu::ShaderProgram*		m_vaoProgram;
687 	glu::ShaderProgram*		m_stateProgram;
688 	de::Random				m_random;
689 	deUint8*				m_indices;
690 
691 	void					logVertexArrayState			(tcu::TestLog& log, const VertexArrayState& state, const std::string& msg);
692 	deUint8*				createRandomBufferData		(const BufferSpec& buffer);
693 	deUint8*				generateIndices				(void);
694 	glu::ShaderProgram*		createProgram				(const VertexArrayState& state);
695 	void					setState					(const VertexArrayState& state);
696 	void					render						(tcu::Surface& vaoResult, tcu::Surface& defaultResult);
697 	void					makeDrawCall				(const VertexArrayState& state);
698 	void					genReferences				(tcu::Surface& vaoRef, tcu::Surface& defaultRef);
699 
700 							MultiVertexArrayObjectTest	(const MultiVertexArrayObjectTest&);
701 	MultiVertexArrayObjectTest&	operator=				(const MultiVertexArrayObjectTest&);
702 };
703 
MultiVertexArrayObjectTest(Context & context,const char * name,const char * description)704 MultiVertexArrayObjectTest::MultiVertexArrayObjectTest (Context& context, const char* name, const char* description)
705 	: TestCase			(context, name, description)
706 	, m_log				(context.getTestContext().getLog())
707 	, m_vaoProgram		(NULL)
708 	, m_stateProgram	(NULL)
709 	, m_random			(deStringHash(name))
710 	, m_indices			(NULL)
711 {
712 	// Makes zero to zero mapping for buffers
713 	m_buffers.push_back(0);
714 }
715 
~MultiVertexArrayObjectTest(void)716 MultiVertexArrayObjectTest::~MultiVertexArrayObjectTest (void)
717 {
718 }
719 
logVertexArrayState(tcu::TestLog & log,const VertexArrayState & state,const std::string & msg)720 void MultiVertexArrayObjectTest::logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg)
721 {
722 	std::stringstream message;
723 
724 	message << msg << "\n";
725 	message << "GL_ELEMENT_ARRAY_BUFFER : " << state.elementArrayBuffer << "\n";
726 
727 	for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
728 	{
729 		message
730 		<< "attribute : " << attribNdx << "\n"
731 		<< "\tGL_VERTEX_ATTRIB_ARRAY_ENABLED : " << (state.attributes[attribNdx].enabled ? "GL_TRUE" : "GL_FALSE") <<  "\n"
732 		<< "\tGL_VERTEX_ATTRIB_ARRAY_SIZE : " << state.attributes[attribNdx].size <<  "\n"
733 		<< "\tGL_VERTEX_ATTRIB_ARRAY_STRIDE : " << state.attributes[attribNdx].stride <<  "\n"
734 		<< "\tGL_VERTEX_ATTRIB_ARRAY_TYPE : " << state.attributes[attribNdx].type <<  "\n"
735 		<< "\tGL_VERTEX_ATTRIB_ARRAY_NORMALIZED : " << (state.attributes[attribNdx].normalized ? "GL_TRUE" : "GL_FALSE") <<  "\n"
736 		<< "\tGL_VERTEX_ATTRIB_ARRAY_INTEGER : " << (state.attributes[attribNdx].integer ? "GL_TRUE" : "GL_FALSE") <<  "\n"
737 		<< "\tGL_VERTEX_ATTRIB_ARRAY_DIVISOR : " << state.attributes[attribNdx].divisor <<  "\n"
738 		<< "\tGL_VERTEX_ATTRIB_ARRAY_POINTER : " << state.attributes[attribNdx].offset <<  "\n"
739 		<< "\t GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : " << m_buffers[state.attributes[attribNdx].bufferNdx] <<  "\n";
740 	}
741 	log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
742 }
743 
744 
init(void)745 void MultiVertexArrayObjectTest::init (void)
746 {
747 	GLint attribCount;
748 
749 	GLU_CHECK_CALL(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribCount));
750 
751 	m_spec.useDrawElements			= false;
752 	m_spec.instances				= 0;
753 	m_spec.count					= 24;
754 	m_spec.indexOffset				= 0;
755 	m_spec.indexRangeMin			= 0;
756 	m_spec.indexRangeMax			= 0;
757 	m_spec.indexType				= GL_NONE;
758 	m_spec.indexCount				= 0;
759 	m_spec.vao.elementArrayBuffer	= 0;
760 	m_spec.state.elementArrayBuffer	= 0;
761 
762 	for (int attribNdx = 0; attribNdx < attribCount; attribNdx++)
763 	{
764 		BufferSpec shortCoordBuffer48 = { 48, 2*384, 4, 0, 0, GL_SHORT, -32768, 32768, 0.0f, 0.0f };
765 		m_spec.buffers.push_back(shortCoordBuffer48);
766 
767 		m_spec.state.attributes.push_back(Attribute());
768 		m_spec.state.attributes[attribNdx].enabled		= (m_random.getInt(0, 4) == 0) ? GL_FALSE : GL_TRUE;
769 		m_spec.state.attributes[attribNdx].size			= m_random.getInt(2,4);
770 		m_spec.state.attributes[attribNdx].stride		= 2*m_random.getInt(1, 3);
771 		m_spec.state.attributes[attribNdx].type			= GL_SHORT;
772 		m_spec.state.attributes[attribNdx].integer		= m_random.getBool();
773 		m_spec.state.attributes[attribNdx].divisor		= m_random.getInt(0, 1);
774 		m_spec.state.attributes[attribNdx].offset		= 2*m_random.getInt(0, 2);
775 		m_spec.state.attributes[attribNdx].normalized	= m_random.getBool();
776 		m_spec.state.attributes[attribNdx].bufferNdx	= attribNdx+1;
777 
778 		if (attribNdx == 0)
779 		{
780 			m_spec.state.attributes[attribNdx].divisor	= 0;
781 			m_spec.state.attributes[attribNdx].enabled	= GL_TRUE;
782 			m_spec.state.attributes[attribNdx].size		= 2;
783 		}
784 
785 		m_spec.vao.attributes.push_back(Attribute());
786 		m_spec.vao.attributes[attribNdx].enabled		= (m_random.getInt(0, 4) == 0) ? GL_FALSE : GL_TRUE;
787 		m_spec.vao.attributes[attribNdx].size			= m_random.getInt(2,4);
788 		m_spec.vao.attributes[attribNdx].stride			= 2*m_random.getInt(1, 3);
789 		m_spec.vao.attributes[attribNdx].type			= GL_SHORT;
790 		m_spec.vao.attributes[attribNdx].integer		= m_random.getBool();
791 		m_spec.vao.attributes[attribNdx].divisor		= m_random.getInt(0, 1);
792 		m_spec.vao.attributes[attribNdx].offset			= 2*m_random.getInt(0, 2);
793 		m_spec.vao.attributes[attribNdx].normalized		= m_random.getBool();
794 		m_spec.vao.attributes[attribNdx].bufferNdx		= attribCount - attribNdx;
795 
796 		if (attribNdx == 0)
797 		{
798 			m_spec.vao.attributes[attribNdx].divisor	= 0;
799 			m_spec.vao.attributes[attribNdx].enabled	= GL_TRUE;
800 			m_spec.vao.attributes[attribNdx].size		= 2;
801 		}
802 
803 	}
804 
805 	// \note [mika] Index 0 is reserved for 0 buffer
806 	for (int bufferNdx = 0; bufferNdx < (int)m_spec.buffers.size(); bufferNdx++)
807 	{
808 		deUint8* data = createRandomBufferData(m_spec.buffers[bufferNdx]);
809 
810 		try
811 		{
812 			GLuint buffer;
813 			GLU_CHECK_CALL(glGenBuffers(1, &buffer));
814 			m_buffers.push_back(buffer);
815 
816 			GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, buffer));
817 			GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, m_spec.buffers[bufferNdx].size, data, GL_DYNAMIC_DRAW));
818 			GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
819 
820 		} catch (...) {
821 			delete[] data;
822 			throw;
823 		}
824 
825 		delete[] data;
826 	}
827 
828 	m_vaoProgram	= createProgram(m_spec.vao);
829 	m_log << tcu::TestLog::Message << "Program used with Vertex Array Object" << tcu::TestLog::EndMessage;
830 	m_log << *m_vaoProgram;
831 	m_stateProgram	= createProgram(m_spec.state);
832 	m_log << tcu::TestLog::Message << "Program used with Vertex Array State" << tcu::TestLog::EndMessage;
833 	m_log << *m_stateProgram;
834 
835 	if (!m_vaoProgram->isOk() || !m_stateProgram->isOk())
836 		TCU_FAIL("Failed to compile shaders");
837 
838 	if (m_spec.useDrawElements && (m_spec.vao.elementArrayBuffer == 0 || m_spec.state.elementArrayBuffer == 0))
839 		m_indices = generateIndices();
840 }
841 
deinit(void)842 void MultiVertexArrayObjectTest::deinit (void)
843 {
844 	GLU_CHECK_CALL(glDeleteBuffers((GLsizei)m_buffers.size(), &(m_buffers[0])));
845 	m_buffers.clear();
846 	delete m_vaoProgram;
847 	delete m_stateProgram;
848 	delete[] m_indices;
849 }
850 
generateIndices(void)851 deUint8* MultiVertexArrayObjectTest::generateIndices (void)
852 {
853 	int typeSize = 0;
854 	switch (m_spec.indexType)
855 	{
856 		case GL_UNSIGNED_INT:	typeSize = sizeof(GLuint);		break;
857 		case GL_UNSIGNED_SHORT:	typeSize = sizeof(GLushort);	break;
858 		case GL_UNSIGNED_BYTE:	typeSize = sizeof(GLubyte);		break;
859 		default:
860 			DE_ASSERT(false);
861 	}
862 
863 	deUint8* indices = new deUint8[m_spec.indexCount * typeSize];
864 
865 	for (int i = 0; i < m_spec.indexCount; i++)
866 	{
867 		deUint8* pos = indices + typeSize * i;
868 
869 		switch (m_spec.indexType)
870 		{
871 			case GL_UNSIGNED_INT:
872 			{
873 				GLuint v = (GLuint)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
874 				deMemcpy(pos, &v, sizeof(v));
875 				break;
876 			}
877 
878 			case GL_UNSIGNED_SHORT:
879 			{
880 				GLushort v = (GLushort)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
881 				deMemcpy(pos, &v, sizeof(v));
882 				break;
883 			}
884 
885 			case GL_UNSIGNED_BYTE:
886 			{
887 				GLubyte v = (GLubyte)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
888 				deMemcpy(pos, &v, sizeof(v));
889 				break;
890 			}
891 
892 			default:
893 				DE_ASSERT(false);
894 		}
895 	}
896 
897 	return indices;
898 }
899 
createRandomBufferData(const BufferSpec & buffer)900 deUint8* MultiVertexArrayObjectTest::createRandomBufferData (const BufferSpec& buffer)
901 {
902 	deUint8* data = new deUint8[buffer.size];
903 
904 	int stride;
905 
906 	if (buffer.stride != 0)
907 	{
908 		stride = buffer.stride;
909 	}
910 	else
911 	{
912 		switch (buffer.type)
913 		{
914 			case GL_FLOAT:			stride = buffer.componentCount * (int)sizeof(GLfloat);	break;
915 			case GL_INT:			stride = buffer.componentCount * (int)sizeof(GLint);	break;
916 			case GL_UNSIGNED_INT:	stride = buffer.componentCount * (int)sizeof(GLuint);	break;
917 			case GL_SHORT:			stride = buffer.componentCount * (int)sizeof(GLshort);	break;
918 			case GL_UNSIGNED_SHORT:	stride = buffer.componentCount * (int)sizeof(GLushort);	break;
919 			case GL_BYTE:			stride = buffer.componentCount * (int)sizeof(GLbyte);	break;
920 			case GL_UNSIGNED_BYTE:	stride = buffer.componentCount * (int)sizeof(GLubyte);	break;
921 
922 			default:
923 				stride = 0;
924 				DE_ASSERT(DE_FALSE);
925 		}
926 	}
927 
928 	deUint8* itr = data;
929 
930 	for (int pos = 0; pos < buffer.count; pos++)
931 	{
932 		deUint8* componentItr = itr;
933 		for (int componentNdx = 0; componentNdx < buffer.componentCount; componentNdx++)
934 		{
935 			switch (buffer.type)
936 			{
937 				case GL_FLOAT:
938 				{
939 					float v = buffer.floatRangeMin + (buffer.floatRangeMax - buffer.floatRangeMin) * m_random.getFloat();
940 					deMemcpy(componentItr, &v, sizeof(v));
941 					componentItr += sizeof(v);
942 					break;
943 				}
944 
945 				case GL_INT:
946 				{
947 					GLint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
948 					deMemcpy(componentItr, &v, sizeof(v));
949 					componentItr += sizeof(v);
950 					break;
951 				}
952 
953 				case GL_UNSIGNED_INT:
954 				{
955 					GLuint v = (GLuint)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
956 					deMemcpy(componentItr, &v, sizeof(v));
957 					componentItr += sizeof(v);
958 					break;
959 				}
960 
961 				case GL_SHORT:
962 				{
963 					GLshort v = (GLshort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
964 					deMemcpy(componentItr, &v, sizeof(v));
965 					componentItr += sizeof(v);
966 					break;
967 				}
968 
969 				case GL_UNSIGNED_SHORT:
970 				{
971 					GLushort v = (GLushort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
972 					deMemcpy(componentItr, &v, sizeof(v));
973 					componentItr += sizeof(v);
974 					break;
975 				}
976 
977 				case GL_BYTE:
978 				{
979 					GLbyte v = (GLbyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
980 					deMemcpy(componentItr, &v, sizeof(v));
981 					componentItr += sizeof(v);
982 					break;
983 				}
984 
985 				case GL_UNSIGNED_BYTE:
986 				{
987 					GLubyte v = (GLubyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
988 					deMemcpy(componentItr, &v, sizeof(v));
989 					componentItr += sizeof(v);
990 					break;
991 				}
992 
993 				default:
994 					DE_ASSERT(false);
995 			}
996 		}
997 
998 		itr += stride;
999 	}
1000 
1001 	return data;
1002 }
1003 
createProgram(const VertexArrayState & state)1004 glu::ShaderProgram* MultiVertexArrayObjectTest::createProgram (const VertexArrayState& state)
1005 {
1006 	std::stringstream vertexShaderStream;
1007 	std::stringstream value;
1008 
1009 	vertexShaderStream << "#version 300 es\n";
1010 
1011 	for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
1012 	{
1013 		if (state.attributes[attribNdx].integer)
1014 			vertexShaderStream << "layout(location = " << attribNdx << ") in mediump ivec4 a_attrib" << attribNdx << ";\n";
1015 		else
1016 			vertexShaderStream << "layout(location = " << attribNdx << ") in mediump vec4 a_attrib" << attribNdx << ";\n";
1017 
1018 		if (state.attributes[attribNdx].integer)
1019 		{
1020 			float scale = 0.0f;
1021 
1022 			switch (state.attributes[0].type)
1023 			{
1024 				case GL_SHORT:			scale  = (1.0f/float((1u<<14)-1u));	break;
1025 				case GL_UNSIGNED_SHORT:	scale  = (1.0f/float((1u<<15)-1u));	break;
1026 				case GL_INT:			scale  = (1.0f/float((1u<<30)-1u));	break;
1027 				case GL_UNSIGNED_INT:	scale  = (1.0f/float((1u<<31)-1u));	break;
1028 				case GL_BYTE:			scale  = (1.0f/float((1u<<6)-1u));	break;
1029 				case GL_UNSIGNED_BYTE:	scale  = (1.0f/float((1u<<7)-1u));	break;
1030 
1031 				default:
1032 					DE_ASSERT(DE_FALSE);
1033 			}
1034 			value << (attribNdx != 0 ? " + " : "" ) << scale << " * vec4(a_attrib" << attribNdx << ")";
1035 		}
1036 		else if (state.attributes[attribNdx].type != GL_FLOAT && !state.attributes[attribNdx].normalized)
1037 		{
1038 			float scale = 0.0f;
1039 
1040 			switch (state.attributes[0].type)
1041 			{
1042 				case GL_SHORT:			scale  = (0.5f/float((1u<<14)-1u));	break;
1043 				case GL_UNSIGNED_SHORT:	scale  = (0.5f/float((1u<<15)-1u));	break;
1044 				case GL_INT:			scale  = (0.5f/float((1u<<30)-1u));	break;
1045 				case GL_UNSIGNED_INT:	scale  = (0.5f/float((1u<<31)-1u));	break;
1046 				case GL_BYTE:			scale  = (0.5f/float((1u<<6)-1u));	break;
1047 				case GL_UNSIGNED_BYTE:	scale  = (0.5f/float((1u<<7)-1u));	break;
1048 
1049 				default:
1050 					DE_ASSERT(DE_FALSE);
1051 			}
1052 			value << (attribNdx != 0 ? " + " : "" ) << scale << " * a_attrib" << attribNdx;
1053 		}
1054 		else
1055 			value << (attribNdx != 0 ? " + " : "" ) << "a_attrib" << attribNdx;
1056 	}
1057 
1058 	vertexShaderStream
1059 		<< "out mediump vec4 v_value;\n"
1060 		<< "void main (void)\n"
1061 		<< "{\n"
1062 		<< "\tv_value = " << value.str() << ";\n";
1063 
1064 	if (state.attributes[0].integer)
1065 	{
1066 		float scale = 0.0f;
1067 
1068 		switch (state.attributes[0].type)
1069 		{
1070 			case GL_SHORT:			scale  = (1.0f/float((1u<<14)-1u));	break;
1071 			case GL_UNSIGNED_SHORT:	scale  = (1.0f/float((1u<<15)-1u));	break;
1072 			case GL_INT:			scale  = (1.0f/float((1u<<30)-1u));	break;
1073 			case GL_UNSIGNED_INT:	scale  = (1.0f/float((1u<<31)-1u));	break;
1074 			case GL_BYTE:			scale  = (1.0f/float((1u<<6)-1u));	break;
1075 			case GL_UNSIGNED_BYTE:	scale  = (1.0f/float((1u<<7)-1u));	break;
1076 
1077 
1078 			default:
1079 				DE_ASSERT(DE_FALSE);
1080 		}
1081 
1082 		vertexShaderStream
1083 			<< "\tgl_Position = vec4(" << scale << " * " <<  "a_attrib0.xyz, 1.0);\n"
1084 			<< "}";
1085 	}
1086 	else
1087 	{
1088 		if (state.attributes[0].normalized || state.attributes[0].type == GL_FLOAT)
1089 		{
1090 			vertexShaderStream
1091 				<< "\tgl_Position = vec4(a_attrib0.xyz, 1.0);\n"
1092 				<< "}";
1093 		}
1094 		else
1095 		{
1096 			float scale = 0.0f;
1097 
1098 			switch (state.attributes[0].type)
1099 			{
1100 				case GL_SHORT:			scale  = (1.0f/float((1u<<14)-1u));	break;
1101 				case GL_UNSIGNED_SHORT:	scale  = (1.0f/float((1u<<15)-1u));	break;
1102 				case GL_INT:			scale  = (1.0f/float((1u<<30)-1u));	break;
1103 				case GL_UNSIGNED_INT:	scale  = (1.0f/float((1u<<31)-1u));	break;
1104 				case GL_BYTE:			scale  = (1.0f/float((1u<<6)-1u));	break;
1105 				case GL_UNSIGNED_BYTE:	scale  = (1.0f/float((1u<<7)-1u));	break;
1106 
1107 				default:
1108 					DE_ASSERT(DE_FALSE);
1109 			}
1110 
1111 			scale *= 0.5f;
1112 
1113 			vertexShaderStream
1114 				<< "\tgl_Position = vec4(" << scale << " * " <<  "vec3(a_attrib0.xyz), 1.0);\n"
1115 				<< "}";
1116 		}
1117 	}
1118 
1119 	const char* fragmentShader =
1120 	"#version 300 es\n"
1121 	"in mediump vec4 v_value;\n"
1122 	"layout(location = 0) out mediump vec4 fragColor;\n"
1123 	"void main (void)\n"
1124 	"{\n"
1125 	"\tfragColor = vec4(v_value.xyz, 1.0);\n"
1126 	"}";
1127 
1128 	return new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderStream.str(), fragmentShader));
1129 }
1130 
setState(const VertexArrayState & state)1131 void MultiVertexArrayObjectTest::setState (const VertexArrayState& state)
1132 {
1133 	GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[state.elementArrayBuffer]));
1134 
1135 	for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
1136 	{
1137 		GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_buffers[state.attributes[attribNdx].bufferNdx]));
1138 		if (state.attributes[attribNdx].enabled)
1139 			GLU_CHECK_CALL(glEnableVertexAttribArray(attribNdx));
1140 		else
1141 			GLU_CHECK_CALL(glDisableVertexAttribArray(attribNdx));
1142 
1143 		if (state.attributes[attribNdx].integer)
1144 			GLU_CHECK_CALL(glVertexAttribIPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
1145 		else
1146 			GLU_CHECK_CALL(glVertexAttribPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].normalized, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
1147 
1148 		GLU_CHECK_CALL(glVertexAttribDivisor(attribNdx, state.attributes[attribNdx].divisor));
1149 	}
1150 }
1151 
makeDrawCall(const VertexArrayState & state)1152 void MultiVertexArrayObjectTest::makeDrawCall (const VertexArrayState& state)
1153 {
1154 	GLU_CHECK_CALL(glClearColor(0.7f, 0.7f, 0.7f, 1.0f));
1155 	GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
1156 
1157 	if (m_spec.useDrawElements)
1158 	{
1159 		if (state.elementArrayBuffer == 0)
1160 		{
1161 			if (m_spec.instances == 0)
1162 				GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices));
1163 			else
1164 				GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices, m_spec.instances));
1165 		}
1166 		else
1167 		{
1168 			if (m_spec.instances == 0)
1169 				GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset)));
1170 			else
1171 				GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset), m_spec.instances));
1172 		}
1173 	}
1174 	else
1175 	{
1176 		if (m_spec.instances == 0)
1177 			GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, m_spec.count));
1178 		else
1179 			GLU_CHECK_CALL(glDrawArraysInstanced(GL_TRIANGLES, 0, m_spec.count, m_spec.instances));
1180 	}
1181 }
1182 
render(tcu::Surface & vaoResult,tcu::Surface & defaultResult)1183 void MultiVertexArrayObjectTest::render (tcu::Surface& vaoResult, tcu::Surface& defaultResult)
1184 {
1185 	GLuint vao = 0;
1186 
1187 	GLU_CHECK_CALL(glGenVertexArrays(1, &vao));
1188 	GLU_CHECK_CALL(glBindVertexArray(vao));
1189 	setState(m_spec.vao);
1190 	GLU_CHECK_CALL(glBindVertexArray(0));
1191 
1192 	setState(m_spec.state);
1193 
1194 	GLU_CHECK_CALL(glBindVertexArray(vao));
1195 	GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
1196 	makeDrawCall(m_spec.vao);
1197 	glu::readPixels(m_context.getRenderContext(), 0, 0, vaoResult.getAccess());
1198 	setState(m_spec.vao);
1199 	GLU_CHECK_CALL(glBindVertexArray(0));
1200 
1201 	GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
1202 	makeDrawCall(m_spec.state);
1203 	glu::readPixels(m_context.getRenderContext(), 0, 0, defaultResult.getAccess());
1204 }
1205 
genReferences(tcu::Surface & vaoRef,tcu::Surface & defaultRef)1206 void MultiVertexArrayObjectTest::genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef)
1207 {
1208 	setState(m_spec.vao);
1209 	GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
1210 	makeDrawCall(m_spec.vao);
1211 	glu::readPixels(m_context.getRenderContext(), 0, 0, vaoRef.getAccess());
1212 
1213 	setState(m_spec.state);
1214 	GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
1215 	makeDrawCall(m_spec.state);
1216 	glu::readPixels(m_context.getRenderContext(), 0, 0, defaultRef.getAccess());
1217 }
1218 
iterate(void)1219 TestCase::IterateResult MultiVertexArrayObjectTest::iterate (void)
1220 {
1221 	tcu::Surface	vaoReference	(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1222 	tcu::Surface	stateReference	(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1223 
1224 	tcu::Surface	vaoResult		(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1225 	tcu::Surface	stateResult		(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1226 
1227 	bool			isOk;
1228 
1229 	logVertexArrayState(m_log, m_spec.vao, "Vertex Array Object State");
1230 	logVertexArrayState(m_log, m_spec.state, "OpenGL Vertex Array State");
1231 	genReferences(stateReference, vaoReference);
1232 	render(stateResult, vaoResult);
1233 
1234 	isOk = tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array State", stateReference, stateResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
1235 	isOk = isOk && tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array Object", vaoReference, vaoResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
1236 
1237 	if (isOk)
1238 	{
1239 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1240 		return STOP;
1241 	}
1242 	else
1243 	{
1244 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1245 		return STOP;
1246 	}
1247 }
1248 
VertexArrayObjectTestGroup(Context & context)1249 VertexArrayObjectTestGroup::VertexArrayObjectTestGroup (Context& context)
1250 	: TestCaseGroup(context, "vertex_array_objects", "Vertex array object test cases")
1251 {
1252 }
1253 
~VertexArrayObjectTestGroup(void)1254 VertexArrayObjectTestGroup::~VertexArrayObjectTestGroup (void)
1255 {
1256 }
1257 
init(void)1258 void VertexArrayObjectTestGroup::init (void)
1259 {
1260 	BufferSpec floatCoordBuffer48_1 = { 48, 384, 2, 0, 0, GL_FLOAT, 0, 0, -1.0f, 1.0f };
1261 	BufferSpec floatCoordBuffer48_2 = { 48, 384, 2, 0, 0, GL_FLOAT, 0, 0, -1.0f, 1.0f };
1262 
1263 	BufferSpec shortCoordBuffer48 = { 48, 192, 2, 0, 0, GL_SHORT, -32768, 32768, 0.0f, 0.0f };
1264 
1265 	// Different buffer
1266 	{
1267 		Spec spec;
1268 
1269 		VertexArrayState state;
1270 
1271 		state.attributes.push_back(Attribute());
1272 
1273 		state.attributes[0].enabled		= true;
1274 		state.attributes[0].size		= 2;
1275 		state.attributes[0].stride		= 0;
1276 		state.attributes[0].type		= GL_FLOAT;
1277 		state.attributes[0].integer		= GL_FALSE;
1278 		state.attributes[0].divisor		= 0;
1279 		state.attributes[0].offset		= 0;
1280 		state.attributes[0].normalized	= GL_FALSE;
1281 
1282 		state.elementArrayBuffer = 0;
1283 
1284 		spec.buffers.push_back(floatCoordBuffer48_1);
1285 		spec.buffers.push_back(floatCoordBuffer48_2);
1286 
1287 		spec.useDrawElements	= false;
1288 		spec.instances			= 0;
1289 		spec.count				= 48;
1290 		spec.vao				= state;
1291 		spec.state				= state;
1292 		spec.indexOffset		= 0;
1293 		spec.indexRangeMin		= 0;
1294 		spec.indexRangeMax		= 0;
1295 		spec.indexType			= GL_NONE;
1296 		spec.indexCount			= 0;
1297 
1298 		spec.state.attributes[0].bufferNdx	= 1;
1299 		spec.vao.attributes[0].bufferNdx	= 2;
1300 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_buffer", "diff_buffer"));
1301 	}
1302 	// Different size
1303 	{
1304 		Spec spec;
1305 
1306 		VertexArrayState state;
1307 
1308 		state.attributes.push_back(Attribute());
1309 
1310 		state.attributes[0].enabled		= true;
1311 		state.attributes[0].size		= 2;
1312 		state.attributes[0].stride		= 0;
1313 		state.attributes[0].type		= GL_FLOAT;
1314 		state.attributes[0].integer		= GL_FALSE;
1315 		state.attributes[0].divisor		= 0;
1316 		state.attributes[0].offset		= 0;
1317 		state.attributes[0].normalized	= GL_FALSE;
1318 		state.attributes[0].bufferNdx	= 1;
1319 
1320 		state.elementArrayBuffer = 0;
1321 
1322 		spec.buffers.push_back(floatCoordBuffer48_1);
1323 
1324 		spec.useDrawElements	= false;
1325 		spec.instances			= 0;
1326 		spec.count				= 24;
1327 		spec.vao				= state;
1328 		spec.state				= state;
1329 		spec.indexOffset		= 0;
1330 		spec.indexRangeMin		= 0;
1331 		spec.indexRangeMax		= 0;
1332 		spec.indexType			= GL_NONE;
1333 		spec.indexCount			= 0;
1334 
1335 		spec.state.attributes[0].size		= 2;
1336 		spec.vao.attributes[0].size			= 3;
1337 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_size", "diff_size"));
1338 	}
1339 
1340 	// Different stride
1341 	{
1342 		Spec spec;
1343 
1344 		VertexArrayState state;
1345 
1346 		state.attributes.push_back(Attribute());
1347 
1348 		state.attributes[0].enabled		= true;
1349 		state.attributes[0].size		= 2;
1350 		state.attributes[0].stride		= 0;
1351 		state.attributes[0].type		= GL_SHORT;
1352 		state.attributes[0].integer		= GL_FALSE;
1353 		state.attributes[0].divisor		= 0;
1354 		state.attributes[0].offset		= 0;
1355 		state.attributes[0].normalized	= GL_TRUE;
1356 		state.attributes[0].bufferNdx	= 1;
1357 
1358 		state.elementArrayBuffer = 0;
1359 
1360 		spec.buffers.push_back(shortCoordBuffer48);
1361 
1362 		spec.useDrawElements	= false;
1363 		spec.instances			= 0;
1364 		spec.count				= 24;
1365 		spec.vao				= state;
1366 		spec.state				= state;
1367 		spec.indexOffset		= 0;
1368 		spec.indexRangeMin		= 0;
1369 		spec.indexRangeMax		= 0;
1370 		spec.indexType			= GL_NONE;
1371 		spec.indexCount			= 0;
1372 
1373 		spec.vao.attributes[0].stride	= 2;
1374 		spec.state.attributes[0].stride	= 4;
1375 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_stride", "diff_stride"));
1376 	}
1377 
1378 	// Different types
1379 	{
1380 		Spec spec;
1381 
1382 		VertexArrayState state;
1383 
1384 		state.attributes.push_back(Attribute());
1385 
1386 		state.attributes[0].enabled		= true;
1387 		state.attributes[0].size		= 2;
1388 		state.attributes[0].stride		= 0;
1389 		state.attributes[0].type		= GL_SHORT;
1390 		state.attributes[0].integer		= GL_FALSE;
1391 		state.attributes[0].divisor		= 0;
1392 		state.attributes[0].offset		= 0;
1393 		state.attributes[0].normalized	= GL_TRUE;
1394 		state.attributes[0].bufferNdx	= 1;
1395 
1396 		state.elementArrayBuffer = 0;
1397 
1398 		spec.buffers.push_back(shortCoordBuffer48);
1399 
1400 		spec.useDrawElements	= false;
1401 		spec.instances			= 0;
1402 		spec.count				= 24;
1403 		spec.vao				= state;
1404 		spec.state				= state;
1405 		spec.indexOffset		= 0;
1406 		spec.indexRangeMin		= 0;
1407 		spec.indexRangeMax		= 0;
1408 		spec.indexType			= GL_NONE;
1409 		spec.indexCount			= 0;
1410 
1411 		spec.vao.attributes[0].type		= GL_SHORT;
1412 		spec.state.attributes[0].type	= GL_BYTE;
1413 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_type", "diff_type"));
1414 	}
1415 	// Different "integer"
1416 	{
1417 		Spec spec;
1418 
1419 		VertexArrayState state;
1420 
1421 		state.attributes.push_back(Attribute());
1422 
1423 		state.attributes[0].enabled		= true;
1424 		state.attributes[0].size		= 2;
1425 		state.attributes[0].stride		= 0;
1426 		state.attributes[0].type		= GL_BYTE;
1427 		state.attributes[0].integer		= GL_TRUE;
1428 		state.attributes[0].divisor		= 0;
1429 		state.attributes[0].offset		= 0;
1430 		state.attributes[0].normalized	= GL_FALSE;
1431 		state.attributes[0].bufferNdx	= 1;
1432 
1433 		state.elementArrayBuffer = 0;
1434 
1435 		spec.buffers.push_back(shortCoordBuffer48);
1436 
1437 		spec.useDrawElements	= false;
1438 		spec.count				= 24;
1439 		spec.vao				= state;
1440 		spec.state				= state;
1441 		spec.instances			= 0;
1442 		spec.indexOffset		= 0;
1443 		spec.indexRangeMin		= 0;
1444 		spec.indexRangeMax		= 0;
1445 		spec.indexType			= GL_NONE;
1446 		spec.indexCount			= 0;
1447 
1448 		spec.state.attributes[0].integer	= GL_FALSE;
1449 		spec.vao.attributes[0].integer		= GL_TRUE;
1450 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_integer", "diff_integer"));
1451 	}
1452 	// Different divisor
1453 	{
1454 		Spec spec;
1455 
1456 		VertexArrayState state;
1457 
1458 		state.attributes.push_back(Attribute());
1459 		state.attributes.push_back(Attribute());
1460 
1461 		state.attributes[0].enabled		= true;
1462 		state.attributes[0].size		= 2;
1463 		state.attributes[0].stride		= 0;
1464 		state.attributes[0].type		= GL_SHORT;
1465 		state.attributes[0].integer		= GL_FALSE;
1466 		state.attributes[0].divisor		= 0;
1467 		state.attributes[0].offset		= 0;
1468 		state.attributes[0].normalized	= GL_TRUE;
1469 		state.attributes[0].bufferNdx	= 1;
1470 
1471 		state.attributes[1].enabled		= true;
1472 		state.attributes[1].size		= 4;
1473 		state.attributes[1].stride		= 0;
1474 		state.attributes[1].type		= GL_FLOAT;
1475 		state.attributes[1].integer		= GL_FALSE;
1476 		state.attributes[1].divisor		= 0;
1477 		state.attributes[1].offset		= 0;
1478 		state.attributes[1].normalized	= GL_FALSE;
1479 		state.attributes[1].bufferNdx	= 2;
1480 
1481 		state.elementArrayBuffer = 0;
1482 
1483 		spec.buffers.push_back(shortCoordBuffer48);
1484 		spec.buffers.push_back(floatCoordBuffer48_1);
1485 
1486 		spec.useDrawElements	= false;
1487 		spec.instances			= 10;
1488 		spec.count				= 12;
1489 		spec.vao				= state;
1490 		spec.state				= state;
1491 		spec.indexOffset		= 0;
1492 		spec.indexRangeMin		= 0;
1493 		spec.indexRangeMax		= 0;
1494 		spec.indexType			= GL_NONE;
1495 		spec.indexCount			= 0;
1496 
1497 		spec.vao.attributes[1].divisor		= 3;
1498 		spec.state.attributes[1].divisor	= 2;
1499 
1500 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_divisor", "diff_divisor"));
1501 	}
1502 	// Different offset
1503 	{
1504 		Spec spec;
1505 
1506 		VertexArrayState state;
1507 
1508 		state.attributes.push_back(Attribute());
1509 
1510 		state.attributes[0].enabled		= true;
1511 		state.attributes[0].size		= 2;
1512 		state.attributes[0].stride		= 0;
1513 		state.attributes[0].type		= GL_SHORT;
1514 		state.attributes[0].integer		= GL_FALSE;
1515 		state.attributes[0].divisor		= 0;
1516 		state.attributes[0].offset		= 0;
1517 		state.attributes[0].normalized	= GL_TRUE;
1518 		state.attributes[0].bufferNdx	= 1;
1519 
1520 		state.elementArrayBuffer = 0;
1521 
1522 		spec.buffers.push_back(shortCoordBuffer48);
1523 
1524 		spec.useDrawElements	= false;
1525 		spec.instances			= 0;
1526 		spec.count				= 24;
1527 		spec.vao				= state;
1528 		spec.state				= state;
1529 		spec.indexOffset		= 0;
1530 		spec.indexRangeMin		= 0;
1531 		spec.indexRangeMax		= 0;
1532 		spec.indexType			= GL_NONE;
1533 		spec.indexCount			= 0;
1534 
1535 		spec.vao.attributes[0].offset	= 2;
1536 		spec.state.attributes[0].offset	= 4;
1537 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_offset", "diff_offset"));
1538 	}
1539 	// Different normalize
1540 	{
1541 		Spec spec;
1542 
1543 		VertexArrayState state;
1544 
1545 		state.attributes.push_back(Attribute());
1546 
1547 		state.attributes[0].enabled		= true;
1548 		state.attributes[0].size		= 2;
1549 		state.attributes[0].stride		= 0;
1550 		state.attributes[0].type		= GL_SHORT;
1551 		state.attributes[0].integer		= GL_FALSE;
1552 		state.attributes[0].divisor		= 0;
1553 		state.attributes[0].offset		= 0;
1554 		state.attributes[0].normalized	= GL_TRUE;
1555 		state.attributes[0].bufferNdx	= 1;
1556 
1557 		state.elementArrayBuffer = 0;
1558 
1559 		spec.buffers.push_back(shortCoordBuffer48);
1560 
1561 		spec.useDrawElements	= false;
1562 		spec.instances			= 0;
1563 		spec.count				= 48;
1564 		spec.vao				= state;
1565 		spec.state				= state;
1566 		spec.indexOffset		= 0;
1567 		spec.indexRangeMin		= 0;
1568 		spec.indexRangeMax		= 0;
1569 		spec.indexType			= GL_NONE;
1570 		spec.indexCount			= 0;
1571 
1572 		spec.vao.attributes[0].normalized	= GL_TRUE;
1573 		spec.state.attributes[0].normalized	= GL_FALSE;
1574 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_normalize", "diff_normalize"));
1575 	}
1576 	// DrawElements with buffer / Pointer
1577 	{
1578 		Spec spec;
1579 
1580 		VertexArrayState state;
1581 
1582 		state.attributes.push_back(Attribute());
1583 
1584 		state.attributes[0].enabled		= true;
1585 		state.attributes[0].size		= 2;
1586 		state.attributes[0].stride		= 0;
1587 		state.attributes[0].type		= GL_FLOAT;
1588 		state.attributes[0].integer		= GL_FALSE;
1589 		state.attributes[0].divisor		= 0;
1590 		state.attributes[0].offset		= 0;
1591 		state.attributes[0].normalized	= GL_TRUE;
1592 		state.attributes[0].bufferNdx	= 1;
1593 
1594 		state.elementArrayBuffer = 0;
1595 
1596 		spec.buffers.push_back(floatCoordBuffer48_1);
1597 
1598 		BufferSpec indexBuffer = { 24, 192, 1, 0, 0, GL_UNSIGNED_SHORT, 0, 48, 0.0f, 0.0f };
1599 		spec.buffers.push_back(indexBuffer);
1600 
1601 		spec.useDrawElements	= true;
1602 		spec.count				= 24;
1603 		spec.vao				= state;
1604 		spec.state				= state;
1605 		spec.instances			= 0;
1606 		spec.indexOffset		= 0;
1607 		spec.indexRangeMin		= 0;
1608 		spec.indexRangeMax		= 48;
1609 		spec.indexType			= GL_UNSIGNED_SHORT;
1610 		spec.indexCount			= 24;
1611 
1612 		spec.state.elementArrayBuffer	= 0;
1613 		spec.vao.elementArrayBuffer		= 2;
1614 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_indices", "diff_indices"));
1615 	}
1616 	// Use all attributes
1617 
1618 	addChild(new MultiVertexArrayObjectTest(m_context, "all_attributes", "all_attributes"));
1619 }
1620 
1621 } // Functional
1622 } // gles3
1623 } // deqp
1624