Home | History | Annotate | Download | only in gl
      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 
     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  **/
     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 
     94 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  **/
    123 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 
    136 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  **/
    180 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 
    190 void Base::IterateStart()
    191 {
    192 	gl = m_context.getRenderContext().getFunctions();
    193 }
    194 
    195 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 
    211 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  **/
    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  **/
    263 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 
    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  **/
    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 
    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  **/
    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  **/
    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  **/
    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  **/
    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  **/
    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 
    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:
    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  **/
    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  **/
    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  **/
    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>
    755 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>
    784 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  **/
    810 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 <>
    885 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 <>
    899 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 <>
    913 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 <>
    927 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 <>
    941 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 <>
    955 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 <>
    969 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 <>
    983 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  **/
    997 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  **/
   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  **/
   1039 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  **/
   1090 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  **/
   1137 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 
   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 	{
   1315 		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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   1578 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  **/
   1599 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  **/
   1634 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  **/
   1655 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  **/
   1815 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  **/
   2023 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  **/
   2185 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  **/
   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  **/
   2313 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  **/
   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  **/
   2371 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  **/
   2412 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  **/
   2434 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  **/
   2461 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  **/
   2494 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  **/
   2535 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  **/
   2563 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  **/
   2590 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(false))
   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  **/
   2617 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  **/
   2644 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(false))
   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  **/
   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  **/
   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  **/
   2854 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  **/
   2894 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  **/
   2924 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  **/
   2952 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 
   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  **/
   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 */
   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  **/
   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  **/
   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. */
   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  **/
   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  **/
   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  **/
   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  */
   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 
   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 
   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