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