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