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, ¶ms_getVertexAttribiv);
1098 GLU_EXPECT_NO_ERROR(gl.getError(), "GetVertexAttribiv");
1099
1100 gl.getVertexAttribLdv(index, pname, ¶ms_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 ≷
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