• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
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
22  */ /*-------------------------------------------------------------------*/
23 
24 /**
25  * @file  gl4cVertexAttrib64BitTests.hpp
26  * @brief Implement conformance tests for GL_ARB_vertex_attrib_64bit functionality
27  **/
28 
29 #include "gl4cVertexAttrib64BitTest.hpp"
30 
31 #include "gluContextInfo.hpp"
32 #include "gluStrUtil.hpp"
33 #include "glwDefs.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 #include "tcuTestLog.hpp"
37 
38 #include <algorithm>
39 #include <iomanip>
40 #include <string>
41 #include <vector>
42 
43 using namespace glw;
44 
45 namespace VertexAttrib64Bit
46 {
47 
48 class Base : public deqp::TestCase
49 {
50 public:
51 	/* Public constructor and destructor */
52 	Base(deqp::Context& context, const char* name, const char* description);
53 
~Base()54 	virtual ~Base()
55 	{
56 	}
57 
58 	/* Public methods */
59 	void BuildProgram(const GLchar* fragment_shader_code, GLuint& program_id, const GLchar* vertex_shader_code,
60 					  GLuint& out_fragment_shader_id, GLuint& out_vertex_shader_id) const;
61 
62 	void BuildProgramVSOnly(GLuint out_program_id, const GLchar* vertex_shader_code,
63 							GLuint& out_vertex_shader_id) const;
64 
65 	void CompileShader(GLuint id, const GLchar* source_code) const;
66 
67 	GLint GetMaxVertexAttribs() const;
68 
69 	void IterateStart();
70 
71 	tcu::TestNode::IterateResult IterateStop(bool result) const;
72 
73 	void LinkProgram(GLuint id) const;
74 
75 	static GLdouble RandomDouble(GLdouble min, GLdouble max);
76 
77 	void RequireExtension(const GLchar* extension_name) const;
78 
79 	/* Public fields */
80 	/* Test framework objects */
81 	glw::Functions gl; /* prefix "m_" ommitted for readability */
82 	tcu::TestLog&  m_log;
83 };
84 
85 /** Constructor
86  *
87  **/
Base(deqp::Context & context,const char * name,const char * description)88 Base::Base(deqp::Context& context, const char* name, const char* description)
89 	: TestCase(context, name, description), m_log(m_context.getTestContext().getLog())
90 {
91 	/* Nothing to be done here */
92 }
93 
BuildProgram(const GLchar * fragment_shader_code,GLuint & program_id,const GLchar * vertex_shader_code,GLuint & out_fragment_shader_id,GLuint & out_vertex_shader_id) const94 void Base::BuildProgram(const GLchar* fragment_shader_code, GLuint& program_id, const GLchar* vertex_shader_code,
95 						GLuint& out_fragment_shader_id, GLuint& out_vertex_shader_id) const
96 {
97 	out_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
98 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
99 
100 	out_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
101 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
102 
103 	CompileShader(out_fragment_shader_id, fragment_shader_code);
104 	CompileShader(out_vertex_shader_id, vertex_shader_code);
105 
106 	gl.attachShader(program_id, out_fragment_shader_id);
107 	GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
108 
109 	gl.attachShader(program_id, out_vertex_shader_id);
110 	GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
111 
112 	LinkProgram(program_id);
113 }
114 
115 /** Builds and links a program object consisting only of vertex shader stage.
116  *  The function also creates a vertex shader, assigns it user-provided body
117  *  and compiles it.
118  *
119  *  @param program_id           ID of a created program object to configure.
120  *  @param vertex_shader_code   Source code to use for the vertex shader.
121  *  @param out_vertex_shader_id Will hold
122  **/
BuildProgramVSOnly(GLuint program_id,const GLchar * vertex_shader_code,GLuint & out_vertex_shader_id) const123 void Base::BuildProgramVSOnly(GLuint program_id, const GLchar* vertex_shader_code, GLuint& out_vertex_shader_id) const
124 {
125 	out_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
126 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
127 
128 	CompileShader(out_vertex_shader_id, vertex_shader_code);
129 
130 	gl.attachShader(program_id, out_vertex_shader_id);
131 	GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
132 
133 	LinkProgram(program_id);
134 }
135 
CompileShader(GLuint id,const GLchar * source_code) const136 void Base::CompileShader(GLuint id, const GLchar* source_code) const
137 {
138 	GLint status = 0;
139 
140 	gl.shaderSource(id, 1, &source_code, 0 /* length */);
141 	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
142 
143 	gl.compileShader(id);
144 	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
145 
146 	gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
147 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
148 
149 	if (GL_FALSE == status)
150 	{
151 		GLint				message_length = 0;
152 		std::vector<GLchar> message;
153 
154 		gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &message_length);
155 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
156 
157 		message.resize(message_length + 1);
158 
159 		gl.getShaderInfoLog(id, message_length, &message_length, &message[0]);
160 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
161 
162 		m_log << tcu::TestLog::Section("Shader compilation error", "");
163 
164 		m_log << tcu::TestLog::Message << "Compilation log:\n" << &message[0] << tcu::TestLog::EndMessage;
165 
166 		m_log << tcu::TestLog::Message << "Shader source:\n" << source_code << tcu::TestLog::EndMessage;
167 
168 		m_log << tcu::TestLog::EndSection;
169 
170 		TCU_FAIL("Shader compilation failed");
171 	}
172 }
173 
174 /** Get value of GL_MAX_VERTEX_ATTRIBS
175  *
176  * Throws exception in case of failure
177  *
178  * @return Value
179  **/
GetMaxVertexAttribs() const180 GLint Base::GetMaxVertexAttribs() const
181 {
182 	GLint max_vertex_attribs;
183 
184 	gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs);
185 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
186 
187 	return max_vertex_attribs;
188 }
189 
IterateStart()190 void Base::IterateStart()
191 {
192 	gl = m_context.getRenderContext().getFunctions();
193 }
194 
IterateStop(bool result) const195 tcu::TestNode::IterateResult Base::IterateStop(bool result) const
196 {
197 	/* Set test result */
198 	if (false == result)
199 	{
200 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
201 	}
202 	else
203 	{
204 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
205 	}
206 
207 	/* Done */
208 	return tcu::TestNode::STOP;
209 }
210 
LinkProgram(GLuint id) const211 void Base::LinkProgram(GLuint id) const
212 {
213 	GLint status = 0;
214 	gl.linkProgram(id);
215 	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
216 
217 	gl.getProgramiv(id, GL_LINK_STATUS, &status);
218 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
219 
220 	if (GL_FALSE == status)
221 	{
222 		GLint				message_length = 0;
223 		std::vector<GLchar> message;
224 
225 		gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &message_length);
226 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
227 
228 		message.resize(message_length + 1);
229 
230 		gl.getProgramInfoLog(id, message_length, &message_length, &message[0]);
231 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
232 
233 		m_log << tcu::TestLog::Section("Program link error", "");
234 
235 		m_log << tcu::TestLog::Message << "Link log:\n" << &message[0] << tcu::TestLog::EndMessage;
236 
237 		m_log << tcu::TestLog::EndSection;
238 
239 		TCU_FAIL("Program linking failed");
240 	}
241 }
242 
243 /** Return "random" double value from range <min:max>
244  *
245  * @return Value
246  **/
RandomDouble(GLdouble min,GLdouble max)247 GLdouble Base::RandomDouble(GLdouble min, GLdouble max)
248 {
249 	static const glw::GLushort max_value = 0x2000;
250 	static glw::GLushort	   value	 = 0x1234;
251 
252 	GLdouble	   fraction = ((GLdouble)value) / ((GLdouble)max_value);
253 	const GLdouble range	= max - min;
254 
255 	value = static_cast<glw::GLushort>((max_value <= value) ? 0 : value + 1);
256 
257 	return min + fraction * range;
258 }
259 
260 /** Throws tcu::NotSupportedError if requested extensions is not available.
261  *
262  **/
RequireExtension(const GLchar * extension_name) const263 void Base::RequireExtension(const GLchar* extension_name) const
264 {
265 	const std::vector<std::string>& extensions = m_context.getContextInfo().getExtensions();
266 
267 	if (std::find(extensions.begin(), extensions.end(), extension_name) == extensions.end())
268 	{
269 		std::string message = "Required extension is not supported: ";
270 		message.append(extension_name);
271 
272 		throw tcu::NotSupportedError(message);
273 	}
274 }
275 
276 /** Implementation of conformance test "1", description follows.
277  *
278  *  Make sure the following errors are generated as specified:
279  *
280  *  a) GL_INVALID_VALUE should be generated by:
281  *     I.    glVertexAttribL1d     ()
282  *     II.   glVertexAttribL2d     ()
283  *     III.  glVertexAttribL3d     ()
284  *     IV.   glVertexAttribL4d     ()
285  *     V.    glVertexAttribL1dv    ()
286  *     VI.   glVertexAttribL2dv    ()
287  *     VII.  glVertexAttribL3dv    ()
288  *     VIII. glVertexAttribL4dv    ()
289  *     IX.   glVertexAttribLPointer()
290  *
291  *     if <index> is greater than or equal to GL_MAX_VERTEX_ATTRIBS;
292  *
293  *  b) GL_INVALID_ENUM should be generated by glVertexAttribLPointer()
294  *     if <type> is not GL_DOUBLE;
295  *
296  *  c) GL_INVALID_VALUE should be generated by glVertexAttribLPointer()
297  *     if <size> is not 1, 2, 3 or 4.
298  *
299  *  d) GL_INVALID_VALUE should be generated by glVertexAttribLPointer()
300  *     if <stride> is negative.
301  *
302  *  e) GL_INVALID_OPERATION should be generated by glVertexAttribLPointer()
303  *     if zero is bound to the GL_ARRAY_BUFFER buffer object binding
304  *     point and the <pointer> argument is not NULL.
305  *
306  *  f) GL_INVALID_OPERATION should be generated by glGetVertexAttribLdv()
307  *     if <index> is zero.
308  **/
309 class ApiErrorsTest : public Base
310 {
311 public:
312 	/* Public methods */
313 	ApiErrorsTest(deqp::Context& context);
314 
~ApiErrorsTest()315 	virtual ~ApiErrorsTest()
316 	{
317 	}
318 
319 	/* Public methods inheritated from TestCase */
320 	virtual void						 deinit();
321 	virtual tcu::TestNode::IterateResult iterate();
322 
323 private:
324 	/* Private methods */
325 	void invalidEnum(bool& result);
326 	void invalidOperation(bool& result);
327 	void invalidValue(bool& result);
328 	void verifyError(GLenum expected_error, const char* function_name, int line_number, bool& result);
329 
330 	/* Private fields */
331 	GLuint m_vertex_array_object_id;
332 };
333 
334 /** Constructor
335  *
336  * @param context CTS context instance
337  **/
ApiErrorsTest(deqp::Context & context)338 ApiErrorsTest::ApiErrorsTest(deqp::Context& context)
339 	: Base(context, "api_errors", "Verify that API routines provoke errors as specified"), m_vertex_array_object_id(0)
340 {
341 	/* Nothing to be done here */
342 }
343 
deinit()344 void ApiErrorsTest::deinit()
345 {
346 	/* Delete VAO */
347 	if (0 != m_vertex_array_object_id)
348 	{
349 		gl.bindVertexArray(0);
350 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
351 		m_vertex_array_object_id = 0;
352 	}
353 }
354 
355 /** Execute test
356  *
357  * @return tcu::TestNode::STOP
358  **/
iterate()359 tcu::TestNode::IterateResult ApiErrorsTest::iterate()
360 {
361 	IterateStart();
362 
363 	bool result = true;
364 
365 	RequireExtension("GL_ARB_vertex_attrib_64bit");
366 
367 	gl.genVertexArrays(1, &m_vertex_array_object_id);
368 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
369 
370 	gl.bindVertexArray(m_vertex_array_object_id);
371 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
372 
373 	invalidEnum(result);
374 	invalidOperation(result);
375 	invalidValue(result);
376 
377 	/* Done */
378 	return IterateStop(result);
379 }
380 
381 /** Test if GL_INVALID_ENUM error is provoked as expected
382  *
383  * @param result If test fails result is set to false, not modified otherwise.
384  **/
invalidEnum(bool & result)385 void ApiErrorsTest::invalidEnum(bool& result)
386 {
387 	/*
388 	 *b) GL_INVALID_ENUM should be generated by glVertexAttribLPointer()
389 	 *   if <type> is not GL_DOUBLE;
390 	 */
391 
392 	static const GLenum type_array[] = { GL_BYTE,
393 										 GL_UNSIGNED_BYTE,
394 										 GL_SHORT,
395 										 GL_UNSIGNED_SHORT,
396 										 GL_INT,
397 										 GL_UNSIGNED_INT,
398 										 GL_HALF_FLOAT,
399 										 GL_FLOAT,
400 										 GL_FIXED,
401 										 GL_INT_2_10_10_10_REV,
402 										 GL_UNSIGNED_INT_2_10_10_10_REV,
403 										 GL_UNSIGNED_INT_10F_11F_11F_REV };
404 	static const GLuint type_array_length = sizeof(type_array) / sizeof(type_array[0]);
405 
406 	for (GLuint i = 0; i < type_array_length; ++i)
407 	{
408 		const GLenum type = type_array[i];
409 
410 		std::stringstream message;
411 		message << "VertexAttribLPointer(..., " << glu::getTypeName(type) << " /* type */, ...)";
412 
413 		gl.vertexAttribLPointer(1 /*index */, 4 /*size */, type, 0 /* stride */, 0 /* pointer */);
414 		verifyError(GL_INVALID_ENUM, message.str().c_str(), __LINE__, result);
415 	}
416 
417 	gl.vertexAttribLPointer(1 /* index */, 4 /*size */, GL_DOUBLE, 0 /* stride */, 0 /* pointer */);
418 	verifyError(GL_NO_ERROR, "VertexAttribLPointer(..., GL_DOUBLE /* type */, ...)", __LINE__, result);
419 }
420 
421 /** Test if GL_INVALID_OPERATON error is provoked as expected
422  *
423  * @param result If test fails result is set to false, not modified otherwise.
424  **/
invalidOperation(bool & result)425 void ApiErrorsTest::invalidOperation(bool& result)
426 {
427 
428 	/*
429 	 *e) GL_INVALID_OPERATION should be generated by glVertexAttribLPointer()
430 	 *   if zero is bound to the GL_ARRAY_BUFFER buffer object binding
431 	 *   point and the <pointer> argument is not NULL.
432 	 */
433 	static const GLvoid* pointer_array[]	  = { (GLvoid*)1, (GLvoid*)4, (GLvoid*)-16 };
434 	static const GLuint  pointer_array_length = sizeof(pointer_array) / sizeof(pointer_array[0]);
435 
436 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
437 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
438 
439 	for (GLuint i = 0; i < pointer_array_length; ++i)
440 	{
441 		const GLvoid* pointer = pointer_array[i];
442 
443 		std::stringstream message;
444 		message << "VertexAttribLPointer(..., " << pointer << " /* pointer */)";
445 
446 		gl.vertexAttribLPointer(1 /* index */, 4 /*size */, GL_DOUBLE, 0 /* stride */, pointer);
447 		verifyError(GL_INVALID_OPERATION, message.str().c_str(), __LINE__, result);
448 	}
449 }
450 
451 /** Test if GL_INVALID_VALUE error is provoked as expected
452  *
453  * @param result If test fails result is set to false, not modified otherwise.
454  **/
invalidValue(bool & result)455 void ApiErrorsTest::invalidValue(bool& result)
456 {
457 	GLint		   max_vertex_attribs = GetMaxVertexAttribs();
458 	const GLdouble vector[4]		  = { 0.0, 0.0, 0.0, 0.0 };
459 
460 	/*
461 	 * a) GL_INVALID_VALUE should be generated by:
462 	 *    I.    glVertexAttribL1d     ()
463 	 *    II.   glVertexAttribL2d     ()
464 	 *    III.  glVertexAttribL3d     ()
465 	 *    IV.   glVertexAttribL4d     ()
466 	 *    V.    glVertexAttribL1dv    ()
467 	 *    VI.   glVertexAttribL2dv    ()
468 	 *    VII.  glVertexAttribL3dv    ()
469 	 *    VIII. glVertexAttribL4dv    ()
470 	 *    IX.   glVertexAttribLPointer()
471 	 *
472 	 *    if <index> is greater than or equal to GL_MAX_VERTEX_ATTRIBS;
473 	 */
474 	gl.vertexAttribL1d(max_vertex_attribs, 0.0);
475 	verifyError(GL_INVALID_VALUE, "VertexAttribL1d(GL_MAX_VERTEX_ATTRIBS, ...)", __LINE__, result);
476 
477 	gl.vertexAttribL1d(max_vertex_attribs + 1, 0.0);
478 	verifyError(GL_INVALID_VALUE, "VertexAttribL1d(GL_MAX_VERTEX_ATTRIBS + 1, ...)", __LINE__, result);
479 
480 	gl.vertexAttribL2d(max_vertex_attribs, 0.0, 0.0);
481 	verifyError(GL_INVALID_VALUE, "VertexAttribL2d(GL_MAX_VERTEX_ATTRIBS, ...)", __LINE__, result);
482 
483 	gl.vertexAttribL2d(max_vertex_attribs + 1, 0.0, 0.0);
484 	verifyError(GL_INVALID_VALUE, "VertexAttribL2d(GL_MAX_VERTEX_ATTRIBS + 1, ...)", __LINE__, result);
485 
486 	gl.vertexAttribL3d(max_vertex_attribs, 0.0, 0.0, 0.0);
487 	verifyError(GL_INVALID_VALUE, "VertexAttribL3d(GL_MAX_VERTEX_ATTRIBS, ...)", __LINE__, result);
488 
489 	gl.vertexAttribL3d(max_vertex_attribs + 1, 0.0, 0.0, 0.0);
490 	verifyError(GL_INVALID_VALUE, "VertexAttribL3d(GL_MAX_VERTEX_ATTRIBS + 1, ...)", __LINE__, result);
491 
492 	gl.vertexAttribL4d(max_vertex_attribs, 0.0, 0.0, 0.0, 0.0);
493 	verifyError(GL_INVALID_VALUE, "VertexAttribL4d(GL_MAX_VERTEX_ATTRIBS, ...)", __LINE__, result);
494 
495 	gl.vertexAttribL4d(max_vertex_attribs + 1, 0.0, 0.0, 0.0, 0.0);
496 	verifyError(GL_INVALID_VALUE, "VertexAttribL4d(GL_MAX_VERTEX_ATTRIBS + 1, ...)", __LINE__, result);
497 
498 	gl.vertexAttribL1dv(max_vertex_attribs, vector);
499 	verifyError(GL_INVALID_VALUE, "VertexAttribL1dv(GL_MAX_VERTEX_ATTRIBS, ...)", __LINE__, result);
500 
501 	gl.vertexAttribL1dv(max_vertex_attribs + 1, vector);
502 	verifyError(GL_INVALID_VALUE, "VertexAttribL1dv(GL_MAX_VERTEX_ATTRIBS + 1, ...)", __LINE__, result);
503 
504 	gl.vertexAttribL2dv(max_vertex_attribs, vector);
505 	verifyError(GL_INVALID_VALUE, "VertexAttribL2dv(GL_MAX_VERTEX_ATTRIBS, ...)", __LINE__, result);
506 
507 	gl.vertexAttribL2dv(max_vertex_attribs + 1, vector);
508 	verifyError(GL_INVALID_VALUE, "VertexAttribL2dv(GL_MAX_VERTEX_ATTRIBS + 1, ...)", __LINE__, result);
509 
510 	gl.vertexAttribL3dv(max_vertex_attribs, vector);
511 	verifyError(GL_INVALID_VALUE, "VertexAttribL3dv(GL_MAX_VERTEX_ATTRIBS, ...)", __LINE__, result);
512 
513 	gl.vertexAttribL3dv(max_vertex_attribs + 1, vector);
514 	verifyError(GL_INVALID_VALUE, "VertexAttribL3dv(GL_MAX_VERTEX_ATTRIBS + 1, ...)", __LINE__, result);
515 
516 	gl.vertexAttribL4dv(max_vertex_attribs, vector);
517 	verifyError(GL_INVALID_VALUE, "VertexAttribL4dv(GL_MAX_VERTEX_ATTRIBS, ...)", __LINE__, result);
518 
519 	gl.vertexAttribL4dv(max_vertex_attribs + 1, vector);
520 	verifyError(GL_INVALID_VALUE, "VertexAttribL4dv(GL_MAX_VERTEX_ATTRIBS + 1, ...)", __LINE__, result);
521 
522 	gl.vertexAttribLPointer(max_vertex_attribs, 4 /*size */, GL_DOUBLE, 0 /* stride */, 0 /* pointer */);
523 	verifyError(GL_INVALID_VALUE, "VertexAttribLPointer(GL_MAX_VERTEX_ATTRIBS, ...)", __LINE__, result);
524 
525 	gl.vertexAttribLPointer(max_vertex_attribs + 1, 4 /*size */, GL_DOUBLE, 0 /* stride */, 0 /* pointer */);
526 	verifyError(GL_INVALID_VALUE, "VertexAttribLPointer(GL_MAX_VERTEX_ATTRIBS + 1, ...)", __LINE__, result);
527 
528 	/*
529 	 *c) GL_INVALID_VALUE should be generated by glVertexAttribLPointer()
530 	 *if <size> is not 1, 2, 3 or 4.
531 	 */
532 	gl.vertexAttribLPointer(1, 0 /*size */, GL_DOUBLE, 0 /* stride */, 0 /* pointer */);
533 	verifyError(GL_INVALID_VALUE, "VertexAttribLPointer(..., 0 /* size */, ...)", __LINE__, result);
534 
535 	gl.vertexAttribLPointer(1, 5 /*size */, GL_DOUBLE, 0 /* stride */, 0 /* pointer */);
536 	verifyError(GL_INVALID_VALUE, "VertexAttribLPointer(..., 5 /* size */, ...)", __LINE__, result);
537 
538 	/*
539 	 *d) GL_INVALID_VALUE should be generated by glVertexAttribLPointer()
540 	 *   if <stride> is negative.
541 	 */
542 	gl.vertexAttribLPointer(1, 4 /*size */, GL_DOUBLE, -1 /* stride */, 0 /* pointer */);
543 	verifyError(GL_INVALID_VALUE, "VertexAttribLPointer(..., -1 /* stride */, ...)", __LINE__, result);
544 
545 	gl.vertexAttribLPointer(1, 4 /*size */, GL_DOUBLE, -4 /* stride */, 0 /* pointer */);
546 	verifyError(GL_INVALID_VALUE, "VertexAttribLPointer(..., -4 /* stride */, ...)", __LINE__, result);
547 }
548 
549 /** Verify that GetError returns expected error code. In case of failure logs error message.
550  *
551  * @param expected_error Expected error code
552  * @param function_name  Name of function to log in case of error
553  * @param line_number    Line number, for reference
554  * @param result         Result of verification, set to false in case of failure, not modified otherwise
555  **/
verifyError(GLenum expected_error,const char * function_name,int line_number,bool & result)556 void ApiErrorsTest::verifyError(GLenum expected_error, const char* function_name, int line_number, bool& result)
557 {
558 	GLenum error = gl.getError();
559 
560 	if (expected_error != error)
561 	{
562 		m_log << tcu::TestLog::Section("Error", "");
563 
564 		m_log << tcu::TestLog::Message << "GetError returned: " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
565 
566 		m_log << tcu::TestLog::Message << "Expected: " << glu::getErrorStr(expected_error) << tcu::TestLog::EndMessage;
567 
568 		m_log << tcu::TestLog::Message << "Operation: " << function_name << tcu::TestLog::EndMessage;
569 
570 		m_log << tcu::TestLog::Message << "File: " << __FILE__ << "@" << line_number << tcu::TestLog::EndMessage;
571 
572 		m_log << tcu::TestLog::EndSection;
573 
574 		result = false;
575 	}
576 }
577 
578 /** Implementation of conformance test "2", description follows.
579  *
580  *  Make sure that all available generic vertex attributes report
581  *  correct values when queried with corresponding glGetVertexAttribL*()
582  *  function, after they had been set with a glVertexAttribL*() call.
583  *  All double-precision floating-point setters and getters should
584  *  be checked, as enlisted below:
585  *
586  *  * glVertexAttribL1d ()
587  *  * glVertexAttribL2d ()
588  *  * glVertexAttribL3d ()
589  *  * glVertexAttribL4d ()
590  *  * glVertexAttribL1dv()
591  *  * glVertexAttribL2dv()
592  *  * glVertexAttribL3dv()
593  *  * glVertexAttribL4dv()
594  *
595  *  The test should also verify glGetVertexAttribiv() and
596  *  glGetVertexAttribLdv() report correct property values for all
597  *  vertex attribute arrays configured with glVertexAttribLPointer()
598  *  call. Two different configurations should be checked for each
599  *  VAA index.
600  **/
601 class GetVertexAttribTest : public Base
602 {
603 public:
604 	/* Public constructor and destructor */
605 	GetVertexAttribTest(deqp::Context& context);
606 
~GetVertexAttribTest()607 	virtual ~GetVertexAttribTest()
608 	{
609 	}
610 
611 	/* Public methods inheritated from TestCase */
612 	virtual void						 deinit();
613 	virtual tcu::TestNode::IterateResult iterate();
614 
615 private:
616 	/* Private types */
617 	/** Template class to store vertex attribute data
618 	 *
619 	 * @tparam SIZE Number of elements
620 	 **/
621 	template <GLuint SIZE>
622 	class vertexAttribute
623 	{
624 	public:
vertexAttribute(GLdouble min,GLdouble max)625 		vertexAttribute(GLdouble min, GLdouble max)
626 		{
627 			for (GLuint i = 0; i < SIZE; ++i)
628 			{
629 				m_array[i] = RandomDouble(min, max);
630 			}
631 		}
632 
633 		GLdouble m_array[SIZE];
634 	};
635 
636 	/* Private methods */
637 	/* checkVertexAttrib methods */
638 	template <GLuint SIZE>
639 	void checkVertexAttribLd(GLuint index, bool& result) const;
640 
641 	template <GLuint SIZE>
642 	void checkVertexAttribLdv(GLuint index, bool& result) const;
643 
644 	void checkVertexAttribLPointer(GLuint index, bool& result) const;
645 
646 	/* Wrappers for vertexAttribLd routines */
647 	template <GLuint SIZE>
648 	void vertexAttribLd(GLuint index, const vertexAttribute<SIZE>& attribute) const;
649 
650 	template <GLuint SIZE>
651 	void vertexAttribLdv(GLuint index, const vertexAttribute<SIZE>& attribute) const;
652 
653 	/* Utilities */
654 	bool compareDoubles(const GLdouble* a, const GLdouble* b, GLuint length) const;
655 
656 	void initTest();
657 
658 	bool verifyResults(GLuint index, GLenum pname, GLint expected_value) const;
659 
660 	bool verifyResults(const GLdouble* set_values, GLuint length, GLuint index, const char* function_name,
661 					   int line_number) const;
662 
663 	bool verifyPointerResults(const GLdouble* set_values, GLuint length, GLuint index, int line_number) const;
664 
665 	void logError(const GLdouble* set_values, const GLdouble* get_values, GLuint length, const char* function_name,
666 				  GLuint index, int line_number) const;
667 
668 	/* Private fields */
669 	const GLdouble		m_epsilon;
670 	static const GLuint m_n_iterations = 128;
671 	GLint				m_max_vertex_attribs;
672 	const GLdouble		m_min;
673 	const GLdouble		m_max;
674 
675 	/* GL objects */
676 	GLuint m_buffer_object_id;
677 	GLuint m_vertex_array_object_id;
678 };
679 
680 /** Constructor
681  *
682  * @param context CTS context
683  **/
GetVertexAttribTest(deqp::Context & context)684 GetVertexAttribTest::GetVertexAttribTest(deqp::Context& context)
685 	: Base(context, "get_vertex_attrib", "Verify that GetVertexAttribL* routines")
686 	, m_epsilon(0.0)
687 	, m_max_vertex_attribs(0)
688 	, m_min(-16.384)
689 	, m_max(16.384)
690 	, m_buffer_object_id(0)
691 	, m_vertex_array_object_id(0)
692 {
693 	/* Nothing to be done */
694 }
695 
696 /** Clean up after test
697  *
698  **/
deinit()699 void GetVertexAttribTest::deinit()
700 {
701 	if (0 != m_buffer_object_id)
702 	{
703 		gl.bindBuffer(GL_ARRAY_BUFFER, 0);
704 		gl.deleteBuffers(1, &m_buffer_object_id);
705 		m_buffer_object_id = 0;
706 	}
707 
708 	if (0 != m_vertex_array_object_id)
709 	{
710 		gl.bindVertexArray(0);
711 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
712 		m_vertex_array_object_id = 0;
713 	}
714 }
715 
716 /** Execute test
717  *
718  * @return tcu::TestNode::STOP
719  **/
iterate()720 tcu::TestNode::IterateResult GetVertexAttribTest::iterate()
721 {
722 	IterateStart();
723 
724 	bool result = true;
725 
726 	RequireExtension("GL_ARB_vertex_attrib_64bit");
727 
728 	initTest();
729 
730 	for (GLint i = 1; i < m_max_vertex_attribs; ++i)
731 	{
732 		checkVertexAttribLd<1>(i, result);
733 		checkVertexAttribLd<2>(i, result);
734 		checkVertexAttribLd<3>(i, result);
735 		checkVertexAttribLd<4>(i, result);
736 		checkVertexAttribLdv<1>(i, result);
737 		checkVertexAttribLdv<2>(i, result);
738 		checkVertexAttribLdv<3>(i, result);
739 		checkVertexAttribLdv<4>(i, result);
740 		checkVertexAttribLPointer(i, result);
741 	}
742 
743 	/* Done */
744 	return IterateStop(result);
745 }
746 
747 /** Verifies glVertexAttribLd routines
748  *
749  * @tparam SIZE Size of vertex attribute
750  *
751  * @param index  Index of vertex attribute, starts from 1.
752  * @param result Result of verification, set to false in case of failure, not modified otherwise.
753  **/
754 template <GLuint SIZE>
checkVertexAttribLd(GLuint index,bool & result) const755 void GetVertexAttribTest::checkVertexAttribLd(GLuint index, bool& result) const
756 {
757 	std::stringstream function_name;
758 
759 	function_name << "VertexAttribL" << SIZE << "d";
760 
761 	for (GLuint i = 0; i < m_n_iterations; ++i)
762 	{
763 		vertexAttribute<SIZE> vertex_attribute(m_min, m_max);
764 
765 		vertexAttribLd<SIZE>(index, vertex_attribute);
766 		GLU_EXPECT_NO_ERROR(gl.getError(), function_name.str().c_str());
767 
768 		if (false == verifyResults(vertex_attribute.m_array, SIZE, index, function_name.str().c_str(), __LINE__))
769 		{
770 			result = false;
771 			return;
772 		}
773 	}
774 }
775 
776 /** Verifies glVertexAttribLdv routines
777  *
778  * @tparam SIZE Size of vertex attribute
779  *
780  * @param index  Index of vertex attribute, starts from 1.
781  * @param result Result of verification, set to false in case of failure, not modified otherwise.
782  **/
783 template <GLuint SIZE>
checkVertexAttribLdv(GLuint index,bool & result) const784 void GetVertexAttribTest::checkVertexAttribLdv(GLuint index, bool& result) const
785 {
786 	std::stringstream function_name;
787 
788 	function_name << "VertexAttribL" << SIZE << "dv";
789 
790 	for (GLuint i = 0; i < m_n_iterations; ++i)
791 	{
792 		vertexAttribute<SIZE> vertex_attribute(m_min, m_max);
793 
794 		vertexAttribLdv<SIZE>(index, vertex_attribute);
795 		GLU_EXPECT_NO_ERROR(gl.getError(), function_name.str().c_str());
796 
797 		if (false == verifyResults(vertex_attribute.m_array, SIZE, index, function_name.str().c_str(), __LINE__))
798 		{
799 			result = false;
800 			return;
801 		}
802 	}
803 }
804 
805 /** Verifies glVertexAttribLPointer
806  *
807  * @param index  Index of vertex attribute, starts from 1.
808  * @param result Result of verification, set to false in case of failure, not modified otherwise.
809  **/
checkVertexAttribLPointer(GLuint index,bool & result) const810 void GetVertexAttribTest::checkVertexAttribLPointer(GLuint index, bool& result) const
811 {
812 	static const GLuint max_size   = 4;
813 	static const GLuint max_stride = 16;
814 
815 	gl.bindVertexArray(m_vertex_array_object_id);
816 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
817 
818 	gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_object_id);
819 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
820 
821 	for (GLuint size = 1; size <= max_size; ++size)
822 	{
823 		for (GLuint stride = 0; stride < max_stride; ++stride)
824 		{
825 			gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_object_id);
826 			GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
827 
828 			gl.vertexAttribLPointer(index, size, GL_DOUBLE, stride, (GLvoid*)0);
829 			GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribLPointer");
830 
831 			gl.bindBuffer(GL_ARRAY_BUFFER, 0);
832 			GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
833 
834 			if (false == verifyResults(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, m_buffer_object_id))
835 			{
836 				result = false;
837 			}
838 
839 			if (false == verifyResults(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE))
840 			{
841 				result = false;
842 			}
843 
844 			if (false == verifyResults(index, GL_VERTEX_ATTRIB_ARRAY_SIZE, size))
845 			{
846 				result = false;
847 			}
848 
849 			if (false == verifyResults(index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, stride))
850 			{
851 				result = false;
852 			}
853 
854 			if (false == verifyResults(index, GL_VERTEX_ATTRIB_ARRAY_TYPE, GL_DOUBLE))
855 			{
856 				result = false;
857 			}
858 
859 			if (false == verifyResults(index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_FALSE))
860 			{
861 				result = false;
862 			}
863 
864 			if (false == verifyResults(index, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_FALSE))
865 			{
866 				result = false;
867 			}
868 
869 			if (false == verifyResults(index, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 0))
870 			{
871 				result = false;
872 			}
873 		}
874 	}
875 }
876 
877 /** Wrapper of vertexAttribLd routines.
878  *
879  * @tparam SIZE Size of vertex attribute. Specialisation for 1.
880  *
881  * @param index     Index parameter
882  * @param attribute Vertex attribute data are taken from provided instance of vertexAttribute
883  **/
884 template <>
vertexAttribLd(GLuint index,const GetVertexAttribTest::vertexAttribute<1> & attribute) const885 void GetVertexAttribTest::vertexAttribLd<1>(GLuint										   index,
886 											const GetVertexAttribTest::vertexAttribute<1>& attribute) const
887 {
888 	gl.vertexAttribL1d(index, attribute.m_array[0]);
889 }
890 
891 /** Wrapper of vertexAttribLd routines.
892  *
893  * @tparam SIZE Size of vertex attribute. Specialisation for 2.
894  *
895  * @param index     Index parameter
896  * @param attribute Vertex attribute data are taken from provided instance of vertexAttribute
897  **/
898 template <>
vertexAttribLd(GLuint index,const GetVertexAttribTest::vertexAttribute<2> & attribute) const899 void GetVertexAttribTest::vertexAttribLd<2>(GLuint										   index,
900 											const GetVertexAttribTest::vertexAttribute<2>& attribute) const
901 {
902 	gl.vertexAttribL2d(index, attribute.m_array[0], attribute.m_array[1]);
903 }
904 
905 /** Wrapper of vertexAttribLd routines.
906  *
907  * @tparam SIZE Size of vertex attribute. Specialisation for 3.
908  *
909  * @param index     Index parameter
910  * @param attribute Vertex attribute data are taken from provided instance of vertexAttribute
911  **/
912 template <>
vertexAttribLd(GLuint index,const GetVertexAttribTest::vertexAttribute<3> & attribute) const913 void GetVertexAttribTest::vertexAttribLd<3>(GLuint										   index,
914 											const GetVertexAttribTest::vertexAttribute<3>& attribute) const
915 {
916 	gl.vertexAttribL3d(index, attribute.m_array[0], attribute.m_array[1], attribute.m_array[2]);
917 }
918 
919 /** Wrapper of vertexAttribLd routines.
920  *
921  * @tparam SIZE Size of vertex attribute. Specialisation for 4.
922  *
923  * @param index     Index parameter
924  * @param attribute Vertex attribute data are taken from provided instance of vertexAttribute
925  **/
926 template <>
vertexAttribLd(GLuint index,const GetVertexAttribTest::vertexAttribute<4> & attribute) const927 void GetVertexAttribTest::vertexAttribLd<4>(GLuint										   index,
928 											const GetVertexAttribTest::vertexAttribute<4>& attribute) const
929 {
930 	gl.vertexAttribL4d(index, attribute.m_array[0], attribute.m_array[1], attribute.m_array[2], attribute.m_array[3]);
931 }
932 
933 /** Wrapper of vertexAttribLdv routines.
934  *
935  * @tparam SIZE Size of vertex attribute. Specialisation for 1.
936  *
937  * @param index     Index parameter
938  * @param attribute Vertex attribute data are taken from provided instance of vertexAttribute
939  **/
940 template <>
vertexAttribLdv(GLuint index,const GetVertexAttribTest::vertexAttribute<1> & attribute) const941 void GetVertexAttribTest::vertexAttribLdv<1>(GLuint											index,
942 											 const GetVertexAttribTest::vertexAttribute<1>& attribute) const
943 {
944 	gl.vertexAttribL1dv(index, attribute.m_array);
945 }
946 
947 /** Wrapper of vertexAttribLdv routines.
948  *
949  * @tparam SIZE Size of vertex attribute. Specialisation for 2.
950  *
951  * @param index     Index parameter
952  * @param attribute Vertex attribute data are taken from provided instance of vertexAttribute
953  **/
954 template <>
vertexAttribLdv(GLuint index,const GetVertexAttribTest::vertexAttribute<2> & attribute) const955 void GetVertexAttribTest::vertexAttribLdv<2>(GLuint											index,
956 											 const GetVertexAttribTest::vertexAttribute<2>& attribute) const
957 {
958 	gl.vertexAttribL2dv(index, attribute.m_array);
959 }
960 
961 /** Wrapper of vertexAttribLdv routines.
962  *
963  * @tparam SIZE Size of vertex attribute. Specialisation for 3.
964  *
965  * @param index     Index parameter
966  * @param attribute Vertex attribute data are taken from provided instance of vertexAttribute
967  **/
968 template <>
vertexAttribLdv(GLuint index,const GetVertexAttribTest::vertexAttribute<3> & attribute) const969 void GetVertexAttribTest::vertexAttribLdv<3>(GLuint											index,
970 											 const GetVertexAttribTest::vertexAttribute<3>& attribute) const
971 {
972 	gl.vertexAttribL3dv(index, attribute.m_array);
973 }
974 
975 /** Wrapper of vertexAttribLdv routines.
976  *
977  * @tparam SIZE Size of vertex attribute. Specialisation for 4.
978  *
979  * @param index     Index parameter
980  * @param attribute Vertex attribute data are taken from provided instance of vertexAttribute
981  **/
982 template <>
vertexAttribLdv(GLuint index,const GetVertexAttribTest::vertexAttribute<4> & attribute) const983 void GetVertexAttribTest::vertexAttribLdv<4>(GLuint											index,
984 											 const GetVertexAttribTest::vertexAttribute<4>& attribute) const
985 {
986 	gl.vertexAttribL4dv(index, attribute.m_array);
987 }
988 
989 /** Compare two arrays of doubles
990  *
991  * @param a      First array of doubles
992  * @param b      Second array of doubles
993  * @param length Length of arrays
994  *
995  * @return true if arrays are considered equal, false otherwise
996  **/
compareDoubles(const GLdouble * a,const GLdouble * b,GLuint length) const997 bool GetVertexAttribTest::compareDoubles(const GLdouble* a, const GLdouble* b, GLuint length) const
998 {
999 	for (GLuint i = 0; i < length; ++i)
1000 	{
1001 		if ((b[i] > a[i] + m_epsilon) || (b[i] < a[i] - m_epsilon))
1002 		{
1003 			return false;
1004 		}
1005 	}
1006 
1007 	return true;
1008 }
1009 
1010 /** Prepare buffer and vertex array object, get max vertex attributes
1011  *
1012  **/
initTest()1013 void GetVertexAttribTest::initTest()
1014 {
1015 	gl.genBuffers(1, &m_buffer_object_id);
1016 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
1017 
1018 	gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_object_id);
1019 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
1020 
1021 	gl.bufferData(GL_ARRAY_BUFFER, 16 * sizeof(GLdouble), 0, GL_DYNAMIC_DRAW);
1022 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferStorage");
1023 
1024 	gl.genVertexArrays(1, &m_vertex_array_object_id);
1025 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
1026 
1027 	m_max_vertex_attribs = GetMaxVertexAttribs();
1028 }
1029 
1030 /** Logs message informing that values got with GetVertexAttribLdv do not match set with "function_name"
1031  *
1032  * @param set_values    Values set with "function_name"
1033  * @param get_values    Values extracted with GetVertexAttribLdv
1034  * @param length        Length of "get/set_values" arrays
1035  * @param function_name Name of function used to set vertex attributes
1036  * @param index         Index of vertex attribute
1037  * @param line_number   Line number refereing to location of "function_name"
1038  **/
logError(const GLdouble * set_values,const GLdouble * get_values,GLuint length,const char * function_name,GLuint index,int line_number) const1039 void GetVertexAttribTest::logError(const GLdouble* set_values, const GLdouble* get_values, GLuint length,
1040 								   const char* function_name, GLuint index, int line_number) const
1041 {
1042 	m_log << tcu::TestLog::Section("Error", "");
1043 
1044 	tcu::MessageBuilder message = m_log << tcu::TestLog::Message;
1045 	message << "Values set with " << function_name << " [";
1046 
1047 	for (GLuint i = 0; i < length; ++i)
1048 	{
1049 		message << std::setprecision(24) << set_values[i];
1050 
1051 		if (length != i + 1)
1052 		{
1053 			message << ", ";
1054 		}
1055 	}
1056 
1057 	message << "]" << tcu::TestLog::EndMessage;
1058 
1059 	message = m_log << tcu::TestLog::Message;
1060 	message << "Values got with GetVertexAttribLdv"
1061 			<< " [";
1062 
1063 	for (GLuint i = 0; i < length; ++i)
1064 	{
1065 		message << std::setprecision(24) << get_values[i];
1066 
1067 		if (length != i + 1)
1068 		{
1069 			message << ", ";
1070 		}
1071 	}
1072 
1073 	message << "]" << tcu::TestLog::EndMessage;
1074 
1075 	m_log << tcu::TestLog::Message << "Index: " << index << tcu::TestLog::EndMessage;
1076 
1077 	m_log << tcu::TestLog::Message << "File: " << __FILE__ << "@" << line_number << tcu::TestLog::EndMessage;
1078 
1079 	m_log << tcu::TestLog::EndSection;
1080 }
1081 
1082 /** Verify results of vertexAttribLPointer
1083  *
1084  * @param index          Index of vertex attribute
1085  * @param pname          Parameter name to be querried with getVertexAttribiv and getVertexAttribLdv
1086  * @param expected_value Expected valued
1087  *
1088  * @return true if Results match expected_value, false otherwise
1089  **/
verifyResults(GLuint index,GLenum pname,GLint expected_value) const1090 bool GetVertexAttribTest::verifyResults(GLuint index, GLenum pname, GLint expected_value) const
1091 {
1092 	GLint	params_getVertexAttribiv  = 0;
1093 	GLdouble params_getVertexAttribLdv = 0.0;
1094 
1095 	gl.getVertexAttribiv(index, pname, &params_getVertexAttribiv);
1096 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetVertexAttribiv");
1097 
1098 	gl.getVertexAttribLdv(index, pname, &params_getVertexAttribLdv);
1099 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetVertexAttribLdv");
1100 
1101 	if ((expected_value != params_getVertexAttribiv) || (expected_value != params_getVertexAttribLdv))
1102 	{
1103 		m_log << tcu::TestLog::Section("Error", "");
1104 
1105 		m_log << tcu::TestLog::Message << "GetVertexAttribiv(" << index << "/* index */, "
1106 			  << glu::getVertexAttribParameterNameName(pname) << "/* pname */)" << tcu::TestLog::EndMessage;
1107 
1108 		m_log << tcu::TestLog::Message << "Result: " << params_getVertexAttribiv << tcu::TestLog::EndMessage;
1109 
1110 		m_log << tcu::TestLog::Message << "GetVertexAttribLdv(" << index << "/* index */, "
1111 			  << glu::getVertexAttribParameterNameName(pname) << "/* pname */)" << tcu::TestLog::EndMessage;
1112 
1113 		m_log << tcu::TestLog::Message << "Result: " << params_getVertexAttribLdv << tcu::TestLog::EndMessage;
1114 
1115 		m_log << tcu::TestLog::Message << "Expected: " << expected_value << tcu::TestLog::EndMessage;
1116 
1117 		m_log << tcu::TestLog::Message << "File: " << __FILE__ << "@" << __LINE__ << tcu::TestLog::EndMessage;
1118 
1119 		m_log << tcu::TestLog::EndSection;
1120 
1121 		return false;
1122 	}
1123 
1124 	return true;
1125 }
1126 
1127 /** Verify results of vertexAttribLdv routines
1128  *
1129  * @param set_values    Values set with vertexAttribLdv
1130  * @param length        Length of "set_values" array
1131  * @param index         Index of vertex attribute
1132  * @param function_name Name of function used to set, it will be used for error logging
1133  * @param line_number   Line number refering to location of "function_name", used to log errors
1134  *
1135  * @return true if results match set values, false otherwise
1136  **/
verifyResults(const GLdouble * set_values,GLuint length,GLuint index,const char * function_name,int line_number) const1137 bool GetVertexAttribTest::verifyResults(const GLdouble* set_values, GLuint length, GLuint index,
1138 										const char* function_name, int line_number) const
1139 {
1140 	GLdouble results[4] = { 0.0, 0.0, 0.0, 0.0 };
1141 
1142 	gl.getVertexAttribLdv(index, GL_CURRENT_VERTEX_ATTRIB, results);
1143 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetVertexAttribLdv");
1144 
1145 	if (false == compareDoubles(set_values, results, length))
1146 	{
1147 		logError(set_values, results, length, function_name, index, line_number);
1148 
1149 		return false;
1150 	}
1151 
1152 	return true;
1153 }
1154 
1155 /** Implementation of conformance test "3", description follows.
1156  *
1157  *  Verify that a total of GL_MAX_VERTEX_ATTRIBS double and dvec2,
1158  *  (GL_MAX_VERTEX_ATTRIBS / 2) dvec3, dvec4 and dmat2,
1159  *  (GL_MAX_VERTEX_ATTRIBS / 3) dmat3x2,
1160  *  (GL_MAX_VERTEX_ATTRIBS / 4) dmat4x2, dmat2x3 and dmat2x4,
1161  *  (GL_MAX_VERTEX_ATTRIBS / 6) dmat3 and dmat3x4,
1162  *  (GL_MAX_VERTEX_ATTRIBS / 8) dmat4x3 and dmat4,
1163  *  attributes can be used in each shader stage at the same time.
1164  *
1165  *  The test should run in 7 iterations:
1166  *
1167  *  a) In the first iteration, (GL_MAX_VERTEX_ATTRIBS / 2) double
1168  *      attributes and (GL_MAX_VERTEX_ATTRIBS / 2) dvec2 attributes
1169  *      should be defined in a vertex shader. The test should verify
1170  *      the values exposed by these attributes and write 1 to an
1171  *      output variable if all attribute values are found to be
1172  *      correct, or set it to 0 if at least one of the retrieved
1173  *      values is found invalid.
1174  *
1175  *      Double attributes should be assigned the value:
1176  *                  (n_attribute + gl_VertexID * 2)
1177  *
1178  *      Dvec2 attribute components should be assigned the following
1179  *      vector values:
1180  *                  (n_attribute + gl_VertexID * 3 + 1,
1181  *                  n_attribute + gl_VertexID * 3 + 2)
1182  *
1183  *  b) In the second iteration, (GL_MAX_VERTEX_ATTRIBS / 4) dvec3
1184  *      and (GL_MAX_VERTEX_ATTRIBS / 4) dvec4 attributes should be
1185  *      defined in a vertex shader. Verification of the data exposed
1186  *      by these input variables should be performed as in step a),
1187  *      with an exception of the values passed through the attributes.
1188  *
1189  *      Dvec3 attribute components should be assigned the following
1190  *      vector values:
1191  *                  (n_attribute + gl_VertexID * 3 + 0,
1192  *                  n_attribute + gl_VertexID * 3 + 1,
1193  *                  n_attribute + gl_VertexID * 3 + 2).
1194  *
1195  *      Dvec4 attribute components should be assigned the following
1196  *      vector values:
1197  *                  (n_attribute + gl_VertexID * 4 + 0,
1198  *                  n_attribute + gl_VertexID * 4 + 1,
1199  *                  n_attribute + gl_VertexID * 4 + 2,
1200  *                  n_attribute + gl_VertexID * 4 + 3).
1201  *
1202  *      n_attribute corresponds to the ordinal number of each attribute,
1203  *      as defined in the shader.
1204  *
1205  *  c) In the third iteration, (GL_MAX_VERTEX_ATTRIBS / 2) dmat2 attributes
1206  *      should be defined in a vertex shader. Verification of the data exposed
1207  *      by these input variables should be performed as in step a), with an
1208  *      exception of the values passed through the attributes.
1209  *
1210  *      Subsequent matrix elements should be assigned the following value:
1211  *              (n_type + n_attribute + gl_VertexID * 16 + n_value)
1212  *
1213  *      n_type corresponds to the ordinal number of type as per the
1214  *      order at the beginning of the paragraph.
1215  *      n_value corresponds to the ordinal number of the element.
1216  *
1217  *  d) In the fourth iteration, (GL_MAX_VERTEX_ATTRIBS / 8) dmat3x2 and
1218  *      (GL_MAX_VERTEX_ATTRIBS / 8) dmat4x2 attributes should be defined in a
1219  *      vertex shader. Verification of the data exposed by these input
1220  *      variables should be performed as in step a), with an exception of the
1221  *      values passed through the attributes.
1222  *
1223  *      Use the same element values as in step c)
1224  *
1225  *  e) In the fifth iteration, (GL_MAX_VERTEX_ATTRIBS / 8) dmat2x3 and
1226  *      (GL_MAX_VERTEX_ATTRIBS / 8) dmat2x4 attributes should be defined in a
1227  *      vertex shader. Verification of the data exposed by these input
1228  *      variables should be performed as in step a), with an exception of the
1229  *      values passed through the attributes.
1230  *
1231  *      Use the same element values as in step c)
1232  *
1233  *  f) In the sixth iteration, (GL_MAX_VERTEX_ATTRIBS / 12) dmat3 and
1234  *      (GL_MAX_VERTEX_ATTRIBS / 12) dmat3x4 attributes should be defined in a
1235  *      vertex shader. Verification of the data exposed by these input
1236  *      variables should be performed as in step a), with an exception of the
1237  *      values passed through the attributes.
1238  *
1239  *      Use the same element values as in step c)
1240  *
1241  *  g) In the seventh iteration, (GL_MAX_VERTEX_ATTRIBS / 16) dmat4x3 and
1242  *      (GL_MAX_VERTEX_ATTRIBS / 16) dmat4 attributes should be defined in a
1243  *      vertex shader. Verification of the data exposed by these input
1244  *      variables should be performed as in step a), with an exception of the
1245  *      values passed through the attributes.
1246  *
1247  *      Use the same element values as in step c)
1248  *
1249  *  h) Modify the language of cases a) - g), so that instead of separate
1250  *      attributes, all attributes of the same type are now a single arrayed
1251  *      attribute.
1252  *
1253  *  Vertex shaders from both iterations should be used to form two program
1254  *  objects. 1024 vertices should be used for a non-indiced GL_POINTS
1255  *  draw call, made using those two programs.
1256  *
1257  *  All glVertexAttribL*() and glVertexAttribLPointer() should be used for
1258  *  the purpose of the test. The following draw call API functions should be
1259  *  tested:
1260  *
1261  *  a) glDrawArrays()
1262  *  b) glDrawArraysInstanced(), primcount > 1, zero vertex attrib divisor
1263  *  c) glDrawArraysInstanced(), primcount > 1, non-zero vertex attrib divisor
1264  *  d) glDrawElements()
1265  *  e) glDrawElementsInstanced(), properties as in b)
1266  *  f) glDrawElementsInstanced(), properties as in c)
1267  *
1268  *  All shaders used by the test should come in two flavors:
1269  *
1270  *  - one where attribute locations are explicitly defined in the body;
1271  *  - the other one where attribute locations are to be assigned by
1272  *      the compiler.
1273  *
1274  *  For each shader, the test should make sure that all attributes have
1275  *  been assigned correct amount of locations. (eg: dvec4 attribute
1276  *  should be granted exactly one location).
1277  *
1278  *  Data stored in output variables should be XFBed to the test.
1279  *  The test passes if the retrieved values are found to be valid
1280  *  for all vertex shader invocations.
1281  **/
1282 
1283 class LimitTest : public Base
1284 {
1285 public:
1286 	/* Public constructor and destructor */
1287 	LimitTest(deqp::Context& context);
1288 
~LimitTest()1289 	virtual ~LimitTest()
1290 	{
1291 	}
1292 
1293 	/* Public methods inheritated from TestCase */
1294 	virtual void						 deinit();
1295 	virtual tcu::TestNode::IterateResult iterate();
1296 
1297 private:
1298 	/* Private types */
1299 	class programInfo
1300 	{
1301 	public:
1302 		programInfo(const glw::Functions& gl);
1303 		~programInfo();
1304 
1305 		GLuint m_fragment_shader_id;
1306 		GLuint m_program_id;
1307 		GLuint m_vertex_shader_id;
1308 
1309 	private:
1310 		const glw::Functions& gl;
1311 	};
1312 
1313 	struct attributeConfiguration
1314 	{
attributeConfigurationVertexAttrib64Bit::LimitTest::attributeConfiguration1315 		attributeConfiguration()
1316 			: m_n_attributes_per_group(0)
1317 			, m_n_elements(0)
1318 			, m_n_rows(0)
1319 			, m_n_types(0)
1320 			, m_type_names(0)
1321 			, m_vertex_length(0)
1322 		{
1323 			/* nothing to be done */
1324 		}
1325 
1326 		GLint				 m_n_attributes_per_group;
1327 		const GLint*		 m_n_elements;
1328 		const GLint*		 m_n_rows;
1329 		GLint				 m_n_types;
1330 		const GLchar* const* m_type_names;
1331 		GLint				 m_vertex_length;
1332 	};
1333 
1334 	typedef GLint _varyingType;
1335 
1336 	/* Private enums */
1337 	enum _iteration
1338 	{
1339 		DOUBLE_DVEC2,	// 1 + 1         = 2
1340 		DVEC3_DVEC4,	 // 2 + 2         = 4
1341 		DMAT2,			 // 2 * 1         = 2
1342 		DMAT3X2_DMAT4X2, // 3 * 1 + 4 * 1 = 8
1343 		DMAT2X3_DMAT2X4, // 2 * 2 + 2 * 2 = 8
1344 		DMAT3_DMAT3X4,   // 3 * 2 + 3 * 2 = 12
1345 		DMAT4X3_DMAT4	// 4 * 2 + 4 * 2 = 16
1346 	};
1347 
1348 	enum _attributeType
1349 	{
1350 		REGULAR,
1351 		PER_INSTANCE,
1352 		CONSTANT,
1353 	};
1354 
1355 	/*Private methods */
1356 	GLint calculateAttributeGroupOffset(const attributeConfiguration& configuration, GLint index) const;
1357 
1358 	GLint calculateAttributeLocation(const attributeConfiguration& configuration, GLint attribute, GLint n_type) const;
1359 
1360 	void calculateVertexLength(attributeConfiguration& configuration) const;
1361 
1362 	void configureAttribute(_iteration iteration, const attributeConfiguration& configuration, GLint n_type,
1363 							GLuint program_id, bool use_arrays, bool use_vertex_array) const;
1364 
1365 	void getProgramDetails(_iteration iteration, bool use_arrays, bool use_locations, bool use_vertex_attrib_divisor,
1366 						   std::string& out_varying_name, std::string& out_vertex_shader_code) const;
1367 
1368 	void getVertexArrayConfiguration(_iteration iteration, attributeConfiguration& out_configuration) const;
1369 
1370 	void logTestIterationAndConfig(_iteration iteration, _attributeType attribute_type, bool use_arrays,
1371 								   bool use_locations) const;
1372 
1373 	void prepareProgram(_iteration iteration, bool use_arrays, bool use_locations, bool use_vertex_attrib_divisor,
1374 						programInfo& programInfo);
1375 
1376 	void prepareVertexArray(_iteration iteration, _attributeType attribute_type, GLuint program_id,
1377 							bool use_arrays) const;
1378 
1379 	void prepareVertexArrayBuffer(_iteration iteration);
1380 
1381 	void setAttributes(_iteration iteration, const attributeConfiguration& configuration, GLuint vertex,
1382 					   std::vector<GLdouble>& out_buffer_data) const;
1383 
1384 	void setAttributes_a(const attributeConfiguration& configuration, GLint n_type, GLuint vertex,
1385 						 std::vector<GLdouble>& out_buffer_data) const;
1386 
1387 	void setAttributes_a_scalar(const attributeConfiguration& configuration, GLint n_type, GLuint vertex,
1388 								std::vector<GLdouble>& out_buffer_data) const;
1389 
1390 	void setAttributes_a_vec(const attributeConfiguration& configuration, GLint n_type, GLuint vertex,
1391 							 std::vector<GLdouble>& out_buffer_data) const;
1392 
1393 	void setAttributes_b(const attributeConfiguration& configuration, GLint n_type, GLuint vertex,
1394 						 std::vector<GLdouble>& out_buffer_dataa) const;
1395 
1396 	void setAttributes_c(const attributeConfiguration& configuration, GLint n_type, GLuint vertex,
1397 						 std::vector<GLdouble>& out_buffer_data) const;
1398 
1399 	bool testDrawArrays() const;
1400 	bool testDrawArraysInstanced() const;
1401 	bool testDrawElements() const;
1402 	bool testDrawElementsInstanced() const;
1403 	void testInit();
1404 	bool testIteration(_iteration iteration);
1405 
1406 	bool testProgram(_iteration iteration, GLuint program_id, bool use_arrays) const;
1407 
1408 	bool testProgramWithConstant(_iteration iteration, GLuint program_id, bool use_arrays) const;
1409 
1410 	bool testProgramWithDivisor(_iteration iteration, GLuint program_id, bool use_arrays) const;
1411 
1412 	bool verifyResult(bool use_instancing) const;
1413 
1414 	/* Private fields */
1415 	/* Constants */
1416 	static const GLint  m_array_attribute = -1;
1417 	static const GLuint m_n_instances	 = 16;
1418 	static const GLuint m_n_varyings	  = 1;
1419 	static const GLuint m_n_vertices	  = 1024;
1420 	static const GLuint m_transform_feedback_buffer_size =
1421 		sizeof(_varyingType) * m_n_instances * m_n_vertices * m_n_varyings;
1422 
1423 	/* GL objects */
1424 	GLuint m_element_array_buffer_id;
1425 	GLuint m_transoform_feedback_buffer_id;
1426 	GLuint m_vertex_array_buffer_id;
1427 	GLuint m_vertex_array_object_id;
1428 };
1429 
1430 /** Constructor
1431  *
1432  **/
programInfo(const glw::Functions & gl_functions)1433 LimitTest::programInfo::programInfo(const glw::Functions& gl_functions)
1434 	: m_fragment_shader_id(0), m_program_id(0), m_vertex_shader_id(0), gl(gl_functions)
1435 {
1436 	/* Nothing to be done here */
1437 }
1438 
1439 /** Destructor
1440  *
1441  **/
~programInfo()1442 LimitTest::programInfo::~programInfo()
1443 {
1444 	if (0 != m_program_id)
1445 	{
1446 		gl.deleteProgram(m_program_id);
1447 		m_program_id = 0;
1448 	}
1449 
1450 	if (0 != m_fragment_shader_id)
1451 	{
1452 		gl.deleteShader(m_fragment_shader_id);
1453 		m_fragment_shader_id = 0;
1454 	}
1455 
1456 	if (0 != m_vertex_shader_id)
1457 	{
1458 		gl.deleteShader(m_vertex_shader_id);
1459 		m_vertex_shader_id = 0;
1460 	}
1461 }
1462 
1463 /** Constructor
1464  *
1465  * @param context CTS context
1466  **/
LimitTest(deqp::Context & context)1467 LimitTest::LimitTest(deqp::Context& context)
1468 	: Base(context, "limits_test", "Verify that maximum allowed number of attribiutes can be used")
1469 	, m_element_array_buffer_id(0)
1470 	, m_transoform_feedback_buffer_id(0)
1471 	, m_vertex_array_buffer_id(0)
1472 	, m_vertex_array_object_id(0)
1473 {
1474 	/* Nothing to be done here */
1475 }
1476 
1477 /** Clean up after test
1478  *
1479  **/
deinit()1480 void LimitTest::deinit()
1481 {
1482 	/* Restore default settings */
1483 	if (0 != gl.disable)
1484 	{
1485 		gl.disable(GL_RASTERIZER_DISCARD);
1486 	}
1487 
1488 	/* Delete GL objects */
1489 	if (0 != m_element_array_buffer_id)
1490 	{
1491 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1492 		gl.deleteBuffers(1, &m_element_array_buffer_id);
1493 		m_element_array_buffer_id = 0;
1494 	}
1495 
1496 	if (0 != m_transoform_feedback_buffer_id)
1497 	{
1498 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1499 		gl.deleteBuffers(1, &m_transoform_feedback_buffer_id);
1500 		m_transoform_feedback_buffer_id = 0;
1501 	}
1502 
1503 	if (0 != m_vertex_array_buffer_id)
1504 	{
1505 		gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1506 		gl.deleteBuffers(1, &m_vertex_array_buffer_id);
1507 		m_vertex_array_buffer_id = 0;
1508 	}
1509 
1510 	if (0 != m_vertex_array_object_id)
1511 	{
1512 		gl.bindVertexArray(0);
1513 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
1514 		m_vertex_array_object_id = 0;
1515 	}
1516 }
1517 
1518 /** Execute test
1519  *
1520  * @return tcu::TestNode::STOP
1521  **/
iterate()1522 tcu::TestNode::IterateResult LimitTest::iterate()
1523 {
1524 	IterateStart();
1525 
1526 	bool result = true;
1527 
1528 	RequireExtension("GL_ARB_vertex_attrib_64bit");
1529 
1530 	testInit();
1531 
1532 	if (false == testIteration(DOUBLE_DVEC2))
1533 	{
1534 		result = false;
1535 	}
1536 
1537 	if (false == testIteration(DVEC3_DVEC4))
1538 	{
1539 		result = false;
1540 	}
1541 
1542 	if (false == testIteration(DMAT2))
1543 	{
1544 		result = false;
1545 	}
1546 
1547 	if (false == testIteration(DMAT3X2_DMAT4X2))
1548 	{
1549 		result = false;
1550 	}
1551 
1552 	if (false == testIteration(DMAT2X3_DMAT2X4))
1553 	{
1554 		result = false;
1555 	}
1556 
1557 	if (false == testIteration(DMAT3_DMAT3X4))
1558 	{
1559 		result = false;
1560 	}
1561 
1562 	if (false == testIteration(DMAT4X3_DMAT4))
1563 	{
1564 		result = false;
1565 	}
1566 
1567 	/* Done */
1568 	return IterateStop(result);
1569 }
1570 
1571 /** Calculate offset of "n_type" attributes group in doubles, tightly packed, for vertex buffer offsets
1572  *
1573  * @param configuration Attribute configuration
1574  * @param n_type        Attribute type ordinal number
1575  *
1576  * @return Calculated offset
1577  **/
calculateAttributeGroupOffset(const attributeConfiguration & configuration,GLint n_type) const1578 GLint LimitTest::calculateAttributeGroupOffset(const attributeConfiguration& configuration, GLint n_type) const
1579 {
1580 	GLint result = 0;
1581 
1582 	for (GLint i = 0; i < n_type; ++i)
1583 	{
1584 		result += configuration.m_n_attributes_per_group * configuration.m_n_elements[i];
1585 	}
1586 
1587 	return result;
1588 }
1589 
1590 /** Calculates attribute location for manually setting "layout(location =)".
1591  *  Results are in reveresed order of vertex buffer
1592  *
1593  * @param configuration Attribute configuration
1594  * @param attribute     Intex of attribute in "n_type" group
1595  * @param n_type        Ordinal number of type
1596  *
1597  * @return Calculated location
1598  **/
calculateAttributeLocation(const attributeConfiguration & configuration,GLint attribute,GLint n_type) const1599 GLint LimitTest::calculateAttributeLocation(const attributeConfiguration& configuration, GLint attribute,
1600 											GLint n_type) const
1601 {
1602 	const GLint n_types = configuration.m_n_types;
1603 	GLint		result  = 0;
1604 
1605 	/* Amount of location required for types after given "n_type" */
1606 	for (GLint i = n_types - 1; i > n_type; --i)
1607 	{
1608 		const GLint n_elements = configuration.m_n_elements[i];
1609 		const GLint n_rows	 = configuration.m_n_rows[i];
1610 		const GLint n_columns  = n_elements / n_rows;
1611 
1612 		result += n_columns * configuration.m_n_attributes_per_group;
1613 	}
1614 
1615 	/* Amount of locations required for attributes after given attribute in given "n_type" */
1616 	/* Arrayed attributes does not have any attributes after */
1617 	if (m_array_attribute != attribute)
1618 	{
1619 		const GLint n_elements = configuration.m_n_elements[n_type];
1620 		const GLint n_rows	 = configuration.m_n_rows[n_type];
1621 		const GLint n_columns  = n_elements / n_rows;
1622 
1623 		result += n_columns * (configuration.m_n_attributes_per_group - 1 - attribute);
1624 	}
1625 
1626 	/* Done */
1627 	return result;
1628 }
1629 
1630 /** Calculate vertex length in "doubles", tightly packed, for offset in vertex buffer
1631  *
1632  * @param configuration Attribute configuration, result is store as field ::m_vertex_length
1633  **/
calculateVertexLength(attributeConfiguration & configuration) const1634 void LimitTest::calculateVertexLength(attributeConfiguration& configuration) const
1635 {
1636 	GLint result = 0;
1637 
1638 	for (GLint i = 0; i < configuration.m_n_types; ++i)
1639 	{
1640 		result += configuration.m_n_elements[i] * configuration.m_n_attributes_per_group;
1641 	}
1642 
1643 	configuration.m_vertex_length = result;
1644 }
1645 
1646 /** Configure attributes in given "n_type" group
1647  *
1648  * @param iteration        Iteration id
1649  * @param configuration    Configuration of attributes
1650  * @param n_type           "n_type" of attibutes
1651  * @param program_id       Program object id
1652  * @param use_arrays       If attributes are groupd in arrays
1653  * @param use_vertex_array If attributes are configured with vertex array or as constants
1654  **/
configureAttribute(_iteration iteration,const attributeConfiguration & configuration,GLint n_type,GLuint program_id,bool use_arrays,bool use_vertex_array) const1655 void LimitTest::configureAttribute(_iteration iteration, const attributeConfiguration& configuration, GLint n_type,
1656 								   GLuint program_id, bool use_arrays, bool use_vertex_array) const
1657 {
1658 	static const GLint invalid_attrib_location = -1;
1659 
1660 	const GLint attributes_index = n_type * configuration.m_n_attributes_per_group;
1661 	const GLint group_offset	 = calculateAttributeGroupOffset(configuration, n_type);
1662 	const GLint n_elements		 = configuration.m_n_elements[n_type];
1663 	const GLint n_rows			 = configuration.m_n_rows[n_type];
1664 	const GLint n_columns		 = n_elements / n_rows;
1665 	const GLint vertex_length	= configuration.m_vertex_length;
1666 
1667 	/* For each attribute in "n_type" group */
1668 	for (GLint i = 0; i < configuration.m_n_attributes_per_group; ++i)
1669 	{
1670 		const GLint		  attribute_ordinal = i + attributes_index;
1671 		std::stringstream attribute_name;
1672 
1673 		/* Separate attributes are called: attribute_ORDINAL, arrayed: attribute_N_TYPE[INDEX] */
1674 		if (false == use_arrays)
1675 		{
1676 			attribute_name << "attribute_" << attribute_ordinal;
1677 		}
1678 		else
1679 		{
1680 			attribute_name << "attribute_" << n_type << "[" << i << "]";
1681 		}
1682 
1683 		/* get location */
1684 		GLint attribute_location = gl.getAttribLocation(program_id, attribute_name.str().c_str());
1685 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetAttribLocation");
1686 
1687 		if (invalid_attrib_location == attribute_location)
1688 		{
1689 			m_log << tcu::TestLog::Message << "GetAttribLocation(" << program_id << ", " << attribute_name.str()
1690 				  << ") returned: " << attribute_location << tcu::TestLog::EndMessage;
1691 
1692 			TCU_FAIL("Inactive attribute");
1693 		}
1694 
1695 		/* Configure */
1696 		if (true == use_vertex_array)
1697 		{
1698 			/* With vertex array */
1699 			for (GLint column = 0; column < n_columns; ++column)
1700 			{
1701 				const GLint attribute_offset = group_offset + i * n_elements;
1702 				const GLint column_offset	= column * n_rows;
1703 
1704 				gl.enableVertexAttribArray(attribute_location + column);
1705 				GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray");
1706 
1707 				gl.vertexAttribLPointer(attribute_location + column, n_rows /* size */, GL_DOUBLE,
1708 										static_cast<glw::GLsizei>(vertex_length * sizeof(GLdouble)),
1709 										(GLvoid*)((attribute_offset + column_offset) * sizeof(GLdouble)));
1710 				GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribLPointer");
1711 			}
1712 		}
1713 		else
1714 		{
1715 			/* As constant */
1716 			for (GLint column = 0; column < n_columns; ++column)
1717 			{
1718 				switch (iteration)
1719 				{
1720 				case DOUBLE_DVEC2:
1721 
1722 					/* Double attributes should be assigned the value:
1723 					 (n_attribute + gl_VertexID * 2) */
1724 					/* Dvec2 attribute components should be assigned the following
1725 					 vector values:
1726 					 (n_attribute + gl_VertexID * 3 + 1,
1727 					 n_attribute + gl_VertexID * 3 + 2)*/
1728 
1729 					if (1 == n_rows)
1730 					{
1731 						gl.vertexAttribL1d(attribute_location, attribute_ordinal);
1732 					}
1733 					else
1734 					{
1735 						gl.vertexAttribL2d(attribute_location, attribute_ordinal + 1, attribute_ordinal + 2);
1736 					}
1737 
1738 					break;
1739 
1740 				case DVEC3_DVEC4:
1741 
1742 					/* Dvec3 attribute components should be assigned the following
1743 					 vector values:
1744 					 (n_attribute + gl_VertexID * 3 + 0,
1745 					 n_attribute + gl_VertexID * 3 + 1,
1746 					 n_attribute + gl_VertexID * 3 + 2).
1747 
1748 					 Dvec4 attribute components should be assigned the following
1749 					 vector values:
1750 					 (n_attribute + gl_VertexID * 4 + 0,
1751 					 n_attribute + gl_VertexID * 4 + 1,
1752 					 n_attribute + gl_VertexID * 4 + 2,
1753 					 n_attribute + gl_VertexID * 4 + 3).*/
1754 
1755 					if (3 == n_rows)
1756 					{
1757 						gl.vertexAttribL3d(attribute_location, attribute_ordinal + 0, attribute_ordinal + 1,
1758 										   attribute_ordinal + 2);
1759 					}
1760 					else
1761 					{
1762 						gl.vertexAttribL4d(attribute_location, attribute_ordinal + 0, attribute_ordinal + 1,
1763 										   attribute_ordinal + 2, attribute_ordinal + 3);
1764 					}
1765 
1766 					break;
1767 
1768 				case DMAT2:
1769 				case DMAT3X2_DMAT4X2:
1770 				case DMAT2X3_DMAT2X4:
1771 				case DMAT3_DMAT3X4:
1772 				case DMAT4X3_DMAT4:
1773 
1774 					/* Subsequent matrix elements should be assigned the following value:
1775 					 (n_type + n_attribute + gl_VertexID * 16 + n_value)*/
1776 
1777 					if (2 == n_rows)
1778 					{
1779 						gl.vertexAttribL2d(attribute_location + column,
1780 										   n_type + attribute_ordinal + 0 + column * n_rows,
1781 										   n_type + attribute_ordinal + 1 + column * n_rows);
1782 					}
1783 					else if (3 == n_rows)
1784 					{
1785 						gl.vertexAttribL3d(attribute_location + column,
1786 										   n_type + attribute_ordinal + 0 + column * n_rows,
1787 										   n_type + attribute_ordinal + 1 + column * n_rows,
1788 										   n_type + attribute_ordinal + 2 + column * n_rows);
1789 					}
1790 					else
1791 					{
1792 						gl.vertexAttribL4d(attribute_location + column,
1793 										   n_type + attribute_ordinal + 0 + column * n_rows,
1794 										   n_type + attribute_ordinal + 1 + column * n_rows,
1795 										   n_type + attribute_ordinal + 2 + column * n_rows,
1796 										   n_type + attribute_ordinal + 3 + column * n_rows);
1797 					}
1798 
1799 					break;
1800 				}
1801 			}
1802 		}
1803 	}
1804 }
1805 
1806 /** Get varying name and vertex shader code for given configuration
1807  *
1808  * @param iteration                 Iteration id
1809  * @param use_arrays                If attributes should be grouped in arrays
1810  * @param use_locations             If attributes locations should be set manualy
1811  * @param use_vertex_attrib_divisor If vertex attribute divisor should be used
1812  * @param out_varying_name          Name of varying to be captured with transform feedback
1813  * @param out_vertex_shader_code    Source code of vertex shader
1814  **/
getProgramDetails(_iteration iteration,bool use_arrays,bool use_locations,bool use_vertex_attrib_divisor,std::string & out_varying_name,std::string & out_vertex_shader_code) const1815 void LimitTest::getProgramDetails(_iteration iteration, bool use_arrays, bool use_locations,
1816 								  bool use_vertex_attrib_divisor, std::string& out_varying_name,
1817 								  std::string& out_vertex_shader_code) const
1818 {
1819 	static const GLchar* varying_name = "vs_output_value";
1820 
1821 	attributeConfiguration configuration;
1822 	GLint				   n_attributes = 0;
1823 	GLint				   n_types		= 0;
1824 	std::stringstream	  stream;
1825 
1826 	const GLchar* advancement_str = (true == use_vertex_attrib_divisor) ? "gl_InstanceID" : "gl_VertexID";
1827 
1828 	getVertexArrayConfiguration(iteration, configuration);
1829 
1830 	n_attributes = configuration.m_n_attributes_per_group;
1831 	n_types		 = configuration.m_n_types;
1832 
1833 	/* Preamble */
1834 	stream << "#version 400\n"
1835 			  "#extension GL_ARB_vertex_attrib_64bit : require\n"
1836 			  "\n"
1837 			  "precision highp float;\n"
1838 			  "\n";
1839 
1840 	/* Attribute declarations */
1841 	/* Spearated attributes are called: attribute_ORDINAL, arrayed: attribute_N_TYPE */
1842 	for (GLint n_type = 0; n_type < n_types; ++n_type)
1843 	{
1844 		const GLint   attribute_offset = n_type * n_attributes;
1845 		const GLchar* type_name		   = configuration.m_type_names[n_type];
1846 
1847 		stream << "// " << type_name << "\n";
1848 
1849 		if (false == use_arrays)
1850 		{
1851 			for (GLint attribute = 0; attribute < n_attributes; ++attribute)
1852 			{
1853 				if (true == use_locations)
1854 				{
1855 					const GLint location = calculateAttributeLocation(configuration, attribute, n_type);
1856 
1857 					stream << "layout(location = " << location << ") ";
1858 				}
1859 
1860 				stream << "in " << type_name << " attribute_" << attribute + attribute_offset << ";\n";
1861 			}
1862 		}
1863 		else
1864 		{
1865 			if (true == use_locations)
1866 			{
1867 				const GLint location = calculateAttributeLocation(configuration, m_array_attribute, n_type);
1868 
1869 				stream << "layout(location = " << location << ") ";
1870 			}
1871 
1872 			stream << "in " << type_name << " attribute_" << n_type << "[" << n_attributes << "];\n";
1873 		}
1874 
1875 		stream << "\n";
1876 	}
1877 
1878 	/* Varying declaration */
1879 	stream << "out int " << varying_name << ";\n\n";
1880 
1881 	/* Main */
1882 	stream << "void main()\n"
1883 			  "{\n";
1884 
1885 	for (GLint n_type = 0; n_type < n_types; ++n_type)
1886 	{
1887 		const GLint   n_elements = configuration.m_n_elements[n_type];
1888 		const GLchar* type_name  = configuration.m_type_names[n_type];
1889 
1890 		stream << "// " << type_name << "\n";
1891 
1892 		/* if (attribute_name != type(values))
1893 		 * {
1894 		 *     varying = 0;
1895 		 * }
1896 		 */
1897 		for (GLint attribute = 0; attribute < n_attributes; ++attribute)
1898 		{
1899 			const GLint attribute_ordinal = attribute + n_type * n_attributes;
1900 
1901 			/* First attribute is verified with "if", rest with "else if" */
1902 			if (0 == attribute_ordinal)
1903 			{
1904 				stream << "    if (attribute_";
1905 			}
1906 			else
1907 			{
1908 				stream << "    else if (attribute_";
1909 			}
1910 
1911 			/* Spearated attributes are called: attribute_ORDINAL, arrayed: attribute_N_TYPE[INDEX] */
1912 			if (false == use_arrays)
1913 			{
1914 				stream << attribute_ordinal;
1915 			}
1916 			else
1917 			{
1918 				stream << n_type << "[" << attribute << "]";
1919 			}
1920 
1921 			/* != type() */
1922 			stream << " != " << type_name << "(";
1923 
1924 			/* Values for type constructor, depend on iteration */
1925 			switch (iteration)
1926 			{
1927 			case DOUBLE_DVEC2:
1928 
1929 				/* Double attributes should be assigned the value:
1930 				 (n_attribute + gl_VertexID * 2) */
1931 				/* Dvec2 attribute components should be assigned the following
1932 				 vector values:
1933 				 (n_attribute + gl_VertexID * 3 + 1,
1934 				 n_attribute + gl_VertexID * 3 + 2)*/
1935 
1936 				if (1 == n_elements)
1937 				{
1938 					stream << attribute_ordinal << " + " << advancement_str << " * 2";
1939 				}
1940 				else
1941 				{
1942 					stream << attribute_ordinal << " + " << advancement_str << " * 3 + 1"
1943 						   << ", " << attribute_ordinal << " + " << advancement_str << " * 3 + 2";
1944 				}
1945 
1946 				break;
1947 
1948 			case DVEC3_DVEC4:
1949 
1950 				/* Dvec3 attribute components should be assigned the following
1951 				 vector values:
1952 				 (n_attribute + gl_VertexID * 3 + 0,
1953 				 n_attribute + gl_VertexID * 3 + 1,
1954 				 n_attribute + gl_VertexID * 3 + 2).
1955 
1956 				 Dvec4 attribute components should be assigned the following
1957 				 vector values:
1958 				 (n_attribute + gl_VertexID * 4 + 0,
1959 				 n_attribute + gl_VertexID * 4 + 1,
1960 				 n_attribute + gl_VertexID * 4 + 2,
1961 				 n_attribute + gl_VertexID * 4 + 3).*/
1962 
1963 				for (GLint element = 0; element < n_elements; ++element)
1964 				{
1965 					stream << attribute_ordinal << " + " << advancement_str << " * " << n_elements << " + " << element;
1966 
1967 					if (n_elements != element + 1)
1968 					{
1969 						stream << ", ";
1970 					}
1971 				}
1972 
1973 				break;
1974 
1975 			case DMAT2:
1976 			case DMAT3X2_DMAT4X2:
1977 			case DMAT2X3_DMAT2X4:
1978 			case DMAT3_DMAT3X4:
1979 			case DMAT4X3_DMAT4:
1980 
1981 				/* Subsequent matrix elements should be assigned the following value:
1982 				 (n_type + n_attribute + gl_VertexID * 16 + n_value)*/
1983 
1984 				for (GLint element = 0; element < n_elements; ++element)
1985 				{
1986 					stream << n_type << " + " << attribute_ordinal << " + " << advancement_str << " * 16 + " << element;
1987 
1988 					if (n_elements != element + 1)
1989 					{
1990 						stream << ", ";
1991 					}
1992 				}
1993 
1994 				break;
1995 			}
1996 
1997 			/* type() { varying = 0 } */
1998 			stream << "))\n"
1999 				   << "    {\n"
2000 				   << "        " << varying_name << " = 0;\n"
2001 				   << "    }\n";
2002 		}
2003 	}
2004 
2005 	/* All attributes verified: else { varyin = 1 }
2006 	 Close main body */
2007 	stream << "    else\n"
2008 		   << "    {\n"
2009 		   << "        " << varying_name << " = 1;\n"
2010 		   << "    }\n"
2011 		   << "}\n\n";
2012 
2013 	/* Store results */
2014 	out_varying_name	   = varying_name;
2015 	out_vertex_shader_code = stream.str();
2016 }
2017 
2018 /** Get configuration of vertex array object
2019  *
2020  * @param iteration         Iteration id
2021  * @param out_configuration Configuration
2022  **/
getVertexArrayConfiguration(_iteration iteration,attributeConfiguration & out_configuration) const2023 void LimitTest::getVertexArrayConfiguration(_iteration iteration, attributeConfiguration& out_configuration) const
2024 {
2025 	static const GLuint n_elements_per_scalar = 1;
2026 	static const GLuint n_elements_per_vec2   = 2;
2027 	static const GLuint n_elements_per_vec3   = 3;
2028 	static const GLuint n_elements_per_vec4   = 4;
2029 	static const GLuint n_elements_per_mat2   = 4;
2030 	static const GLuint n_elements_per_mat2x3 = 6;
2031 	static const GLuint n_elements_per_mat2x4 = 8;
2032 	static const GLuint n_elements_per_mat3   = 9;
2033 	static const GLuint n_elements_per_mat3x2 = 6;
2034 	static const GLuint n_elements_per_mat3x4 = 12;
2035 	static const GLuint n_elements_per_mat4   = 16;
2036 	static const GLuint n_elements_per_mat4x2 = 8;
2037 	static const GLuint n_elements_per_mat4x3 = 12;
2038 
2039 	const GLint max_vertex_attribs = GetMaxVertexAttribs();
2040 
2041 	switch (iteration)
2042 	{
2043 	case DOUBLE_DVEC2:
2044 	{
2045 		static const GLint n_elements[] = { n_elements_per_scalar, n_elements_per_vec2 };
2046 		static const GLint n_types		= sizeof(n_elements) / sizeof(n_elements[0]);
2047 
2048 		static const GLint divisor = 2;
2049 
2050 		static const GLchar* type_names[] = { "double", "dvec2" };
2051 
2052 		static const GLint n_rows[] = {
2053 			1, 2,
2054 		};
2055 
2056 		out_configuration.m_n_attributes_per_group = max_vertex_attribs / divisor;
2057 		out_configuration.m_n_elements			   = n_elements;
2058 		out_configuration.m_n_rows				   = n_rows;
2059 		out_configuration.m_n_types				   = n_types;
2060 		out_configuration.m_type_names			   = type_names;
2061 	}
2062 	break;
2063 	case DVEC3_DVEC4:
2064 	{
2065 		static const GLint n_elements[] = { n_elements_per_vec3, n_elements_per_vec4 };
2066 		static const GLint n_types		= sizeof(n_elements) / sizeof(n_elements[0]);
2067 
2068 		static const GLint divisor = 4;
2069 
2070 		static const GLchar* type_names[] = { "dvec3", "dvec4" };
2071 
2072 		static const GLint n_rows[] = {
2073 			3, 4,
2074 		};
2075 
2076 		out_configuration.m_n_attributes_per_group = max_vertex_attribs / divisor;
2077 		out_configuration.m_n_elements			   = n_elements;
2078 		out_configuration.m_n_rows				   = n_rows;
2079 		out_configuration.m_n_types				   = n_types;
2080 		out_configuration.m_type_names			   = type_names;
2081 	}
2082 	break;
2083 	case DMAT2:
2084 	{
2085 		static const GLint n_elements[] = { n_elements_per_mat2 };
2086 		static const GLint n_types		= sizeof(n_elements) / sizeof(n_elements[0]);
2087 
2088 		static const GLint divisor = 2;
2089 
2090 		static const GLchar* type_names[] = { "dmat2" };
2091 
2092 		static const GLint n_rows[] = { 2 };
2093 
2094 		out_configuration.m_n_attributes_per_group = max_vertex_attribs / divisor;
2095 		out_configuration.m_n_elements			   = n_elements;
2096 		out_configuration.m_n_rows				   = n_rows;
2097 		out_configuration.m_n_types				   = n_types;
2098 		out_configuration.m_type_names			   = type_names;
2099 	}
2100 	break;
2101 	case DMAT3X2_DMAT4X2:
2102 	{
2103 		static const GLint n_elements[] = { n_elements_per_mat3x2, n_elements_per_mat4x2 };
2104 		static const GLint n_types		= sizeof(n_elements) / sizeof(n_elements[0]);
2105 
2106 		static const GLint divisor = 8;
2107 
2108 		static const GLchar* type_names[] = { "dmat3x2", "dmat4x2" };
2109 
2110 		static const GLint n_rows[] = { 2, 2 };
2111 
2112 		out_configuration.m_n_attributes_per_group = max_vertex_attribs / divisor;
2113 		out_configuration.m_n_elements			   = n_elements;
2114 		out_configuration.m_n_rows				   = n_rows;
2115 		out_configuration.m_n_types				   = n_types;
2116 		out_configuration.m_type_names			   = type_names;
2117 	}
2118 	break;
2119 	case DMAT2X3_DMAT2X4:
2120 	{
2121 		static const GLint n_elements[] = { n_elements_per_mat2x3, n_elements_per_mat2x4 };
2122 		static const GLint n_types		= sizeof(n_elements) / sizeof(n_elements[0]);
2123 
2124 		static const GLint divisor = 8;
2125 
2126 		static const GLchar* type_names[] = { "dmat2x3", "dmat2x4" };
2127 
2128 		static const GLint n_rows[] = { 3, 4 };
2129 
2130 		out_configuration.m_n_attributes_per_group = max_vertex_attribs / divisor;
2131 		out_configuration.m_n_elements			   = n_elements;
2132 		out_configuration.m_n_rows				   = n_rows;
2133 		out_configuration.m_n_types				   = n_types;
2134 		out_configuration.m_type_names			   = type_names;
2135 	}
2136 	break;
2137 	case DMAT3_DMAT3X4:
2138 	{
2139 		static const GLint n_elements[] = { n_elements_per_mat3, n_elements_per_mat3x4 };
2140 		static const GLint n_types		= sizeof(n_elements) / sizeof(n_elements[0]);
2141 
2142 		static const GLint divisor = 12;
2143 
2144 		static const GLchar* type_names[] = { "dmat3", "dmat3x4" };
2145 
2146 		static const GLint n_rows[] = { 3, 4 };
2147 
2148 		out_configuration.m_n_attributes_per_group = max_vertex_attribs / divisor;
2149 		out_configuration.m_n_elements			   = n_elements;
2150 		out_configuration.m_n_rows				   = n_rows;
2151 		out_configuration.m_n_types				   = n_types;
2152 		out_configuration.m_type_names			   = type_names;
2153 	}
2154 	break;
2155 	case DMAT4X3_DMAT4:
2156 	{
2157 		static const GLint n_elements[] = { n_elements_per_mat4x3, n_elements_per_mat4 };
2158 		static const GLint n_types		= sizeof(n_elements) / sizeof(n_elements[0]);
2159 
2160 		static const GLint divisor = 16;
2161 
2162 		static const GLchar* type_names[] = { "dmat4x3", "dmat4" };
2163 
2164 		static const GLint n_rows[] = { 3, 4 };
2165 
2166 		out_configuration.m_n_attributes_per_group = max_vertex_attribs / divisor;
2167 		out_configuration.m_n_elements			   = n_elements;
2168 		out_configuration.m_n_rows				   = n_rows;
2169 		out_configuration.m_n_types				   = n_types;
2170 		out_configuration.m_type_names			   = type_names;
2171 	}
2172 	break;
2173 	}
2174 
2175 	calculateVertexLength(out_configuration);
2176 }
2177 
2178 /** Logs iteration and configuration of test
2179  *
2180  * @param iteration      Iteration id
2181  * @param use_arrays     If attributes are grouped in arrays
2182  * @param use_locations  If manual attribute locations are used
2183  * @param attribute_type Regular, constant or per instance
2184  **/
logTestIterationAndConfig(_iteration iteration,_attributeType attribute_type,bool use_arrays,bool use_locations) const2185 void LimitTest::logTestIterationAndConfig(_iteration iteration, _attributeType attribute_type, bool use_arrays,
2186 										  bool use_locations) const
2187 {
2188 	tcu::MessageBuilder message = m_log << tcu::TestLog::Message;
2189 
2190 	switch (iteration)
2191 	{
2192 	case DOUBLE_DVEC2:
2193 		message << "Iteration: double + dvec2";
2194 
2195 		break;
2196 	case DVEC3_DVEC4:
2197 		message << "Iteration: devc3 + dvec4";
2198 
2199 		break;
2200 	case DMAT2:
2201 		message << "Iteration: dmat2";
2202 
2203 		break;
2204 	case DMAT3X2_DMAT4X2:
2205 		message << "Iteration: dmat3x2 + dmat4x2";
2206 
2207 		break;
2208 	case DMAT2X3_DMAT2X4:
2209 		message << "Iteration: dmat2x3 + dmat2x4";
2210 
2211 		break;
2212 	case DMAT3_DMAT3X4:
2213 		message << "Iteration: dmat3 + dmat3x4";
2214 
2215 		break;
2216 	case DMAT4X3_DMAT4:
2217 		message << "Iteration: dmat4x3 + dmat4";
2218 
2219 		break;
2220 	}
2221 
2222 	message << "Configuration: ";
2223 
2224 	if (true == use_arrays)
2225 	{
2226 		message << "arrayed attributes";
2227 	}
2228 	else
2229 	{
2230 		message << "separate attributes";
2231 	}
2232 
2233 	message << ", ";
2234 
2235 	if (true == use_locations)
2236 	{
2237 		message << "reversed locations";
2238 	}
2239 	else
2240 	{
2241 		message << "default locations";
2242 	}
2243 
2244 	message << ", ";
2245 
2246 	switch (attribute_type)
2247 	{
2248 	case REGULAR:
2249 		message << "vertex attribute divisor: 0";
2250 
2251 		break;
2252 	case CONSTANT:
2253 		message << "constant vertex attribute";
2254 
2255 		break;
2256 	case PER_INSTANCE:
2257 		message << "vertex attribute divisor: 1";
2258 
2259 		break;
2260 	}
2261 
2262 	message << tcu::TestLog::EndMessage;
2263 }
2264 
2265 /** Prepare program info for given configuration
2266  *
2267  * @param iteration                 Iteration id
2268  * @param use_arrays                If attributes should be grouped in arrays
2269  * @param use_locations             If manual attribute locations should be used
2270  * @param use_vertex_attrib_divisor If vertex attribute divisor should be used
2271  * @param program_info              Program info
2272  **/
prepareProgram(_iteration iteration,bool use_arrays,bool use_locations,bool use_vertex_attrib_divisor,programInfo & program_info)2273 void LimitTest::prepareProgram(_iteration iteration, bool use_arrays, bool use_locations,
2274 							   bool use_vertex_attrib_divisor, programInfo& program_info)
2275 {
2276 	static const GLchar* fragment_shader_code = "#version 400\n"
2277 												"#extension GL_ARB_vertex_attrib_64bit : require\n"
2278 												"\n"
2279 												"precision highp float;\n"
2280 												"\n"
2281 												"void main()\n"
2282 												"{\n"
2283 												"    discard;\n"
2284 												"}\n\n";
2285 	std::string varying_name;
2286 	std::string vertex_shader_code;
2287 
2288 	program_info.m_program_id = gl.createProgram();
2289 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
2290 
2291 	getProgramDetails(iteration, use_arrays, use_locations, use_vertex_attrib_divisor, varying_name,
2292 					  vertex_shader_code);
2293 
2294 	{
2295 		const GLchar* temp_varying_name = varying_name.c_str();
2296 
2297 		gl.transformFeedbackVaryings(program_info.m_program_id, m_n_varyings, &temp_varying_name,
2298 									 GL_INTERLEAVED_ATTRIBS);
2299 		GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
2300 	}
2301 
2302 	BuildProgram(fragment_shader_code, program_info.m_program_id, vertex_shader_code.c_str(),
2303 				 program_info.m_fragment_shader_id, program_info.m_vertex_shader_id);
2304 }
2305 
2306 /** Configure vertex array object for all attributes
2307  *
2308  * @param iteration      Iteration id
2309  * @param attribute_type Regular, constant or per instance
2310  * @param program_id     Program object id
2311  * @param use_arrays     If attributes are grouped with arrays
2312  **/
prepareVertexArray(_iteration iteration,_attributeType attribute_type,GLuint program_id,bool use_arrays) const2313 void LimitTest::prepareVertexArray(_iteration iteration, _attributeType attribute_type, GLuint program_id,
2314 								   bool use_arrays) const
2315 {
2316 	const GLint  max_vertex_attribs	= GetMaxVertexAttribs();
2317 	const GLuint vertex_attrib_divisor = (PER_INSTANCE == attribute_type) ? 1 : 0;
2318 
2319 	attributeConfiguration configuration;
2320 
2321 	getVertexArrayConfiguration(iteration, configuration);
2322 
2323 	/* Set vertex attributes divisor and disable */
2324 	for (GLint i = 0; i < max_vertex_attribs; ++i)
2325 	{
2326 		gl.vertexAttribDivisor(i, vertex_attrib_divisor);
2327 		GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribDivisor");
2328 
2329 		gl.disableVertexAttribArray(i);
2330 		GLU_EXPECT_NO_ERROR(gl.getError(), "DisableVertexAttribArray");
2331 	}
2332 
2333 	for (GLint n_type = 0; n_type < configuration.m_n_types; ++n_type)
2334 	{
2335 		configureAttribute(iteration, configuration, n_type, program_id, use_arrays, (CONSTANT != attribute_type));
2336 	}
2337 }
2338 
2339 /** Prepare vertex buffer data for given iteration
2340  *
2341  * @param iteration Iteration id
2342  **/
prepareVertexArrayBuffer(_iteration iteration)2343 void LimitTest::prepareVertexArrayBuffer(_iteration iteration)
2344 {
2345 	GLuint				   buffer_length = 0;
2346 	attributeConfiguration configuration;
2347 
2348 	getVertexArrayConfiguration(iteration, configuration);
2349 
2350 	buffer_length = m_n_vertices * configuration.m_vertex_length;
2351 
2352 	std::vector<GLdouble> buffer_data;
2353 	buffer_data.resize(buffer_length);
2354 
2355 	for (GLuint vertex = 0; vertex < m_n_vertices; ++vertex)
2356 	{
2357 		setAttributes(iteration, configuration, vertex, buffer_data);
2358 	}
2359 
2360 	gl.bufferData(GL_ARRAY_BUFFER, buffer_length * sizeof(GLdouble), &buffer_data[0], GL_STATIC_DRAW);
2361 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
2362 }
2363 
2364 /** Set all attributes for <vertex>
2365  *
2366  * @param iteration       Iteration id
2367  * @param configuration   Attribute configuration
2368  * @param vertex          Vertex orinal number
2369  * @param out_buffer_data Buffer data
2370  **/
setAttributes(_iteration iteration,const attributeConfiguration & configuration,GLuint vertex,std::vector<GLdouble> & out_buffer_data) const2371 void LimitTest::setAttributes(_iteration iteration, const attributeConfiguration& configuration, GLuint vertex,
2372 							  std::vector<GLdouble>& out_buffer_data) const
2373 {
2374 	const GLint n_types = configuration.m_n_types;
2375 
2376 	for (GLint n_type = 0; n_type < n_types; ++n_type)
2377 	{
2378 		switch (iteration)
2379 		{
2380 		case DOUBLE_DVEC2:
2381 
2382 			setAttributes_a(configuration, n_type, vertex, out_buffer_data);
2383 
2384 			break;
2385 
2386 		case DVEC3_DVEC4:
2387 
2388 			setAttributes_b(configuration, n_type, vertex, out_buffer_data);
2389 
2390 			break;
2391 
2392 		case DMAT2:
2393 		case DMAT3X2_DMAT4X2:
2394 		case DMAT2X3_DMAT2X4:
2395 		case DMAT3_DMAT3X4:
2396 		case DMAT4X3_DMAT4:
2397 
2398 			setAttributes_c(configuration, n_type, vertex, out_buffer_data);
2399 
2400 			break;
2401 		}
2402 	}
2403 }
2404 
2405 /** Set attributes of given <n_type> for <vertex>, as described in "iteration a".
2406  *
2407  * @param configuration   Attribute configuration
2408  * @param n_type          "n_type" ordinal number
2409  * @param vertex          Vertex orinal number
2410  * @param out_buffer_data Buffer data
2411  **/
setAttributes_a(const attributeConfiguration & configuration,GLint n_type,GLuint vertex,std::vector<GLdouble> & out_buffer_data) const2412 void LimitTest::setAttributes_a(const attributeConfiguration& configuration, GLint n_type, GLuint vertex,
2413 								std::vector<GLdouble>& out_buffer_data) const
2414 {
2415 	const GLint n_elements = configuration.m_n_elements[n_type];
2416 
2417 	if (1 == n_elements)
2418 	{
2419 		setAttributes_a_scalar(configuration, n_type, vertex, out_buffer_data);
2420 	}
2421 	else
2422 	{
2423 		setAttributes_a_vec(configuration, n_type, vertex, out_buffer_data);
2424 	}
2425 }
2426 
2427 /** Set scalar double attributes of given <n_type> for <vertex>, as described in "iteration a".
2428  *
2429  * @param configuration   Attribute configuration
2430  * @param n_type          "n_type" ordinal number
2431  * @param vertex          Vertex orinal number
2432  * @param out_buffer_data Buffer data
2433  **/
setAttributes_a_scalar(const attributeConfiguration & configuration,GLint n_type,GLuint vertex,std::vector<GLdouble> & out_buffer_data) const2434 void LimitTest::setAttributes_a_scalar(const attributeConfiguration& configuration, GLint n_type, GLuint vertex,
2435 									   std::vector<GLdouble>& out_buffer_data) const
2436 {
2437 	const GLint n_attributes	= configuration.m_n_attributes_per_group;
2438 	const GLint attribute_index = n_attributes * n_type;
2439 	GLuint		vertex_offset   = vertex * configuration.m_vertex_length;
2440 
2441 	const GLint group_offset = calculateAttributeGroupOffset(configuration, n_type) + vertex_offset;
2442 
2443 	/* Double attributes should be assigned the value:
2444 	 (n_attribute + gl_VertexID * 2) */
2445 
2446 	for (GLint attribute = 0; attribute < n_attributes; ++attribute)
2447 	{
2448 		const GLuint attribute_offset = attribute + group_offset;
2449 
2450 		out_buffer_data[attribute_offset] = attribute + attribute_index + vertex * 2;
2451 	}
2452 }
2453 
2454 /** Set dvec2 attributes of given <n_type> for <vertex>, as described in "iteration a".
2455  *
2456  * @param configuration   Attribute configuration
2457  * @param n_type          "n_type" ordinal number
2458  * @param vertex          Vertex orinal number
2459  * @param out_buffer_data Buffer data
2460  **/
setAttributes_a_vec(const attributeConfiguration & configuration,GLint n_type,GLuint vertex,std::vector<GLdouble> & out_buffer_data) const2461 void LimitTest::setAttributes_a_vec(const attributeConfiguration& configuration, GLint n_type, GLuint vertex,
2462 									std::vector<GLdouble>& out_buffer_data) const
2463 {
2464 	const GLint n_attributes	= configuration.m_n_attributes_per_group;
2465 	const GLint attribute_index = n_attributes * n_type;
2466 	const GLint n_elements		= configuration.m_n_elements[n_type];
2467 	GLuint		vertex_offset   = vertex * configuration.m_vertex_length;
2468 
2469 	const GLint group_offset = calculateAttributeGroupOffset(configuration, n_type) + vertex_offset;
2470 
2471 	/* Dvec2 attribute components should be assigned the following
2472 	 vector values:
2473 	 (n_attribute + gl_VertexID * 3 + 1,
2474 	 n_attribute + gl_VertexID * 3 + 2)*/
2475 
2476 	for (GLint attribute = 0; attribute < n_attributes; ++attribute)
2477 	{
2478 		const GLuint attribute_offset = n_elements * attribute + group_offset;
2479 
2480 		for (GLint i = 0; i < n_elements; ++i)
2481 		{
2482 			out_buffer_data[attribute_offset + i] = attribute + attribute_index + vertex * 3 + i + 1;
2483 		}
2484 	}
2485 }
2486 
2487 /** Set attributes of given <n_type> for <vertex>, as described in "iteration b".
2488  *
2489  * @param configuration   Attribute configuration
2490  * @param n_type          "n_type" ordinal number
2491  * @param vertex          Vertex orinal number
2492  * @param out_buffer_data Buffer data
2493  **/
setAttributes_b(const attributeConfiguration & configuration,GLint n_type,GLuint vertex,std::vector<GLdouble> & out_buffer_data) const2494 void LimitTest::setAttributes_b(const attributeConfiguration& configuration, GLint n_type, GLuint vertex,
2495 								std::vector<GLdouble>& out_buffer_data) const
2496 {
2497 	const GLint n_attributes	= configuration.m_n_attributes_per_group;
2498 	const GLint attribute_index = n_attributes * n_type;
2499 	const GLint n_elements		= configuration.m_n_elements[n_type];
2500 	GLuint		vertex_offset   = vertex * configuration.m_vertex_length;
2501 
2502 	const GLint group_offset = calculateAttributeGroupOffset(configuration, n_type) + vertex_offset;
2503 
2504 	/* Dvec3 attribute components should be assigned the following
2505 	 vector values:
2506 	 (n_attribute + gl_VertexID * 3 + 0,
2507 	 n_attribute + gl_VertexID * 3 + 1,
2508 	 n_attribute + gl_VertexID * 3 + 2).
2509 
2510 	 Dvec4 attribute components should be assigned the following
2511 	 vector values:
2512 	 (n_attribute + gl_VertexID * 4 + 0,
2513 	 n_attribute + gl_VertexID * 4 + 1,
2514 	 n_attribute + gl_VertexID * 4 + 2,
2515 	 n_attribute + gl_VertexID * 4 + 3).*/
2516 
2517 	for (GLint attribute = 0; attribute < n_attributes; ++attribute)
2518 	{
2519 		const GLuint attribute_offset = n_elements * attribute + group_offset;
2520 
2521 		for (GLint i = 0; i < n_elements; ++i)
2522 		{
2523 			out_buffer_data[attribute_offset + i] = attribute + attribute_index + vertex * n_elements + i;
2524 		}
2525 	}
2526 }
2527 
2528 /** Set attributes of given <n_type> for <vertex>, as described in "iteration c".
2529  *
2530  * @param configuration   Attribute configuration
2531  * @param n_type          "n_type" ordinal number
2532  * @param vertex          Vertex orinal number
2533  * @param out_buffer_data Buffer data
2534  **/
setAttributes_c(const attributeConfiguration & configuration,GLint n_type,GLuint vertex,std::vector<GLdouble> & out_buffer_data) const2535 void LimitTest::setAttributes_c(const attributeConfiguration& configuration, GLint n_type, GLuint vertex,
2536 								std::vector<GLdouble>& out_buffer_data) const
2537 {
2538 	const GLint n_attributes	= configuration.m_n_attributes_per_group;
2539 	const GLint attribute_index = n_attributes * n_type;
2540 	const GLint n_elements		= configuration.m_n_elements[n_type];
2541 	GLuint		vertex_offset   = vertex * configuration.m_vertex_length;
2542 
2543 	const GLint group_offset = calculateAttributeGroupOffset(configuration, n_type) + vertex_offset;
2544 
2545 	/* Subsequent matrix elements should be assigned the following value:
2546 	 (n_type + n_attribute + gl_VertexID * 16 + n_value)*/
2547 
2548 	for (GLint attribute = 0; attribute < n_attributes; ++attribute)
2549 	{
2550 		const GLuint attribute_offset = n_elements * attribute + group_offset;
2551 
2552 		for (GLint i = 0; i < n_elements; ++i)
2553 		{
2554 			out_buffer_data[attribute_offset + i] = n_type + attribute + attribute_index + vertex * 16 + i;
2555 		}
2556 	}
2557 }
2558 
2559 /** Run test with DrawArrays routine
2560  *
2561  * @return true if test pass, false otherwise
2562  **/
testDrawArrays() const2563 bool LimitTest::testDrawArrays() const
2564 {
2565 	gl.beginTransformFeedback(GL_POINTS);
2566 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
2567 
2568 	gl.drawArrays(GL_POINTS, 0 /* first */, m_n_vertices);
2569 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
2570 
2571 	gl.endTransformFeedback();
2572 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
2573 
2574 	if (true == verifyResult(false))
2575 	{
2576 		return true;
2577 	}
2578 	else
2579 	{
2580 		m_log << tcu::TestLog::Message << "Draw function: DrawArrays" << tcu::TestLog::EndMessage;
2581 
2582 		return false;
2583 	}
2584 }
2585 
2586 /** Run test with DrawArraysInstanced routine
2587  *
2588  * @return true if test pass, false otherwise
2589  **/
testDrawArraysInstanced() const2590 bool LimitTest::testDrawArraysInstanced() const
2591 {
2592 	gl.beginTransformFeedback(GL_POINTS);
2593 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
2594 
2595 	gl.drawArraysInstanced(GL_POINTS, 0 /* first */, m_n_vertices, m_n_instances);
2596 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArraysInstanced");
2597 
2598 	gl.endTransformFeedback();
2599 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
2600 
2601 	if (true == verifyResult(true))
2602 	{
2603 		return true;
2604 	}
2605 	else
2606 	{
2607 		m_log << tcu::TestLog::Message << "Draw function: DrawArraysInstanced" << tcu::TestLog::EndMessage;
2608 
2609 		return false;
2610 	}
2611 }
2612 
2613 /** Run test with DrawElements routine
2614  *
2615  * @return true if test pass, false otherwise
2616  **/
testDrawElements() const2617 bool LimitTest::testDrawElements() const
2618 {
2619 	gl.beginTransformFeedback(GL_POINTS);
2620 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
2621 
2622 	gl.drawElements(GL_POINTS, m_n_vertices, GL_UNSIGNED_INT, 0);
2623 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
2624 
2625 	gl.endTransformFeedback();
2626 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
2627 
2628 	if (true == verifyResult(false))
2629 	{
2630 		return true;
2631 	}
2632 	else
2633 	{
2634 		m_log << tcu::TestLog::Message << "Draw function: DrawElements" << tcu::TestLog::EndMessage;
2635 
2636 		return false;
2637 	}
2638 }
2639 
2640 /** Run test with DrawElementsInstanced routine
2641  *
2642  * @return true if test pass, false otherwise
2643  **/
testDrawElementsInstanced() const2644 bool LimitTest::testDrawElementsInstanced() const
2645 {
2646 	gl.beginTransformFeedback(GL_POINTS);
2647 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
2648 
2649 	gl.drawElementsInstanced(GL_POINTS, m_n_vertices, GL_UNSIGNED_INT, 0, m_n_instances);
2650 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsInstanced");
2651 
2652 	gl.endTransformFeedback();
2653 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
2654 
2655 	if (true == verifyResult(true))
2656 	{
2657 		return true;
2658 	}
2659 	else
2660 	{
2661 		m_log << tcu::TestLog::Message << "Draw function: DrawElementsInstanced" << tcu::TestLog::EndMessage;
2662 
2663 		return false;
2664 	}
2665 }
2666 
2667 /** Test initialisation
2668  *
2669  **/
testInit()2670 void LimitTest::testInit()
2671 {
2672 	/* Prepare data for element array buffer */
2673 	std::vector<GLuint> indices_data;
2674 	indices_data.resize(m_n_vertices);
2675 	for (GLuint i = 0; i < m_n_vertices; ++i)
2676 	{
2677 		indices_data[i] = i;
2678 	}
2679 
2680 	/* Prepare vertex array object */
2681 	gl.genVertexArrays(1, &m_vertex_array_object_id);
2682 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
2683 
2684 	gl.bindVertexArray(m_vertex_array_object_id);
2685 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
2686 
2687 	/* Generate buffers */
2688 	gl.genBuffers(1, &m_element_array_buffer_id);
2689 	gl.genBuffers(1, &m_transoform_feedback_buffer_id);
2690 	gl.genBuffers(1, &m_vertex_array_buffer_id);
2691 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
2692 
2693 	/* Prepare element array buffer */
2694 	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_array_buffer_id);
2695 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
2696 
2697 	gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, m_n_vertices * sizeof(GLuint), &indices_data[0], GL_STATIC_DRAW);
2698 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
2699 
2700 	/* Prepare transform feedback buffer */
2701 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transoform_feedback_buffer_id);
2702 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
2703 
2704 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_size, 0 /* data */, GL_DYNAMIC_COPY);
2705 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
2706 
2707 	/* Bind array buffer for future use */
2708 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vertex_array_buffer_id);
2709 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
2710 
2711 	/* Disabe rasterization */
2712 	gl.enable(GL_RASTERIZER_DISCARD);
2713 	GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
2714 }
2715 
2716 /** Tests specified "iteration"
2717  *
2718  * @param iteration Iteration id
2719  *
2720  * @return true if tests pass, false otherwise
2721  **/
testIteration(_iteration iteration)2722 bool LimitTest::testIteration(_iteration iteration)
2723 {
2724 	bool result = true;
2725 
2726 	/* Program infos */
2727 	programInfo _no_array__no_location______regular(gl);
2728 	programInfo use_array__no_location______regular(gl);
2729 	programInfo _no_array_use_location______regular(gl);
2730 	programInfo use_array_use_location______regular(gl);
2731 	programInfo _no_array__no_location_per_instance(gl);
2732 	programInfo use_array__no_location_per_instance(gl);
2733 	programInfo _no_array_use_location_per_instance(gl);
2734 	programInfo use_array_use_location_per_instance(gl);
2735 
2736 	/* Prepare programs for all configuration */
2737 	prepareProgram(iteration, false, false, false, _no_array__no_location______regular);
2738 	prepareProgram(iteration, true, false, false, use_array__no_location______regular);
2739 	prepareProgram(iteration, false, true, false, _no_array_use_location______regular);
2740 	prepareProgram(iteration, true, true, false, use_array_use_location______regular);
2741 	prepareProgram(iteration, false, false, true, _no_array__no_location_per_instance);
2742 	prepareProgram(iteration, true, false, true, use_array__no_location_per_instance);
2743 	prepareProgram(iteration, false, true, true, _no_array_use_location_per_instance);
2744 	prepareProgram(iteration, true, true, true, use_array_use_location_per_instance);
2745 
2746 	/* Bind buffers */
2747 	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_array_buffer_id);
2748 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_transoform_feedback_buffer_id, 0,
2749 					   m_transform_feedback_buffer_size);
2750 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
2751 
2752 	/* Prepare vertex array buffer for iteration */
2753 	prepareVertexArrayBuffer(iteration);
2754 
2755 	/* Regular and instanced draw calls, vertex attribute divisor: 0 */
2756 	if (false == testProgram(iteration, _no_array__no_location______regular.m_program_id, false))
2757 	{
2758 		logTestIterationAndConfig(iteration, REGULAR, false /* use_arrays */, false /* use_locations */);
2759 
2760 		result = false;
2761 	}
2762 
2763 	if (false == testProgram(iteration, use_array__no_location______regular.m_program_id, true))
2764 	{
2765 		logTestIterationAndConfig(iteration, REGULAR, true /* use_arrays */, false /* use_locations */);
2766 
2767 		result = false;
2768 	}
2769 
2770 	if (false == testProgram(iteration, _no_array_use_location______regular.m_program_id, false))
2771 	{
2772 		logTestIterationAndConfig(iteration, REGULAR, false /* use_arrays */, true /* use_locations */);
2773 
2774 		result = false;
2775 	}
2776 
2777 	if (false == testProgram(iteration, use_array_use_location______regular.m_program_id, true))
2778 	{
2779 		logTestIterationAndConfig(iteration, REGULAR, true /* use_arrays */, true /* use_locations */);
2780 
2781 		result = false;
2782 	}
2783 
2784 	/* Regular draw calls, constant vertex attribute */
2785 	if (false == testProgramWithConstant(iteration, _no_array__no_location_per_instance.m_program_id, false))
2786 	{
2787 		logTestIterationAndConfig(iteration, CONSTANT, false /* use_arrays */, false /* use_locations */);
2788 
2789 		result = false;
2790 	}
2791 
2792 	if (false == testProgramWithConstant(iteration, use_array__no_location_per_instance.m_program_id, true))
2793 	{
2794 		logTestIterationAndConfig(iteration, CONSTANT, true /* use_arrays */, false /* use_locations */);
2795 
2796 		result = false;
2797 	}
2798 
2799 	if (false == testProgramWithConstant(iteration, _no_array_use_location_per_instance.m_program_id, false))
2800 	{
2801 		logTestIterationAndConfig(iteration, CONSTANT, false /* use_arrays */, true /* use_locations */);
2802 
2803 		result = false;
2804 	}
2805 
2806 	if (false == testProgramWithConstant(iteration, use_array_use_location_per_instance.m_program_id, true))
2807 	{
2808 		logTestIterationAndConfig(iteration, CONSTANT, true /* use_arrays */, true /* use_locations */);
2809 
2810 		result = false;
2811 	}
2812 
2813 	/* Instanced draw calls, vertex attribute divisor: 1 */
2814 	if (false == testProgramWithDivisor(iteration, _no_array__no_location_per_instance.m_program_id, false))
2815 	{
2816 		logTestIterationAndConfig(iteration, PER_INSTANCE, false /* use_arrays */, false /* use_locations */);
2817 
2818 		result = false;
2819 	}
2820 
2821 	if (false == testProgramWithDivisor(iteration, use_array__no_location_per_instance.m_program_id, true))
2822 	{
2823 		logTestIterationAndConfig(iteration, PER_INSTANCE, true /* use_arrays */, false /* use_locations */);
2824 
2825 		result = false;
2826 	}
2827 
2828 	if (false == testProgramWithDivisor(iteration, _no_array_use_location_per_instance.m_program_id, false))
2829 	{
2830 		logTestIterationAndConfig(iteration, PER_INSTANCE, false /* use_arrays */, true /* use_locations */);
2831 
2832 		result = false;
2833 	}
2834 
2835 	if (false == testProgramWithDivisor(iteration, use_array_use_location_per_instance.m_program_id, true))
2836 	{
2837 		logTestIterationAndConfig(iteration, PER_INSTANCE, true /* use_arrays */, true /* use_locations */);
2838 
2839 		result = false;
2840 	}
2841 
2842 	/* Done */
2843 	return result;
2844 }
2845 
2846 /** Tests regular and instanced draw calls with vertex attribute divisor set to 0
2847  *
2848  * @param iteration  Iteration id
2849  * @param program_id Program object id
2850  * @param use_arrays true if arrays of attributes are used
2851  *
2852  * @return true if tests pass, false otherwise
2853  **/
testProgram(_iteration iteration,GLuint program_id,bool use_arrays) const2854 bool LimitTest::testProgram(_iteration iteration, GLuint program_id, bool use_arrays) const
2855 {
2856 	bool result = true;
2857 
2858 	gl.useProgram(program_id);
2859 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
2860 
2861 	prepareVertexArray(iteration, REGULAR, program_id, use_arrays);
2862 
2863 	if (false == testDrawArrays())
2864 	{
2865 		result = false;
2866 	}
2867 
2868 	if (false == testDrawElements())
2869 	{
2870 		result = false;
2871 	}
2872 
2873 	if (false == testDrawArraysInstanced())
2874 	{
2875 		result = false;
2876 	}
2877 
2878 	if (false == testDrawElementsInstanced())
2879 	{
2880 		result = false;
2881 	}
2882 
2883 	return result;
2884 }
2885 
2886 /** Tests constant attributes value, set with VertexAttribLd* routines
2887  *
2888  * @param iteration  Iteration id
2889  * @param program_id Program object id
2890  * @param use_arrays true if arrays of attributes are used
2891  *
2892  * @return true if tests pass, false otherwise
2893  **/
testProgramWithConstant(_iteration iteration,GLuint program_id,bool use_arrays) const2894 bool LimitTest::testProgramWithConstant(_iteration iteration, GLuint program_id, bool use_arrays) const
2895 {
2896 	bool result = true;
2897 
2898 	gl.useProgram(program_id);
2899 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
2900 
2901 	prepareVertexArray(iteration, CONSTANT, program_id, use_arrays);
2902 
2903 	if (false == testDrawArrays())
2904 	{
2905 		result = false;
2906 	}
2907 
2908 	if (false == testDrawElements())
2909 	{
2910 		result = false;
2911 	}
2912 
2913 	return result;
2914 }
2915 
2916 /** Tests instanced draw calls with vertex attribute divisor set to 1
2917  *
2918  * @param iteration  Iteration id
2919  * @param program_id Program object id
2920  * @param use_arrays true if arrays of attributes are used
2921  *
2922  * @return true if tests pass, false otherwise
2923  **/
testProgramWithDivisor(_iteration iteration,GLuint program_id,bool use_arrays) const2924 bool LimitTest::testProgramWithDivisor(_iteration iteration, GLuint program_id, bool use_arrays) const
2925 {
2926 	bool result = true;
2927 
2928 	gl.useProgram(program_id);
2929 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
2930 
2931 	prepareVertexArray(iteration, PER_INSTANCE, program_id, use_arrays);
2932 
2933 	if (false == testDrawArraysInstanced())
2934 	{
2935 		result = false;
2936 	}
2937 
2938 	if (false == testDrawElementsInstanced())
2939 	{
2940 		result = false;
2941 	}
2942 
2943 	return result;
2944 }
2945 
2946 /** Verifies results
2947  *
2948  * @param use_instancing true if instanced draw call was made, otherwise false
2949  *
2950  * @result true if all vertices outputed 1, false otherwise
2951  **/
verifyResult(bool use_instancing) const2952 bool LimitTest::verifyResult(bool use_instancing) const
2953 {
2954 	_varyingType* buffer_data = (_varyingType*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2955 	const GLuint  n_instances = (true == use_instancing) ? m_n_instances : 1;
2956 	bool		  result	  = true;
2957 
2958 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
2959 
2960 	if (0 == buffer_data)
2961 	{
2962 		TCU_FAIL("Failed to map GL_TRANSFORM_FEEDBACK_BUFFER buffer");
2963 	}
2964 
2965 	/* For each instance */
2966 	for (GLuint instance = 0; instance < n_instances; ++instance)
2967 	{
2968 		const GLuint instance_offset = instance * m_n_vertices * m_n_varyings;
2969 
2970 		/* For each vertex */
2971 		for (GLuint vertex = 0; vertex < m_n_vertices; ++vertex)
2972 		{
2973 			const GLuint vertex_offset = vertex * m_n_varyings;
2974 
2975 			if (1 != buffer_data[vertex_offset + instance_offset])
2976 			{
2977 				if (true == use_instancing)
2978 				{
2979 					m_log << tcu::TestLog::Message << "Failure. Instance: " << instance << " Vertex: " << vertex
2980 						  << tcu::TestLog::EndMessage;
2981 				}
2982 				else
2983 				{
2984 					m_log << tcu::TestLog::Message << "Failure. Vertex: " << vertex << tcu::TestLog::EndMessage;
2985 				}
2986 
2987 				/* Save failure and break loop */
2988 				result = false;
2989 
2990 				/* Sorry about that, but this is nested loop */
2991 				goto end;
2992 			}
2993 		}
2994 	}
2995 
2996 end:
2997 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2998 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
2999 
3000 	return result;
3001 }
3002 
3003 /** Implementation of conformance test "4", description follows.
3004  *
3005  *  Make sure non-trivial VAO configurations are correctly supported
3006  *  for double-precision floating-point types.
3007  *
3008  *  Consider the following Vertex Buffer Object configurations:
3009  *
3010  *  BO1:
3011  *  0            72 73 75      91 96
3012  *  --------------+-+--+-------+---
3013  *  |      A      |B| C|    D  | E|  (times 1024)
3014  *  -------------------------------
3015  *
3016  *  where:
3017  *
3018  *  A: 3x3 double matrix  (72 bytes)
3019  *  B: 1 unsigned byte    (1  byte)
3020  *  C: 1 short            (2  bytes)
3021  *  D: 2 doubles          (16 bytes)
3022  *  E: padding            (5  bytes)
3023  *                     (+) --------
3024  *                         96 bytes
3025  *
3026  *  BO2:
3027  *  --+------------------
3028  *  |A|         B       |  (times 1024)
3029  *  --+------------------
3030  *
3031  *  where:
3032  *
3033  *  A: 1 signed byte     (1  byte)
3034  *  B: 4x2 double matrix (64 bytes)
3035  *                    (+) --------
3036  *                        65 bytes
3037  *
3038  *  A VAO used for the test should be configured as described
3039  *  below:
3040  *
3041  *  Att 0 (L): VAP-type:GL_DOUBLE,        GLSL-type: dmat3,   stride:96,
3042  *             offset:  0,                normalized:0,       source:BO1;
3043  *  Att 1 (F): VAP-type:GL_UNSIGNED_BYTE, GLSL-type: float,   stride:5,
3044  *             offset:  0,                normalized:1,       source:BO2;
3045  *  Att 2 (L): VAP-type:GL_DOUBLE,        GLSL-type: dvec2,   stride:96,
3046  *             offset:  75,               normalized:0,       source:BO1;
3047  *  Att 3 (L): VAP-type:GL_DOUBLE,        GLSL-type: double,  stride:48,
3048  *             offset:  0,                normalized:0,       source:BO1;
3049  *  Att 4 (L): VAP-type:GL_DOUBLE,        GLSL-type: dmat4x2, stride:65,
3050  *             offset:  1,                normalized:0,       source:BO2;
3051  *  Att 5 (F): VAP-type:GL_SHORT,         GLSL-type: float,   stride:96,
3052  *             offset:  73,               normalized:0,       source:BO1;
3053  *  Att 6 (I): VAP-type:GL_BYTE,          GLSL-type: int,     stride:96,
3054  *             offset:  72,               normalized:1,       source:BO1;
3055  *
3056  *  where:
3057  *
3058  *  GLSL-type: Input variable type, as to be used in corresponding
3059  *             vertex shader.
3060  *  (F):       glVertexAttribPointer() call should be used to configure
3061  *             given vertex attribute array;
3062  *  (I):       glVertexAttribIPointer() call should be used to configure
3063  *             given vertex attribute array;
3064  *  (L):       glVertexAttribLPointer() call should be used to configure
3065  *             given vertex attribute array;
3066  *  VAP-type:  <type> argument as passed to corresponding
3067  *             glVertexAttrib*Pointer() call.
3068  *
3069  *  The test should use a program object consisting only of VS.
3070  *  The shader should read all the attributes and store the
3071  *  values in corresponding output variables. These should then be
3072  *  XFBed out to the test implementation, which should then verify
3073  *  the values read in the shader are valid in light of the specification.
3074  *
3075  *  All the draw call types described in test 3) should be tested.
3076  *  A single draw call for each of the types, rendering a total of
3077  *  1024 points should be used for the purpose of the test
3078  *
3079  **/
3080 class VAOTest : public Base
3081 {
3082 public:
3083 	/* Public methods */
3084 	VAOTest(deqp::Context& context);
3085 
~VAOTest()3086 	virtual ~VAOTest()
3087 	{
3088 	}
3089 
3090 	/* Public methods inheritated from TestCase */
3091 	virtual void						 deinit();
3092 	virtual tcu::TestNode::IterateResult iterate();
3093 
3094 private:
3095 	/* Private type declarations */
3096 	enum _draw_call_type
3097 	{
3098 		DRAW_CALL_TYPE_ARRAYS,
3099 		DRAW_CALL_TYPE_ELEMENTS,
3100 
3101 		/* Always last */
3102 		DRAW_CALL_TYPE_COUNT
3103 	};
3104 
3105 	/* Private methods */
3106 	bool executeTest(_draw_call_type draw_call, bool instanced, bool zero_vertex_attrib_divisor);
3107 
3108 	void initBufferObjects();
3109 	void initBuffers();
3110 	void initProgramObject();
3111 	void initVAO();
3112 
3113 	bool verifyXFBData(const void* data, _draw_call_type draw_call, bool instanced, bool zero_vertex_attrib_divisor);
3114 
3115 	/* Private fields */
3116 	unsigned char*  m_bo_1_data;
3117 	unsigned int	m_bo_1_data_size;
3118 	unsigned int	m_bo_1_offset_matrix;
3119 	unsigned int	m_bo_1_offset_ubyte;
3120 	unsigned int	m_bo_1_offset_short;
3121 	unsigned int	m_bo_1_offset_double;
3122 	unsigned char*  m_bo_2_data;
3123 	unsigned int	m_bo_2_data_size;
3124 	unsigned int	m_bo_2_offset_sbyte;
3125 	unsigned int	m_bo_2_offset_matrix;
3126 	unsigned short* m_bo_index_data;
3127 	unsigned int	m_bo_index_data_size;
3128 	glw::GLuint		m_bo_id_1;
3129 	glw::GLuint		m_bo_id_2;
3130 	glw::GLuint		m_bo_id_indices;
3131 	glw::GLuint		m_bo_id_result;
3132 	glw::GLint		m_po_bo1_dmat3_attr_location;
3133 	glw::GLint		m_po_bo2_dmat4x2_attr_location;
3134 	glw::GLint		m_po_bo1_double_attr_location;
3135 	glw::GLint		m_po_bo1_dvec2_attr_location;
3136 	glw::GLint		m_po_bo1_float2_attr_location;
3137 	glw::GLint		m_po_bo1_int_attr_location;
3138 	glw::GLint		m_po_bo2_float_attr_location;
3139 	glw::GLuint		m_po_id;
3140 	glw::GLuint		m_vao_id;
3141 	glw::GLuint		m_vs_id;
3142 	unsigned int	m_xfb_bo1_dmat3_offset;
3143 	unsigned int	m_xfb_bo1_dmat3_size;
3144 	unsigned int	m_xfb_bo1_double_offset;
3145 	unsigned int	m_xfb_bo1_double_size;
3146 	unsigned int	m_xfb_bo1_dvec2_offset;
3147 	unsigned int	m_xfb_bo1_dvec2_size;
3148 	unsigned int	m_xfb_bo1_float2_offset;
3149 	unsigned int	m_xfb_bo1_float2_size;
3150 	unsigned int	m_xfb_bo1_int_offset;
3151 	unsigned int	m_xfb_bo1_int_size;
3152 	unsigned int	m_xfb_bo2_dmat4x2_offset;
3153 	unsigned int	m_xfb_bo2_dmat4x2_size;
3154 	unsigned int	m_xfb_bo2_float_offset;
3155 	unsigned int	m_xfb_bo2_float_size;
3156 	unsigned int	m_xfb_total_size;
3157 
3158 	const unsigned int m_bo_1_batch_size;
3159 	const unsigned int m_bo_2_batch_size;
3160 	const unsigned int m_n_batches;
3161 	const unsigned int m_n_draw_call_instances;
3162 	const unsigned int m_nonzero_vertex_attrib_divisor;
3163 	const unsigned int m_po_bo1_dmat3_attr_offset;
3164 	const unsigned int m_po_bo1_dmat3_attr_stride;
3165 	const unsigned int m_po_bo1_double_attr_offset;
3166 	const unsigned int m_po_bo1_double_attr_stride;
3167 	const unsigned int m_po_bo1_dvec2_attr_offset;
3168 	const unsigned int m_po_bo1_dvec2_attr_stride;
3169 	const unsigned int m_po_bo1_float2_attr_offset;
3170 	const unsigned int m_po_bo1_float2_attr_stride;
3171 	const unsigned int m_po_bo1_int_attr_offset;
3172 	const unsigned int m_po_bo1_int_attr_stride;
3173 	const unsigned int m_po_bo2_dmat4x2_attr_offset;
3174 	const unsigned int m_po_bo2_dmat4x2_attr_stride;
3175 	const unsigned int m_po_bo2_float_attr_offset;
3176 	const unsigned int m_po_bo2_float_attr_stride;
3177 };
3178 
3179 /** Constructor
3180  *
3181  * @param context CTS context instance
3182  **/
VAOTest(deqp::Context & context)3183 VAOTest::VAOTest(deqp::Context& context)
3184 	: Base(context, "vao", "Verify that non-trivial VAO configurations are correctly supported "
3185 						   "for double-precision floating-point types.")
3186 	, m_bo_1_data(DE_NULL)
3187 	, m_bo_1_data_size(0)
3188 	, m_bo_1_offset_matrix(0)
3189 	, m_bo_1_offset_ubyte(72)
3190 	, m_bo_1_offset_short(73)
3191 	, m_bo_1_offset_double(75)
3192 	, m_bo_2_data(DE_NULL)
3193 	, m_bo_2_data_size(0)
3194 	, m_bo_2_offset_sbyte(0)
3195 	, m_bo_2_offset_matrix(1)
3196 	, m_bo_index_data(DE_NULL)
3197 	, m_bo_index_data_size(0)
3198 	, m_bo_id_1(0)
3199 	, m_bo_id_2(0)
3200 	, m_bo_id_indices(0)
3201 	, m_bo_id_result(0)
3202 	, m_po_bo1_dmat3_attr_location(-1)
3203 	, m_po_bo2_dmat4x2_attr_location(-1)
3204 	, m_po_bo1_double_attr_location(-1)
3205 	, m_po_bo1_dvec2_attr_location(-1)
3206 	, m_po_bo1_float2_attr_location(-1)
3207 	, m_po_bo1_int_attr_location(-1)
3208 	, m_po_bo2_float_attr_location(-1)
3209 	, m_po_id(0)
3210 	, m_vao_id(0)
3211 	, m_vs_id(0)
3212 	, m_xfb_bo1_dmat3_offset(0)
3213 	, m_xfb_bo1_dmat3_size(0)
3214 	, m_xfb_bo1_double_offset(0)
3215 	, m_xfb_bo1_double_size(0)
3216 	, m_xfb_bo1_dvec2_offset(0)
3217 	, m_xfb_bo1_dvec2_size(0)
3218 	, m_xfb_bo1_float2_offset(0)
3219 	, m_xfb_bo1_float2_size(0)
3220 	, m_xfb_bo1_int_offset(0)
3221 	, m_xfb_bo1_int_size(0)
3222 	, m_xfb_bo2_dmat4x2_offset(0)
3223 	, m_xfb_bo2_dmat4x2_size(0)
3224 	, m_xfb_bo2_float_offset(0)
3225 	, m_xfb_bo2_float_size(0)
3226 	, m_xfb_total_size(0)
3227 	, m_bo_1_batch_size(96)
3228 	, m_bo_2_batch_size(65)
3229 	, m_n_batches(1024)
3230 	, m_n_draw_call_instances(4)
3231 	, m_nonzero_vertex_attrib_divisor(2)
3232 	, m_po_bo1_dmat3_attr_offset(0)
3233 	, m_po_bo1_dmat3_attr_stride(96)
3234 	, m_po_bo1_double_attr_offset(0)
3235 	, m_po_bo1_double_attr_stride(48)
3236 	, m_po_bo1_dvec2_attr_offset(75)
3237 	, m_po_bo1_dvec2_attr_stride(96)
3238 	, m_po_bo1_float2_attr_offset(73)
3239 	, m_po_bo1_float2_attr_stride(96)
3240 	, m_po_bo1_int_attr_offset(72)
3241 	, m_po_bo1_int_attr_stride(96)
3242 	, m_po_bo2_dmat4x2_attr_offset(1)
3243 	, m_po_bo2_dmat4x2_attr_stride(65)
3244 	, m_po_bo2_float_attr_offset(0)
3245 	, m_po_bo2_float_attr_stride(5)
3246 {
3247 	/* Nothing to be done here */
3248 }
3249 
3250 /** Deinitializes GL objects and deallocates buffers that may have
3251  *  been created during test execution */
deinit()3252 void VAOTest::deinit()
3253 {
3254 	if (m_bo_1_data != DE_NULL)
3255 	{
3256 		delete[] m_bo_1_data;
3257 
3258 		m_bo_1_data = DE_NULL;
3259 	}
3260 
3261 	if (m_bo_2_data != DE_NULL)
3262 	{
3263 		delete[] m_bo_2_data;
3264 
3265 		m_bo_2_data = DE_NULL;
3266 	}
3267 
3268 	if (m_bo_index_data != DE_NULL)
3269 	{
3270 		delete[] m_bo_index_data;
3271 
3272 		m_bo_index_data = DE_NULL;
3273 	}
3274 
3275 	if (m_bo_id_1 != 0)
3276 	{
3277 		gl.deleteBuffers(1, &m_bo_id_1);
3278 
3279 		m_bo_id_1 = 0;
3280 	}
3281 
3282 	if (m_bo_id_2 != 0)
3283 	{
3284 		gl.deleteBuffers(1, &m_bo_id_2);
3285 
3286 		m_bo_id_2 = 0;
3287 	}
3288 
3289 	if (m_bo_id_indices != 0)
3290 	{
3291 		gl.deleteBuffers(1, &m_bo_id_indices);
3292 
3293 		m_bo_id_indices = 0;
3294 	}
3295 
3296 	if (m_bo_id_result != 0)
3297 	{
3298 		gl.deleteBuffers(1, &m_bo_id_result);
3299 
3300 		m_bo_id_result = 0;
3301 	}
3302 
3303 	if (m_po_id != 0)
3304 	{
3305 		gl.deleteProgram(m_po_id);
3306 
3307 		m_po_id = 0;
3308 	}
3309 
3310 	if (m_vao_id != 0)
3311 	{
3312 		gl.deleteVertexArrays(1, &m_vao_id);
3313 
3314 		m_vao_id = 0;
3315 	}
3316 
3317 	if (m_vs_id != 0)
3318 	{
3319 		gl.deleteShader(m_vs_id);
3320 
3321 		m_vs_id = 0;
3322 	}
3323 }
3324 
3325 /** Executes a single test iteration.
3326  *
3327  *  This function may throw error exceptions if GL implementation misbehaves.
3328  *
3329  *  @param draw_call                  Type of the draw call that should be issued.
3330  *  @param instanced                  True if the draw call should be instanced, false otherwise.
3331  *  @param zero_vertex_attrib_divisor True if a zero divisor should be used for all checked attributes,
3332  *                                    false to use a value of m_nonzero_vertex_attrib_divisor as the divisor.
3333  *
3334  *  @return true if the test iteration passed, false otherwise.
3335  **/
executeTest(_draw_call_type draw_call,bool instanced,bool zero_vertex_attrib_divisor)3336 bool VAOTest::executeTest(_draw_call_type draw_call, bool instanced, bool zero_vertex_attrib_divisor)
3337 {
3338 	bool result = true;
3339 
3340 	gl.beginTransformFeedback(GL_POINTS);
3341 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
3342 	{
3343 		const glw::GLint divisor	  = (zero_vertex_attrib_divisor) ? 0 : m_nonzero_vertex_attrib_divisor;
3344 		const glw::GLint attributes[] = { m_po_bo1_dmat3_attr_location,		  m_po_bo1_dmat3_attr_location + 1,
3345 										  m_po_bo1_dmat3_attr_location + 2,
3346 
3347 										  m_po_bo2_dmat4x2_attr_location,	 m_po_bo2_dmat4x2_attr_location + 1,
3348 										  m_po_bo2_dmat4x2_attr_location + 2, m_po_bo2_dmat4x2_attr_location + 3,
3349 
3350 										  m_po_bo1_double_attr_location,	  m_po_bo1_dvec2_attr_location,
3351 										  m_po_bo1_float2_attr_location,	  m_po_bo1_int_attr_location,
3352 										  m_po_bo2_float_attr_location };
3353 		const unsigned int n_attributes = sizeof(attributes) / sizeof(attributes[0]);
3354 
3355 		for (unsigned int n_attribute = 0; n_attribute < n_attributes; ++n_attribute)
3356 		{
3357 			glw::GLint attribute = attributes[n_attribute];
3358 
3359 			/* Configure vertex attribute divisor */
3360 			gl.vertexAttribDivisor(attribute, divisor);
3361 			GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribDivisor() call failed.");
3362 		} /* for (all attribute locations) */
3363 
3364 		/* Issue the draw call */
3365 		switch (draw_call)
3366 		{
3367 		case DRAW_CALL_TYPE_ARRAYS:
3368 		{
3369 			if (instanced)
3370 			{
3371 				gl.drawArraysInstanced(GL_POINTS, 0 /* first */, m_n_batches, m_n_draw_call_instances);
3372 				GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArraysInstanced() call failed");
3373 			}
3374 			else
3375 			{
3376 				gl.drawArrays(GL_POINTS, 0 /* first */, m_n_batches);
3377 				GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
3378 			}
3379 
3380 			break;
3381 		} /* case DRAW_CALL_TYPE_ARRAYS: */
3382 
3383 		case DRAW_CALL_TYPE_ELEMENTS:
3384 		{
3385 			if (instanced)
3386 			{
3387 				gl.drawElementsInstanced(GL_POINTS, m_n_batches, GL_UNSIGNED_SHORT, DE_NULL /* indices */,
3388 										 m_n_draw_call_instances);
3389 				GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsInstanced() call failed.");
3390 			}
3391 			else
3392 			{
3393 				gl.drawElements(GL_POINTS, m_n_batches, GL_UNSIGNED_SHORT, DE_NULL); /* indices */
3394 				GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements() call failed.");
3395 			}
3396 
3397 			break;
3398 		} /* case DRAW_CALL_TYPE_ELEMENTS: */
3399 
3400 		default:
3401 		{
3402 			TCU_FAIL("Unrecognized draw call type");
3403 		}
3404 		} /* switch (draw_call) */
3405 	}
3406 	gl.endTransformFeedback();
3407 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
3408 
3409 	/* Retrieve the results */
3410 	const void* pXFBData = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
3411 
3412 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
3413 
3414 	/* Verify the data */
3415 	result = verifyXFBData(pXFBData, draw_call, instanced, zero_vertex_attrib_divisor);
3416 
3417 	/* Unmap the buffer */
3418 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3419 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
3420 
3421 	return result;
3422 }
3423 
3424 /** Initializes buffer objects that will be used by the test.
3425  *
3426  *  This function may throw error exceptions if GL implementation misbehaves.
3427  **/
initBufferObjects()3428 void VAOTest::initBufferObjects()
3429 {
3430 	DE_ASSERT(m_bo_1_data != DE_NULL);
3431 	DE_ASSERT(m_bo_2_data != DE_NULL);
3432 
3433 	/* Generate BOs */
3434 	gl.genBuffers(1, &m_bo_id_1);
3435 	gl.genBuffers(1, &m_bo_id_2);
3436 	gl.genBuffers(1, &m_bo_id_indices);
3437 	gl.genBuffers(1, &m_bo_id_result);
3438 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
3439 
3440 	/* Initiailize BO storage */
3441 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_1);
3442 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
3443 
3444 	gl.bufferData(GL_ARRAY_BUFFER, m_bo_1_data_size, m_bo_1_data, GL_STATIC_DRAW);
3445 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
3446 
3447 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_2);
3448 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
3449 
3450 	gl.bufferData(GL_ARRAY_BUFFER, m_bo_2_data_size, m_bo_2_data, GL_STATIC_DRAW);
3451 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
3452 
3453 	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id_indices);
3454 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
3455 
3456 	gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, m_bo_index_data_size, m_bo_index_data, GL_STATIC_DRAW);
3457 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
3458 
3459 	/* Finally, reserve sufficient amount of space for the data to be XFBed out from
3460 	 * the test program. We need:
3461 	 *
3462 	 * a) dmat3:   (3 * 3 * 2) components: 18 float components
3463 	 * b) float:   (1)         component :  1 float component
3464 	 * c) dvec2:   (2 * 2)     components:  4 float components
3465 	 * d) double:  (1 * 2)     components:  2 float components
3466 	 * e) dmat4x2: (4 * 2 * 2) components: 16 float components
3467 	 * f) int:     (1)         components:  1 int   component
3468 	 * g) float:   (1)         component:   1 float components
3469 	 * h) padding: 4 bytes because fp64 buffer needs 8 bytes alignment
3470 	 *                                 (+)------
3471 	 *                                    (42 float + 1 int + 4 bytes padding) components times 1024 batches: 43008 floats, 1024 ints
3472 	 *
3473 	 * Don't forget about instanced draw calls. We'll be XFBing data for either 1 or m_n_draw_call_instances
3474 	 * instances.
3475 	 */
3476 	const unsigned int xfb_dat_pad = sizeof(int);
3477 	const unsigned int xfb_data_size =
3478 		static_cast<unsigned int>((42 * sizeof(float) + sizeof(int) + xfb_dat_pad) * 1024 * m_n_draw_call_instances);
3479 
3480 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_result);
3481 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
3482 
3483 	gl.bufferData(GL_ARRAY_BUFFER, xfb_data_size, DE_NULL /* data */, GL_STATIC_DRAW);
3484 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
3485 
3486 	/* Set up XFB bindings */
3487 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_result);
3488 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
3489 
3490 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id_result);
3491 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
3492 }
3493 
3494 /** Initializes buffers that will later be used to fill storage of buffer objects used by the test. */
initBuffers()3495 void VAOTest::initBuffers()
3496 {
3497 	DE_ASSERT(m_bo_1_data == DE_NULL);
3498 	DE_ASSERT(m_bo_2_data == DE_NULL);
3499 	DE_ASSERT(m_bo_index_data == DE_NULL);
3500 
3501 	/* Prepare buffers storing underlying data. The buffers will be used for:
3502 	 *
3503 	 * - storage purposes;
3504 	 * - verification of the data XFBed from the vertex shader.
3505 	 */
3506 	m_bo_1_data_size	 = m_bo_1_batch_size * m_n_batches;
3507 	m_bo_2_data_size	 = m_bo_2_batch_size * m_n_batches;
3508 	m_bo_index_data_size = static_cast<unsigned int>(sizeof(unsigned short) * m_n_batches);
3509 
3510 	m_bo_1_data		= new unsigned char[m_bo_1_data_size];
3511 	m_bo_2_data		= new unsigned char[m_bo_2_data_size];
3512 	m_bo_index_data = new unsigned short[m_bo_index_data_size / sizeof(unsigned short)];
3513 
3514 	/* Workaround for alignment issue that may result in bus error on some platforms */
3515 	union {
3516 		double		  d;
3517 		unsigned char c[sizeof(double)];
3518 	} u;
3519 
3520 	/* Fill index data */
3521 	for (unsigned short n_index = 0; n_index < (unsigned short)m_n_batches; ++n_index)
3522 	{
3523 		m_bo_index_data[n_index] = (unsigned short)((unsigned short)(m_n_batches - 1) - n_index);
3524 	}
3525 
3526 	/* Fill 3x3 matrix data in BO1 */
3527 	for (unsigned int n_matrix = 0; n_matrix < m_n_batches; ++n_matrix)
3528 	{
3529 		double* matrix_ptr = (double*)(m_bo_1_data + n_matrix * m_bo_1_batch_size + m_bo_1_offset_matrix);
3530 
3531 		for (unsigned int n_element = 0; n_element < 9 /* 3x3 matrix */; ++n_element)
3532 		{
3533 			matrix_ptr[n_element] = (double)(n_matrix * 3 * 3 + n_element + 1);
3534 		}
3535 	} /* for (all matrices) */
3536 
3537 	/* Fill unsigned byte data in BO1 */
3538 	for (unsigned int n_element = 0; n_element < m_n_batches; ++n_element)
3539 	{
3540 		unsigned char* data_ptr = m_bo_1_data + n_element * m_bo_1_batch_size + m_bo_1_offset_ubyte;
3541 
3542 		*data_ptr = (unsigned char)n_element;
3543 	}
3544 
3545 	/* Fill short data in BO1 */
3546 	for (unsigned int n_element = 0; n_element < m_n_batches; ++n_element)
3547 	{
3548 		unsigned short* data_ptr = (unsigned short*)(m_bo_1_data + n_element * m_bo_1_batch_size + m_bo_1_offset_short);
3549 
3550 		*data_ptr = (unsigned short)n_element;
3551 	}
3552 
3553 	/* Fill 2 doubles data in BO1 */
3554 	for (unsigned int n_batch = 0; n_batch < m_n_batches; ++n_batch)
3555 	{
3556 		unsigned char* data1_ptr = m_bo_1_data + n_batch * m_bo_1_batch_size + m_bo_1_offset_double;
3557 		unsigned char* data2_ptr = data1_ptr + sizeof(double);
3558 
3559 		u.d = (double)(2 * n_batch);
3560 		memcpy(data1_ptr, u.c, sizeof(double));
3561 		u.d = (double)(2 * n_batch + 1);
3562 		memcpy(data2_ptr, u.c, sizeof(double));
3563 	}
3564 
3565 	/* Fill signed byte data in BO2 */
3566 	for (unsigned int n_element = 0; n_element < m_n_batches; ++n_element)
3567 	{
3568 		signed char* data_ptr = (signed char*)(m_bo_2_data + n_element * m_bo_2_batch_size + m_bo_2_offset_sbyte);
3569 
3570 		*data_ptr = (signed char)n_element;
3571 	}
3572 
3573 	/* Fill 4x2 matrix data in BO2 */
3574 	for (unsigned int n_matrix = 0; n_matrix < m_n_batches; ++n_matrix)
3575 	{
3576 		unsigned char* matrix_ptr = m_bo_2_data + n_matrix * m_bo_2_batch_size + m_bo_2_offset_matrix;
3577 
3578 		for (unsigned int n_element = 0; n_element < 8 /* 4x2 matrix */; ++n_element)
3579 		{
3580 			u.d = (double)(n_matrix * 4 * 2 + n_element);
3581 			memcpy(matrix_ptr + (sizeof(double) * n_element), u.c, sizeof(double));
3582 		}
3583 	} /* for (all matrices) */
3584 }
3585 
3586 /** Initializes a program object used by the test.
3587  *
3588  *  This function may throw error exceptions if GL implementation misbehaves.
3589  *
3590  **/
initProgramObject()3591 void VAOTest::initProgramObject()
3592 {
3593 	DE_ASSERT(m_po_id == 0);
3594 	DE_ASSERT(m_vs_id == 0);
3595 
3596 	/* Generate a program object */
3597 	m_po_id = gl.createProgram();
3598 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3599 
3600 	/* Configure XFB */
3601 	const char* xfb_varyings[] = { "out_bo1_dmat3",  "out_bo1_double",  "out_bo1_int",   "out_bo1_dvec2",
3602 								   "out_bo1_float2", "out_bo2_dmat4x2", "out_bo2_float", "gl_SkipComponents1" };
3603 	const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]);
3604 
3605 	gl.transformFeedbackVaryings(m_po_id, n_xfb_varyings, xfb_varyings, GL_INTERLEAVED_ATTRIBS);
3606 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
3607 
3608 	/* Initialize XFB-specific offset information for the verification routine */
3609 	m_xfb_bo1_dmat3_offset   = 0;
3610 	m_xfb_bo1_dmat3_size	 = sizeof(double) * 3 * 3;
3611 	m_xfb_bo1_double_offset  = m_xfb_bo1_dmat3_offset + m_xfb_bo1_dmat3_size;
3612 	m_xfb_bo1_double_size	= sizeof(double);
3613 	m_xfb_bo1_int_offset	 = m_xfb_bo1_double_offset + m_xfb_bo1_double_size;
3614 	m_xfb_bo1_int_size		 = sizeof(int);
3615 	m_xfb_bo1_dvec2_offset   = m_xfb_bo1_int_offset + m_xfb_bo1_int_size;
3616 	m_xfb_bo1_dvec2_size	 = sizeof(double) * 2;
3617 	m_xfb_bo1_float2_offset  = m_xfb_bo1_dvec2_offset + m_xfb_bo1_dvec2_size;
3618 	m_xfb_bo1_float2_size	= sizeof(float);
3619 	m_xfb_bo2_dmat4x2_offset = m_xfb_bo1_float2_offset + m_xfb_bo1_float2_size;
3620 	m_xfb_bo2_dmat4x2_size   = sizeof(double) * 4 * 2;
3621 	m_xfb_bo2_float_offset   = m_xfb_bo2_dmat4x2_offset + m_xfb_bo2_dmat4x2_size;
3622 	m_xfb_bo2_float_size	 = sizeof(float);
3623 	m_xfb_total_size = m_xfb_bo1_dmat3_size + m_xfb_bo1_double_size + m_xfb_bo1_int_size + m_xfb_bo1_dvec2_size +
3624 					   m_xfb_bo1_float2_size + m_xfb_bo2_dmat4x2_size + m_xfb_bo2_float_size + sizeof(int);
3625 
3626 	/* Build the test program object */
3627 	const char* vs_code = "#version 400\n"
3628 						  "\n"
3629 						  "#extension GL_ARB_vertex_attrib_64bit : require\n"
3630 						  "\n"
3631 						  "in dmat3   in_bo1_dmat3;\n"
3632 						  "in double  in_bo1_double;\n"
3633 						  "in dvec2   in_bo1_dvec2;\n"
3634 						  "in float   in_bo1_float2;\n"
3635 						  "in int     in_bo1_int;\n"
3636 						  "in dmat4x2 in_bo2_dmat4x2;\n"
3637 						  "in float   in_bo2_float;\n"
3638 						  "\n"
3639 						  "out dmat3   out_bo1_dmat3;\n"
3640 						  "out double  out_bo1_double;\n"
3641 						  "out dvec2   out_bo1_dvec2;\n"
3642 						  "out float   out_bo1_float2;\n"
3643 						  "out int     out_bo1_int;\n"
3644 						  "out dmat4x2 out_bo2_dmat4x2;\n"
3645 						  "out float   out_bo2_float;\n"
3646 						  "\n"
3647 						  "void main()\n"
3648 						  "{\n"
3649 						  "    out_bo1_dmat3   = in_bo1_dmat3;\n"
3650 						  "    out_bo1_double  = in_bo1_double;\n"
3651 						  "    out_bo1_dvec2   = in_bo1_dvec2;\n"
3652 						  "    out_bo1_int     = in_bo1_int;\n"
3653 						  "    out_bo1_float2  = in_bo1_float2;\n"
3654 						  "    out_bo2_dmat4x2 = in_bo2_dmat4x2;\n"
3655 						  "    out_bo2_float   = in_bo2_float;\n"
3656 						  "}\n";
3657 
3658 	BuildProgramVSOnly(m_po_id, vs_code, m_vs_id);
3659 
3660 	m_po_bo1_dmat3_attr_location   = gl.getAttribLocation(m_po_id, "in_bo1_dmat3");
3661 	m_po_bo1_double_attr_location  = gl.getAttribLocation(m_po_id, "in_bo1_double");
3662 	m_po_bo1_dvec2_attr_location   = gl.getAttribLocation(m_po_id, "in_bo1_dvec2");
3663 	m_po_bo1_float2_attr_location  = gl.getAttribLocation(m_po_id, "in_bo1_float2");
3664 	m_po_bo1_int_attr_location	 = gl.getAttribLocation(m_po_id, "in_bo1_int");
3665 	m_po_bo2_dmat4x2_attr_location = gl.getAttribLocation(m_po_id, "in_bo2_dmat4x2");
3666 	m_po_bo2_float_attr_location   = gl.getAttribLocation(m_po_id, "in_bo2_float");
3667 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation() call(s) failed.");
3668 
3669 	if (m_po_bo1_dmat3_attr_location == -1 || m_po_bo1_double_attr_location == -1 ||
3670 		m_po_bo1_dvec2_attr_location == -1 || m_po_bo1_int_attr_location == -1 || m_po_bo1_float2_attr_location == -1 ||
3671 		m_po_bo2_dmat4x2_attr_location == -1 || m_po_bo2_float_attr_location == -1)
3672 	{
3673 		TCU_FAIL("At least one attribute is considered inactive which is invalid.");
3674 	}
3675 }
3676 
3677 /** Initializes a vertex array object used by the test.
3678  *
3679  *  This function may throw error exceptions if GL implementation misbehaves.
3680  **/
initVAO()3681 void VAOTest::initVAO()
3682 {
3683 	gl.genVertexArrays(1, &m_vao_id);
3684 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
3685 
3686 	gl.bindVertexArray(m_vao_id);
3687 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
3688 
3689 	/* Set up BO1-sourced attributes */
3690 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_1);
3691 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
3692 
3693 	gl.vertexAttribLPointer(m_po_bo1_dmat3_attr_location + 0, 3, /* size */
3694 							GL_DOUBLE, m_po_bo1_dmat3_attr_stride,
3695 							(const glw::GLvoid*)(deUintptr)m_po_bo1_dmat3_attr_offset);
3696 	gl.vertexAttribLPointer(m_po_bo1_dmat3_attr_location + 1, 3, /* size */
3697 							GL_DOUBLE, m_po_bo1_dmat3_attr_stride,
3698 							(const glw::GLvoid*)(m_po_bo1_dmat3_attr_offset + 1 * sizeof(double) * 3));
3699 	gl.vertexAttribLPointer(m_po_bo1_dmat3_attr_location + 2, 3, /* size */
3700 							GL_DOUBLE, m_po_bo1_dmat3_attr_stride,
3701 							(const glw::GLvoid*)(m_po_bo1_dmat3_attr_offset + 2 * sizeof(double) * 3));
3702 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribLPointer() call(s) failed.");
3703 
3704 	gl.enableVertexAttribArray(m_po_bo1_dmat3_attr_location + 0);
3705 	gl.enableVertexAttribArray(m_po_bo1_dmat3_attr_location + 1);
3706 	gl.enableVertexAttribArray(m_po_bo1_dmat3_attr_location + 2);
3707 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call(s) failed.");
3708 
3709 	gl.vertexAttribLPointer(m_po_bo1_dvec2_attr_location, 2, /* size */
3710 							GL_DOUBLE, m_po_bo1_dvec2_attr_stride,
3711 							(const glw::GLvoid*)(deUintptr)m_po_bo1_dvec2_attr_offset);
3712 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribLPointer() call failed.");
3713 
3714 	gl.enableVertexAttribArray(m_po_bo1_dvec2_attr_location);
3715 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
3716 
3717 	gl.vertexAttribLPointer(m_po_bo1_double_attr_location, 1, /* size */
3718 							GL_DOUBLE, m_po_bo1_double_attr_stride,
3719 							(const glw::GLvoid*)(deUintptr)m_po_bo1_double_attr_offset);
3720 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribLPointer() call failed.");
3721 
3722 	gl.enableVertexAttribArray(m_po_bo1_double_attr_location);
3723 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
3724 
3725 	gl.vertexAttribPointer(m_po_bo1_float2_attr_location, 1, /* size */
3726 						   GL_SHORT, GL_FALSE,				 /* normalized */
3727 						   m_po_bo1_float2_attr_stride, (const glw::GLvoid*)(deUintptr)m_po_bo1_float2_attr_offset);
3728 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
3729 
3730 	gl.enableVertexAttribArray(m_po_bo1_float2_attr_location);
3731 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
3732 
3733 	gl.vertexAttribIPointer(m_po_bo1_int_attr_location, 1, /* size */
3734 							GL_BYTE, m_po_bo1_int_attr_stride, (const glw::GLvoid*)(deUintptr)m_po_bo1_int_attr_offset);
3735 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer() call failed.");
3736 
3737 	gl.enableVertexAttribArray(m_po_bo1_int_attr_location);
3738 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
3739 
3740 	/* Set up BO2-sourced attributes */
3741 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_2);
3742 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
3743 
3744 	gl.vertexAttribPointer(m_po_bo2_float_attr_location, 1, /* size */
3745 						   GL_UNSIGNED_BYTE, GL_TRUE, m_po_bo2_float_attr_stride,
3746 						   (const glw::GLvoid*)(deUintptr)m_po_bo2_float_attr_offset);
3747 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
3748 
3749 	gl.enableVertexAttribArray(m_po_bo2_float_attr_location);
3750 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
3751 
3752 	gl.vertexAttribLPointer(m_po_bo2_dmat4x2_attr_location + 0, 2, /* size */
3753 							GL_DOUBLE, m_po_bo2_dmat4x2_attr_stride,
3754 							(const glw::GLvoid*)(deUintptr)m_po_bo2_dmat4x2_attr_offset);
3755 	gl.vertexAttribLPointer(m_po_bo2_dmat4x2_attr_location + 1, 2, /* size */
3756 							GL_DOUBLE, m_po_bo2_dmat4x2_attr_stride,
3757 							(const glw::GLvoid*)(m_po_bo2_dmat4x2_attr_offset + 2 * sizeof(double)));
3758 	gl.vertexAttribLPointer(m_po_bo2_dmat4x2_attr_location + 2, 2, /* size */
3759 							GL_DOUBLE, m_po_bo2_dmat4x2_attr_stride,
3760 							(const glw::GLvoid*)(m_po_bo2_dmat4x2_attr_offset + 4 * sizeof(double)));
3761 	gl.vertexAttribLPointer(m_po_bo2_dmat4x2_attr_location + 3, 2, /* size */
3762 							GL_DOUBLE, m_po_bo2_dmat4x2_attr_stride,
3763 							(const glw::GLvoid*)(m_po_bo2_dmat4x2_attr_offset + 6 * sizeof(double)));
3764 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribLPointer() call failed.");
3765 
3766 	gl.enableVertexAttribArray(m_po_bo2_dmat4x2_attr_location + 0);
3767 	gl.enableVertexAttribArray(m_po_bo2_dmat4x2_attr_location + 1);
3768 	gl.enableVertexAttribArray(m_po_bo2_dmat4x2_attr_location + 2);
3769 	gl.enableVertexAttribArray(m_po_bo2_dmat4x2_attr_location + 3);
3770 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call(s) failed.");
3771 
3772 	/* Set up element binding */
3773 	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id_indices);
3774 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
3775 }
3776 
3777 /** Executes the test
3778  *
3779  *  @return tcu::TestNode::STOP
3780  **/
iterate()3781 tcu::TestNode::IterateResult VAOTest::iterate()
3782 {
3783 	IterateStart();
3784 
3785 	bool result = true;
3786 
3787 	RequireExtension("GL_ARB_vertex_attrib_64bit");
3788 
3789 	/* Initialize GL objects required to run the test */
3790 	initBuffers();
3791 	initBufferObjects();
3792 	initProgramObject();
3793 	initVAO();
3794 
3795 	/* Activate the program object before we continue */
3796 	gl.useProgram(m_po_id);
3797 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3798 
3799 	/* Iterate through all draw call combinations */
3800 	for (int n_draw_call_type = 0; n_draw_call_type < DRAW_CALL_TYPE_COUNT; ++n_draw_call_type)
3801 	{
3802 		_draw_call_type draw_call = (_draw_call_type)n_draw_call_type;
3803 
3804 		for (int n_instanced_draw_call = 0; n_instanced_draw_call <= 1; /* false & true */
3805 			 ++n_instanced_draw_call)
3806 		{
3807 			bool instanced_draw_call = (n_instanced_draw_call == 1);
3808 
3809 			for (int n_vertex_attrib_divisor = 0; n_vertex_attrib_divisor <= 1; /* 0 & non-zero divisor */
3810 				 ++n_vertex_attrib_divisor)
3811 			{
3812 				bool zero_vertex_attrib_divisor = (n_vertex_attrib_divisor == 0);
3813 
3814 				/* Execute the test */
3815 				result &= executeTest(draw_call, instanced_draw_call, zero_vertex_attrib_divisor);
3816 			} /* for (two vertex attrib divisor configurations) */
3817 		}	 /* for (non-instanced & instanced draw calls) */
3818 	}		  /* for (array-based & indiced draw calls) */
3819 
3820 	/* Done */
3821 	return IterateStop(result);
3822 }
3823 
3824 /** Verifies data that has been XFBed out by the draw call.
3825  *
3826  *  @param data                       XFBed data. Must not be NULL.
3827  *  @param draw_call                  Type of the draw call that was issued.
3828  *  @param instanced                  True if the draw call was instanced, false otherwise.
3829  *  @param zero_vertex_attrib_divisor True if a zero divisor was used for all checked attributes,
3830  *                                    false if the divisors were set to a value of m_nonzero_vertex_attrib_divisor.
3831  */
verifyXFBData(const void * data,_draw_call_type draw_call,bool instanced,bool zero_vertex_attrib_divisor)3832 bool VAOTest::verifyXFBData(const void* data, _draw_call_type draw_call, bool instanced,
3833 							bool zero_vertex_attrib_divisor)
3834 {
3835 	const float			 epsilon	  = 1e-5f;
3836 	bool				 is_indiced   = (draw_call == DRAW_CALL_TYPE_ELEMENTS);
3837 	const unsigned int   n_instances  = (instanced) ? m_n_draw_call_instances : 1;
3838 	bool				 result		  = true;
3839 	const unsigned char* xfb_data_ptr = (const unsigned char*)data;
3840 
3841 	for (unsigned int n_instance = 0; n_instance < n_instances; ++n_instance)
3842 	{
3843 		/* Verify dmat3 data from BO1 has been exposed correctly */
3844 		for (unsigned int n_element = 0; n_element < m_n_batches; ++n_element)
3845 		{
3846 			unsigned int in_index  = n_element;
3847 			unsigned int xfb_index = is_indiced ? m_bo_index_data[n_element] : n_element;
3848 
3849 			if (!zero_vertex_attrib_divisor)
3850 			{
3851 				in_index = n_instance / m_nonzero_vertex_attrib_divisor;
3852 			}
3853 
3854 			const double* in_matrix_data_ptr =
3855 				(const double*)(m_bo_1_data + (in_index)*m_po_bo1_dmat3_attr_stride + m_po_bo1_dmat3_attr_offset);
3856 			const double* xfb_matrix_data_ptr =
3857 				(const double*)(xfb_data_ptr + (m_n_batches * n_instance + xfb_index) * m_xfb_total_size +
3858 								m_xfb_bo1_dmat3_offset);
3859 
3860 			if (memcmp(in_matrix_data_ptr, xfb_matrix_data_ptr, m_xfb_bo1_dmat3_size) != 0)
3861 			{
3862 				m_testCtx.getLog() << tcu::TestLog::Message << "BO1 dmat3 attribute values mismatch for batch ["
3863 								   << n_element << "]"
3864 												   ", expected:["
3865 								   << in_matrix_data_ptr[0] << ", " << in_matrix_data_ptr[1] << ", "
3866 								   << in_matrix_data_ptr[2] << ", " << in_matrix_data_ptr[3] << ", "
3867 								   << in_matrix_data_ptr[4] << ", " << in_matrix_data_ptr[5] << ", "
3868 								   << in_matrix_data_ptr[6] << ", " << in_matrix_data_ptr[7] << ", "
3869 								   << in_matrix_data_ptr[8] << ", "
3870 								   << "], XFBed out:[" << xfb_matrix_data_ptr[0] << ", " << xfb_matrix_data_ptr[1]
3871 								   << ", " << xfb_matrix_data_ptr[2] << ", " << xfb_matrix_data_ptr[3] << ", "
3872 								   << xfb_matrix_data_ptr[4] << ", " << xfb_matrix_data_ptr[5] << ", "
3873 								   << xfb_matrix_data_ptr[6] << ", " << xfb_matrix_data_ptr[7] << ", "
3874 								   << xfb_matrix_data_ptr[8] << ", "
3875 								   << "]" << tcu::TestLog::EndMessage;
3876 
3877 				result = false;
3878 				break;
3879 			}
3880 		}
3881 
3882 		/* Verify float data from BO2 has been exposed correctly */
3883 		for (unsigned int n_batch = 0; n_batch < m_n_batches; ++n_batch)
3884 		{
3885 			unsigned int	   in_index  = n_batch;
3886 			const unsigned int xfb_index = is_indiced ? m_bo_index_data[n_batch] : n_batch;
3887 
3888 			if (!zero_vertex_attrib_divisor)
3889 			{
3890 				in_index = n_instance / m_nonzero_vertex_attrib_divisor;
3891 			}
3892 
3893 			const unsigned char* in_ubyte_data_ptr =
3894 				(const unsigned char*)(m_bo_2_data + (in_index)*m_po_bo2_float_attr_stride +
3895 									   m_po_bo2_float_attr_offset);
3896 			const float* xfb_float_data_ptr =
3897 				(const float*)(xfb_data_ptr + (m_n_batches * n_instance + xfb_index) * m_xfb_total_size +
3898 							   m_xfb_bo2_float_offset);
3899 			float expected_value = ((float)*in_ubyte_data_ptr / 255.0f);
3900 
3901 			if (de::abs(expected_value - *xfb_float_data_ptr) > epsilon)
3902 			{
3903 				m_testCtx.getLog() << tcu::TestLog::Message << "BO2 float attribute value mismatch for batch ["
3904 								   << n_batch << "]"
3905 												 ", expected: ["
3906 								   << expected_value << "]"
3907 														", XFBed out:["
3908 								   << *xfb_float_data_ptr << "]" << tcu::TestLog::EndMessage;
3909 
3910 				result = false;
3911 				break;
3912 			}
3913 		}
3914 
3915 		/* Verify dvec2 data from BO1 has been exposed correctly */
3916 		for (unsigned int n_element = 0; n_element < m_n_batches; ++n_element)
3917 		{
3918 			unsigned int	   in_index  = n_element;
3919 			const unsigned int xfb_index = is_indiced ? m_bo_index_data[n_element] : n_element;
3920 
3921 			if (!zero_vertex_attrib_divisor)
3922 			{
3923 				in_index = n_instance / m_nonzero_vertex_attrib_divisor;
3924 			}
3925 
3926 			const double* in_dvec2_data_ptr =
3927 				(const double*)(m_bo_1_data + (in_index)*m_po_bo1_dvec2_attr_stride + m_po_bo1_dvec2_attr_offset);
3928 			const double* xfb_dvec2_data_ptr =
3929 				(const double*)(xfb_data_ptr + (m_n_batches * n_instance + xfb_index) * m_xfb_total_size +
3930 								m_xfb_bo1_dvec2_offset);
3931 
3932 			if (memcmp(in_dvec2_data_ptr, in_dvec2_data_ptr, m_xfb_bo1_dvec2_size) != 0)
3933 			{
3934 				m_testCtx.getLog() << tcu::TestLog::Message << "BO1 dvec2 attribute values mismatch for batch ["
3935 								   << n_element << "]"
3936 												   ", expected:["
3937 								   << in_dvec2_data_ptr[0] << ", " << in_dvec2_data_ptr[1] << ", "
3938 								   << "], XFBed out:[" << xfb_dvec2_data_ptr[0] << ", " << xfb_dvec2_data_ptr[1] << ", "
3939 								   << "]" << tcu::TestLog::EndMessage;
3940 
3941 				result = false;
3942 				break;
3943 			}
3944 		}
3945 
3946 		/* Verify double data from BO1 has been exposed correctly */
3947 		for (unsigned int n_element = 0; n_element < m_n_batches; ++n_element)
3948 		{
3949 			unsigned int	   in_index  = n_element;
3950 			const unsigned int xfb_index = is_indiced ? m_bo_index_data[n_element] : n_element;
3951 
3952 			if (!zero_vertex_attrib_divisor)
3953 			{
3954 				in_index = n_instance / m_nonzero_vertex_attrib_divisor;
3955 			}
3956 
3957 			const double* in_double_data_ptr =
3958 				(const double*)(m_bo_1_data + (in_index)*m_po_bo1_double_attr_stride + m_po_bo1_double_attr_offset);
3959 			const double* xfb_double_data_ptr =
3960 				(const double*)(xfb_data_ptr + (m_n_batches * n_instance + xfb_index) * m_xfb_total_size +
3961 								m_xfb_bo1_double_offset);
3962 
3963 			if (memcmp(in_double_data_ptr, xfb_double_data_ptr, m_xfb_bo1_double_size) != 0)
3964 			{
3965 				m_testCtx.getLog() << tcu::TestLog::Message << "BO1 double attribute value mismatch for batch ["
3966 								   << n_element << "]"
3967 												   ", expected: ["
3968 								   << *in_double_data_ptr << "]"
3969 															 ", XFBed out:["
3970 								   << *xfb_double_data_ptr << "]" << tcu::TestLog::EndMessage;
3971 
3972 				result = false;
3973 				break;
3974 			}
3975 		}
3976 
3977 		/* Verify dmat4x2 data from BO2 has been exposed correctly */
3978 		for (unsigned int n_element = 0; n_element < m_n_batches; ++n_element)
3979 		{
3980 			unsigned int	   in_index  = n_element;
3981 			const unsigned int xfb_index = is_indiced ? m_bo_index_data[n_element] : n_element;
3982 
3983 			if (!zero_vertex_attrib_divisor)
3984 			{
3985 				in_index = n_instance / m_nonzero_vertex_attrib_divisor;
3986 			}
3987 
3988 			const unsigned char* in_matrix_data_ptr =
3989 				m_bo_2_data + (in_index)*m_po_bo2_dmat4x2_attr_stride + m_po_bo2_dmat4x2_attr_offset;
3990 			const unsigned char* xfb_matrix_data_ptr =
3991 				xfb_data_ptr + (m_n_batches * n_instance + xfb_index) * m_xfb_total_size + m_xfb_bo2_dmat4x2_offset;
3992 
3993 			if (memcmp(in_matrix_data_ptr, xfb_matrix_data_ptr, m_xfb_bo2_dmat4x2_size) != 0)
3994 			{
3995 				m_testCtx.getLog() << tcu::TestLog::Message << "BO2 dmat4x2 attribute values mismatch for batch ["
3996 								   << n_element << "]"
3997 												   ", expected:["
3998 								   << in_matrix_data_ptr[0] << ", " << in_matrix_data_ptr[1] << ", "
3999 								   << in_matrix_data_ptr[2] << ", " << in_matrix_data_ptr[3] << ", "
4000 								   << in_matrix_data_ptr[4] << ", " << in_matrix_data_ptr[5] << ", "
4001 								   << in_matrix_data_ptr[6] << ", " << in_matrix_data_ptr[7] << ", "
4002 								   << "], XFBed out:[" << xfb_matrix_data_ptr[0] << ", " << xfb_matrix_data_ptr[1]
4003 								   << ", " << xfb_matrix_data_ptr[2] << ", " << xfb_matrix_data_ptr[3] << ", "
4004 								   << xfb_matrix_data_ptr[4] << ", " << xfb_matrix_data_ptr[5] << ", "
4005 								   << xfb_matrix_data_ptr[6] << ", " << xfb_matrix_data_ptr[7] << ", "
4006 								   << "]" << tcu::TestLog::EndMessage;
4007 
4008 				result = false;
4009 				break;
4010 			}
4011 		}
4012 
4013 		/* Verify int data from BO1 has been exposed correctly */
4014 		for (unsigned int n_element = 0; n_element < m_n_batches; ++n_element)
4015 		{
4016 			unsigned int	   in_index  = n_element;
4017 			const unsigned int xfb_index = is_indiced ? m_bo_index_data[n_element] : n_element;
4018 
4019 			if (!zero_vertex_attrib_divisor)
4020 			{
4021 				in_index = n_instance / m_nonzero_vertex_attrib_divisor;
4022 			}
4023 
4024 			const signed char* in_char_data_ptr =
4025 				(const signed char*)(m_bo_1_data + (in_index)*m_po_bo1_int_attr_stride + m_po_bo1_int_attr_offset);
4026 			const signed int* xfb_int_data_ptr =
4027 				(const signed int*)(xfb_data_ptr + (m_n_batches * n_instance + xfb_index) * m_xfb_total_size +
4028 									m_xfb_bo1_int_offset);
4029 
4030 			if (de::abs((signed int)*in_char_data_ptr - *xfb_int_data_ptr) > epsilon)
4031 			{
4032 				m_testCtx.getLog() << tcu::TestLog::Message << "BO1 int attribute value mismatch for batch ["
4033 								   << n_element << "]"
4034 												   ", expected: ["
4035 								   << (signed int)*in_char_data_ptr << "]"
4036 																	   ", XFBed out:["
4037 								   << *xfb_int_data_ptr << "]" << tcu::TestLog::EndMessage;
4038 
4039 				result = false;
4040 				break;
4041 			}
4042 		}
4043 
4044 		/* Verify float data from BO1 has been exposed correctly */
4045 		for (unsigned int n_element = 0; n_element < m_n_batches; ++n_element)
4046 		{
4047 			unsigned int	   in_index  = n_element;
4048 			const unsigned int xfb_index = is_indiced ? m_bo_index_data[n_element] : n_element;
4049 
4050 			if (!zero_vertex_attrib_divisor)
4051 			{
4052 				in_index = n_instance / m_nonzero_vertex_attrib_divisor;
4053 			}
4054 
4055 			const unsigned short* in_short_data_ptr =
4056 				(const unsigned short*)(m_bo_1_data + (in_index)*m_po_bo1_float2_attr_stride +
4057 										m_po_bo1_float2_attr_offset);
4058 			const float* xfb_float_data_ptr =
4059 				(const float*)(xfb_data_ptr + (m_n_batches * n_instance + xfb_index) * m_xfb_total_size +
4060 							   m_xfb_bo1_float2_offset);
4061 
4062 			if (de::abs(*in_short_data_ptr - *xfb_float_data_ptr) > epsilon)
4063 			{
4064 				m_testCtx.getLog() << tcu::TestLog::Message << "BO1 float attribute value mismatch for batch ["
4065 								   << n_element << "]"
4066 												   ", expected: ["
4067 								   << (signed int)*in_short_data_ptr << "]"
4068 																		", XFBed out:["
4069 								   << *xfb_float_data_ptr << "]" << tcu::TestLog::EndMessage;
4070 
4071 				result = false;
4072 				break;
4073 			}
4074 		}
4075 	} /* for (all instances) */
4076 
4077 	return result;
4078 }
4079 
4080 } /* namespace VertexAttrib64Bit */
4081 
4082 namespace gl4cts
4083 {
4084 
VertexAttrib64BitTests(deqp::Context & context)4085 VertexAttrib64BitTests::VertexAttrib64BitTests(deqp::Context& context)
4086 	: TestCaseGroup(context, "vertex_attrib_64bit", "Verifes GL_ARB_vertex_attrib_64bit functionality")
4087 {
4088 	/* Nothing to be done here */
4089 }
4090 
init(void)4091 void VertexAttrib64BitTests::init(void)
4092 {
4093 	addChild(new VertexAttrib64Bit::ApiErrorsTest(m_context));
4094 	addChild(new VertexAttrib64Bit::GetVertexAttribTest(m_context));
4095 	addChild(new VertexAttrib64Bit::LimitTest(m_context));
4096 	addChild(new VertexAttrib64Bit::VAOTest(m_context));
4097 }
4098 
4099 } /* namespace gl4cts */
4100