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