1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 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 Vertex array object tests 22 *//*--------------------------------------------------------------------*/ 23 #include "es3fVertexArrayObjectTests.hpp" 24 25 #include "gluShaderProgram.hpp" 26 #include "gluPixelTransfer.hpp" 27 #include "gluRenderContext.hpp" 28 29 #include "tcuTestLog.hpp" 30 #include "tcuImageCompare.hpp" 31 #include "tcuSurface.hpp" 32 #include "tcuRenderTarget.hpp" 33 34 #include "deRandom.hpp" 35 #include "deString.h" 36 #include "deMemory.h" 37 38 #include <vector> 39 #include <string> 40 #include <memory> 41 42 #include "glw.h" 43 44 using std::vector; 45 using std::string; 46 47 namespace deqp 48 { 49 namespace gles3 50 { 51 namespace Functional 52 { 53 54 namespace 55 { 56 struct Attribute 57 { 58 Attribute (void); 59 GLboolean enabled; 60 GLint size; 61 GLint stride; 62 GLenum type; 63 GLboolean integer; 64 GLint divisor; 65 GLint offset; 66 GLboolean normalized; 67 68 int bufferNdx; 69 }; 70 71 struct VertexArrayState 72 { 73 VertexArrayState (void); 74 75 vector<Attribute> attributes; 76 int elementArrayBuffer; 77 }; 78 79 VertexArrayState::VertexArrayState (void) 80 : elementArrayBuffer(-1) 81 { 82 } 83 84 Attribute::Attribute (void) 85 : enabled (GL_FALSE) 86 , size (1) 87 , stride (0) 88 , type (GL_FLOAT) 89 , integer (GL_FALSE) 90 , divisor (0) 91 , offset (0) 92 , normalized (GL_FALSE) 93 , bufferNdx (0) 94 { 95 } 96 97 struct BufferSpec 98 { 99 int count; 100 int size; 101 int componentCount; 102 int stride; 103 int offset; 104 105 GLenum type; 106 107 int intRangeMin; 108 int intRangeMax; 109 110 float floatRangeMin; 111 float floatRangeMax; 112 }; 113 114 struct Spec 115 { 116 Spec (void); 117 118 int count; 119 int instances; 120 bool useDrawElements; 121 GLenum indexType; 122 int indexOffset; 123 int indexRangeMin; 124 int indexRangeMax; 125 int indexCount; 126 VertexArrayState state; 127 VertexArrayState vao; 128 vector<BufferSpec> buffers; 129 }; 130 131 Spec::Spec (void) 132 : count (-1) 133 , instances (-1) 134 , useDrawElements (false) 135 , indexType (GL_NONE) 136 , indexOffset (-1) 137 , indexRangeMin (-1) 138 , indexRangeMax (-1) 139 , indexCount (-1) 140 { 141 } 142 143 } // anonymous 144 145 class VertexArrayObjectTest : public TestCase 146 { 147 public: 148 149 VertexArrayObjectTest (Context& context, const Spec& spec, const char* name, const char* description); 150 ~VertexArrayObjectTest (void); 151 virtual void init (void); 152 virtual void deinit (void); 153 virtual IterateResult iterate (void); 154 155 private: 156 Spec m_spec; 157 tcu::TestLog& m_log; 158 vector<GLuint> m_buffers; 159 glu::ShaderProgram* m_vaoProgram; 160 glu::ShaderProgram* m_stateProgram; 161 de::Random m_random; 162 deUint8* m_indices; 163 164 void logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg); 165 deUint8* createRandomBufferData (const BufferSpec& buffer); 166 deUint8* generateIndices (void); 167 glu::ShaderProgram* createProgram (const VertexArrayState& state); 168 void setState (const VertexArrayState& state); 169 void render (tcu::Surface& vaoResult, tcu::Surface& defaultResult); 170 void makeDrawCall (const VertexArrayState& state); 171 void genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef); 172 173 VertexArrayObjectTest (const VertexArrayObjectTest&); 174 VertexArrayObjectTest& operator= (const VertexArrayObjectTest&); 175 }; 176 177 VertexArrayObjectTest::VertexArrayObjectTest (Context& context, const Spec& spec, const char* name, const char* description) 178 : TestCase (context, name, description) 179 , m_spec (spec) 180 , m_log (context.getTestContext().getLog()) 181 , m_vaoProgram (NULL) 182 , m_stateProgram (NULL) 183 , m_random (deStringHash(name)) 184 , m_indices (NULL) 185 { 186 // Makes zero to zero mapping for buffers 187 m_buffers.push_back(0); 188 } 189 190 VertexArrayObjectTest::~VertexArrayObjectTest (void) 191 { 192 } 193 194 void VertexArrayObjectTest::logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg) 195 { 196 std::stringstream message; 197 198 message << msg << "\n"; 199 message << "GL_ELEMENT_ARRAY_BUFFER : " << state.elementArrayBuffer << "\n"; 200 201 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++) 202 { 203 message 204 << "attribute : " << attribNdx << "\n" 205 << "\tGL_VERTEX_ATTRIB_ARRAY_ENABLED : " << (state.attributes[attribNdx].enabled ? "GL_TRUE" : "GL_FALSE") << "\n" 206 << "\tGL_VERTEX_ATTRIB_ARRAY_SIZE : " << state.attributes[attribNdx].size << "\n" 207 << "\tGL_VERTEX_ATTRIB_ARRAY_STRIDE : " << state.attributes[attribNdx].stride << "\n" 208 << "\tGL_VERTEX_ATTRIB_ARRAY_TYPE : " << state.attributes[attribNdx].type << "\n" 209 << "\tGL_VERTEX_ATTRIB_ARRAY_NORMALIZED : " << (state.attributes[attribNdx].normalized ? "GL_TRUE" : "GL_FALSE") << "\n" 210 << "\tGL_VERTEX_ATTRIB_ARRAY_INTEGER : " << (state.attributes[attribNdx].integer ? "GL_TRUE" : "GL_FALSE") << "\n" 211 << "\tGL_VERTEX_ATTRIB_ARRAY_DIVISOR : " << state.attributes[attribNdx].divisor << "\n" 212 << "\tGL_VERTEX_ATTRIB_ARRAY_POINTER : " << state.attributes[attribNdx].offset << "\n" 213 << "\tGL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : " << m_buffers[state.attributes[attribNdx].bufferNdx] << "\n"; 214 } 215 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; 216 } 217 218 219 void VertexArrayObjectTest::init (void) 220 { 221 // \note [mika] Index 0 is reserved for 0 buffer 222 for (int bufferNdx = 0; bufferNdx < (int)m_spec.buffers.size(); bufferNdx++) 223 { 224 deUint8* data = createRandomBufferData(m_spec.buffers[bufferNdx]); 225 226 try 227 { 228 GLuint buffer; 229 GLU_CHECK_CALL(glGenBuffers(1, &buffer)); 230 m_buffers.push_back(buffer); 231 232 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, buffer)); 233 GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, m_spec.buffers[bufferNdx].size, data, GL_DYNAMIC_DRAW)); 234 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0)); 235 236 } catch (...) { 237 delete[] data; 238 throw; 239 } 240 241 delete[] data; 242 } 243 244 m_vaoProgram = createProgram(m_spec.vao); 245 m_log << tcu::TestLog::Message << "Program used with Vertex Array Object" << tcu::TestLog::EndMessage; 246 m_log << *m_vaoProgram; 247 m_stateProgram = createProgram(m_spec.state); 248 m_log << tcu::TestLog::Message << "Program used with Vertex Array State" << tcu::TestLog::EndMessage; 249 m_log << *m_stateProgram; 250 251 if (!m_vaoProgram->isOk() || !m_stateProgram->isOk()) 252 TCU_FAIL("Failed to compile shaders"); 253 254 if (m_spec.useDrawElements && (m_spec.vao.elementArrayBuffer == 0 || m_spec.state.elementArrayBuffer == 0)) 255 m_indices = generateIndices(); 256 } 257 258 void VertexArrayObjectTest::deinit (void) 259 { 260 GLU_CHECK_CALL(glDeleteBuffers((GLsizei)m_buffers.size(), &(m_buffers[0]))); 261 m_buffers.clear(); 262 delete m_vaoProgram; 263 delete m_stateProgram; 264 delete[] m_indices; 265 } 266 267 deUint8* VertexArrayObjectTest::generateIndices (void) 268 { 269 int typeSize = 0; 270 switch (m_spec.indexType) 271 { 272 case GL_UNSIGNED_INT: typeSize = sizeof(GLuint); break; 273 case GL_UNSIGNED_SHORT: typeSize = sizeof(GLushort); break; 274 case GL_UNSIGNED_BYTE: typeSize = sizeof(GLubyte); break; 275 default: 276 DE_ASSERT(false); 277 } 278 279 deUint8* indices = new deUint8[m_spec.indexCount * typeSize]; 280 281 for (int i = 0; i < m_spec.indexCount; i++) 282 { 283 deUint8* pos = indices + typeSize * i; 284 285 switch (m_spec.indexType) 286 { 287 case GL_UNSIGNED_INT: 288 { 289 GLuint v = (GLuint)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax); 290 deMemcpy(pos, &v, sizeof(v)); 291 break; 292 } 293 294 case GL_UNSIGNED_SHORT: 295 { 296 GLushort v = (GLushort)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax); 297 deMemcpy(pos, &v, sizeof(v)); 298 break; 299 } 300 301 case GL_UNSIGNED_BYTE: 302 { 303 GLubyte v = (GLubyte)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax); 304 deMemcpy(pos, &v, sizeof(v)); 305 break; 306 } 307 308 default: 309 DE_ASSERT(false); 310 } 311 } 312 313 return indices; 314 } 315 316 deUint8* VertexArrayObjectTest::createRandomBufferData (const BufferSpec& buffer) 317 { 318 deUint8* data = new deUint8[buffer.size]; 319 320 int stride; 321 322 if (buffer.stride != 0) 323 { 324 stride = buffer.stride; 325 } 326 else 327 { 328 switch (buffer.type) 329 { 330 case GL_FLOAT: stride = buffer.componentCount * sizeof(GLfloat); break; 331 case GL_INT: stride = buffer.componentCount * sizeof(GLint); break; 332 case GL_UNSIGNED_INT: stride = buffer.componentCount * sizeof(GLuint); break; 333 case GL_SHORT: stride = buffer.componentCount * sizeof(GLshort); break; 334 case GL_UNSIGNED_SHORT: stride = buffer.componentCount * sizeof(GLushort); break; 335 case GL_BYTE: stride = buffer.componentCount * sizeof(GLbyte); break; 336 case GL_UNSIGNED_BYTE: stride = buffer.componentCount * sizeof(GLubyte); break; 337 338 default: 339 stride = 0; 340 DE_ASSERT(DE_FALSE); 341 } 342 } 343 344 deUint8* itr = data; 345 346 for (int pos = 0; pos < buffer.count; pos++) 347 { 348 deUint8* componentItr = itr; 349 for (int componentNdx = 0; componentNdx < buffer.componentCount; componentNdx++) 350 { 351 switch (buffer.type) 352 { 353 case GL_FLOAT: 354 { 355 float v = buffer.floatRangeMin + (buffer.floatRangeMax - buffer.floatRangeMin) * m_random.getFloat(); 356 deMemcpy(componentItr, &v, sizeof(v)); 357 componentItr += sizeof(v); 358 break; 359 } 360 361 case GL_INT: 362 { 363 GLint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax); 364 deMemcpy(componentItr, &v, sizeof(v)); 365 componentItr += sizeof(v); 366 break; 367 } 368 369 case GL_UNSIGNED_INT: 370 { 371 GLuint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax); 372 deMemcpy(componentItr, &v, sizeof(v)); 373 componentItr += sizeof(v); 374 break; 375 } 376 377 case GL_SHORT: 378 { 379 GLshort v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax); 380 deMemcpy(componentItr, &v, sizeof(v)); 381 componentItr += sizeof(v); 382 break; 383 } 384 385 case GL_UNSIGNED_SHORT: 386 { 387 GLushort v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax); 388 deMemcpy(componentItr, &v, sizeof(v)); 389 componentItr += sizeof(v); 390 break; 391 } 392 393 case GL_BYTE: 394 { 395 GLbyte v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax); 396 deMemcpy(componentItr, &v, sizeof(v)); 397 componentItr += sizeof(v); 398 break; 399 } 400 401 case GL_UNSIGNED_BYTE: 402 { 403 GLubyte v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax); 404 deMemcpy(componentItr, &v, sizeof(v)); 405 componentItr += sizeof(v); 406 break; 407 } 408 409 default: 410 DE_ASSERT(false); 411 }; 412 } 413 414 itr += stride; 415 } 416 417 return data; 418 } 419 420 glu::ShaderProgram* VertexArrayObjectTest::createProgram (const VertexArrayState& state) 421 { 422 std::stringstream vertexShaderStream; 423 std::stringstream value; 424 425 vertexShaderStream << "#version 300 es\n"; 426 427 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++) 428 { 429 if (state.attributes[attribNdx].integer) 430 vertexShaderStream << "layout(location = " << attribNdx << ") in mediump ivec4 a_attrib" << attribNdx << ";\n"; 431 else 432 vertexShaderStream << "layout(location = " << attribNdx << ") in mediump vec4 a_attrib" << attribNdx << ";\n"; 433 434 if (state.attributes[attribNdx].integer) 435 { 436 float scale = 0.0f; 437 438 switch (state.attributes[0].type) 439 { 440 case GL_SHORT: scale = (1.0f/((1u<<14)-1)); break; 441 case GL_UNSIGNED_SHORT: scale = (1.0f/((1u<<15)-1)); break; 442 case GL_INT: scale = (1.0f/((1u<<30)-1)); break; 443 case GL_UNSIGNED_INT: scale = (1.0f/((1u<<31)-1)); break; 444 case GL_BYTE: scale = (1.0f/((1u<<6)-1)); break; 445 case GL_UNSIGNED_BYTE: scale = (1.0f/((1u<<7)-1)); break; 446 447 default: 448 DE_ASSERT(DE_FALSE); 449 } 450 value << (attribNdx != 0 ? " + " : "" ) << scale << " * vec4(a_attrib" << attribNdx << ")"; 451 } 452 else if (state.attributes[attribNdx].type != GL_FLOAT && !state.attributes[attribNdx].normalized) 453 { 454 float scale = 0.0f; 455 456 switch (state.attributes[0].type) 457 { 458 case GL_SHORT: scale = (0.5f/((1u<<14)-1)); break; 459 case GL_UNSIGNED_SHORT: scale = (0.5f/((1u<<15)-1)); break; 460 case GL_INT: scale = (0.5f/((1u<<30)-1)); break; 461 case GL_UNSIGNED_INT: scale = (0.5f/((1u<<31)-1)); break; 462 case GL_BYTE: scale = (0.5f/((1u<<6)-1)); break; 463 case GL_UNSIGNED_BYTE: scale = (0.5f/((1u<<7)-1)); break; 464 465 default: 466 DE_ASSERT(DE_FALSE); 467 } 468 value << (attribNdx != 0 ? " + " : "" ) << scale << " * a_attrib" << attribNdx; 469 } 470 else 471 value << (attribNdx != 0 ? " + " : "" ) << "a_attrib" << attribNdx; 472 } 473 474 vertexShaderStream 475 << "out mediump vec4 v_value;\n" 476 << "void main (void)\n" 477 << "{\n" 478 << "\tv_value = " << value.str() << ";\n"; 479 480 if (state.attributes[0].integer) 481 { 482 float scale = 0.0f; 483 484 switch (state.attributes[0].type) 485 { 486 case GL_SHORT: scale = (1.0f/((1u<<14)-1)); break; 487 case GL_UNSIGNED_SHORT: scale = (1.0f/((1u<<15)-1)); break; 488 case GL_INT: scale = (1.0f/((1u<<30)-1)); break; 489 case GL_UNSIGNED_INT: scale = (1.0f/((1u<<31)-1)); break; 490 case GL_BYTE: scale = (1.0f/((1u<<6)-1)); break; 491 case GL_UNSIGNED_BYTE: scale = (1.0f/((1u<<7)-1)); break; 492 493 default: 494 DE_ASSERT(DE_FALSE); 495 } 496 497 vertexShaderStream 498 << "\tgl_Position = vec4(" << scale << " * " << "vec3(a_attrib0.xyz), 1.0);\n" 499 << "}"; 500 } 501 else 502 { 503 if (state.attributes[0].normalized || state.attributes[0].type == GL_FLOAT) 504 { 505 vertexShaderStream 506 << "\tgl_Position = vec4(a_attrib0.xyz, 1.0);\n" 507 << "}"; 508 } 509 else 510 { 511 float scale = 0.0f; 512 513 switch (state.attributes[0].type) 514 { 515 case GL_SHORT: scale = (1.0f/((1u<<14)-1)); break; 516 case GL_UNSIGNED_SHORT: scale = (1.0f/((1u<<15)-1)); break; 517 case GL_INT: scale = (1.0f/((1u<<30)-1)); break; 518 case GL_UNSIGNED_INT: scale = (1.0f/((1u<<31)-1)); break; 519 case GL_BYTE: scale = (1.0f/((1u<<6)-1)); break; 520 case GL_UNSIGNED_BYTE: scale = (1.0f/((1u<<7)-1)); break; 521 522 default: 523 DE_ASSERT(DE_FALSE); 524 } 525 526 scale *= 0.5; 527 528 vertexShaderStream 529 << "\tgl_Position = vec4(" << scale << " * " << "a_attrib0.xyz, 1.0);\n" 530 << "}"; 531 } 532 } 533 534 const char* fragmentShader = 535 "#version 300 es\n" 536 "in mediump vec4 v_value;\n" 537 "layout(location = 0) out mediump vec4 fragColor;\n" 538 "void main (void)\n" 539 "{\n" 540 "\tfragColor = vec4(v_value.xyz, 1.0);\n" 541 "}"; 542 543 return new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderStream.str(), fragmentShader)); 544 } 545 546 void VertexArrayObjectTest::setState (const VertexArrayState& state) 547 { 548 GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[state.elementArrayBuffer])); 549 550 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++) 551 { 552 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_buffers[state.attributes[attribNdx].bufferNdx])); 553 if (state.attributes[attribNdx].enabled) 554 GLU_CHECK_CALL(glEnableVertexAttribArray(attribNdx)); 555 else 556 GLU_CHECK_CALL(glDisableVertexAttribArray(attribNdx)); 557 558 if (state.attributes[attribNdx].integer) 559 GLU_CHECK_CALL(glVertexAttribIPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset))); 560 else 561 GLU_CHECK_CALL(glVertexAttribPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].normalized, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset))); 562 563 GLU_CHECK_CALL(glVertexAttribDivisor(attribNdx, state.attributes[attribNdx].divisor)); 564 } 565 } 566 567 void VertexArrayObjectTest::makeDrawCall (const VertexArrayState& state) 568 { 569 GLU_CHECK_CALL(glClearColor(0.7f, 0.7f, 0.7f, 1.0f)); 570 GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT)); 571 572 if (m_spec.useDrawElements) 573 { 574 if (state.elementArrayBuffer == 0) 575 { 576 if (m_spec.instances == 0) 577 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices)); 578 else 579 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices, m_spec.instances)); 580 } 581 else 582 { 583 if (m_spec.instances == 0) 584 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset))); 585 else 586 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset), m_spec.instances)); 587 } 588 } 589 else 590 { 591 if (m_spec.instances == 0) 592 GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, m_spec.count)); 593 else 594 GLU_CHECK_CALL(glDrawArraysInstanced(GL_TRIANGLES, 0, m_spec.count, m_spec.instances)); 595 } 596 } 597 598 void VertexArrayObjectTest::render (tcu::Surface& vaoResult, tcu::Surface& defaultResult) 599 { 600 GLuint vao = 0; 601 602 GLU_CHECK_CALL(glGenVertexArrays(1, &vao)); 603 GLU_CHECK_CALL(glBindVertexArray(vao)); 604 setState(m_spec.vao); 605 GLU_CHECK_CALL(glBindVertexArray(0)); 606 607 setState(m_spec.state); 608 609 GLU_CHECK_CALL(glBindVertexArray(vao)); 610 GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram())); 611 makeDrawCall(m_spec.vao); 612 glu::readPixels(m_context.getRenderContext(), 0, 0, vaoResult.getAccess()); 613 setState(m_spec.vao); 614 GLU_CHECK_CALL(glBindVertexArray(0)); 615 616 GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram())); 617 makeDrawCall(m_spec.state); 618 glu::readPixels(m_context.getRenderContext(), 0, 0, defaultResult.getAccess()); 619 } 620 621 void VertexArrayObjectTest::genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef) 622 { 623 setState(m_spec.vao); 624 GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram())); 625 makeDrawCall(m_spec.vao); 626 glu::readPixels(m_context.getRenderContext(), 0, 0, vaoRef.getAccess()); 627 628 setState(m_spec.state); 629 GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram())); 630 makeDrawCall(m_spec.state); 631 glu::readPixels(m_context.getRenderContext(), 0, 0, defaultRef.getAccess()); 632 } 633 634 TestCase::IterateResult VertexArrayObjectTest::iterate (void) 635 { 636 tcu::Surface vaoReference (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight()); 637 tcu::Surface stateReference (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight()); 638 639 tcu::Surface vaoResult (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight()); 640 tcu::Surface stateResult (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight()); 641 642 bool isOk; 643 644 logVertexArrayState(m_log, m_spec.vao, "Vertex Array Object State"); 645 logVertexArrayState(m_log, m_spec.state, "OpenGL Vertex Array State"); 646 genReferences(stateReference, vaoReference); 647 render(stateResult, vaoResult); 648 649 isOk = tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array State", stateReference, stateResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT); 650 isOk = isOk && tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array Object", vaoReference, vaoResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT); 651 652 if (isOk) 653 { 654 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 655 return STOP; 656 } 657 else 658 { 659 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 660 return STOP; 661 } 662 } 663 664 class MultiVertexArrayObjectTest : public TestCase 665 { 666 public: 667 668 MultiVertexArrayObjectTest (Context& context, const char* name, const char* description); 669 ~MultiVertexArrayObjectTest (void); 670 virtual void init (void); 671 virtual void deinit (void); 672 virtual IterateResult iterate (void); 673 674 private: 675 Spec m_spec; 676 tcu::TestLog& m_log; 677 vector<GLuint> m_buffers; 678 glu::ShaderProgram* m_vaoProgram; 679 glu::ShaderProgram* m_stateProgram; 680 de::Random m_random; 681 deUint8* m_indices; 682 683 void logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg); 684 deUint8* createRandomBufferData (const BufferSpec& buffer); 685 deUint8* generateIndices (void); 686 glu::ShaderProgram* createProgram (const VertexArrayState& state); 687 void setState (const VertexArrayState& state); 688 void render (tcu::Surface& vaoResult, tcu::Surface& defaultResult); 689 void makeDrawCall (const VertexArrayState& state); 690 void genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef); 691 692 MultiVertexArrayObjectTest (const MultiVertexArrayObjectTest&); 693 MultiVertexArrayObjectTest& operator= (const MultiVertexArrayObjectTest&); 694 }; 695 696 MultiVertexArrayObjectTest::MultiVertexArrayObjectTest (Context& context, const char* name, const char* description) 697 : TestCase (context, name, description) 698 , m_log (context.getTestContext().getLog()) 699 , m_vaoProgram (NULL) 700 , m_stateProgram (NULL) 701 , m_random (deStringHash(name)) 702 , m_indices (NULL) 703 { 704 // Makes zero to zero mapping for buffers 705 m_buffers.push_back(0); 706 } 707 708 MultiVertexArrayObjectTest::~MultiVertexArrayObjectTest (void) 709 { 710 } 711 712 void MultiVertexArrayObjectTest::logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg) 713 { 714 std::stringstream message; 715 716 message << msg << "\n"; 717 message << "GL_ELEMENT_ARRAY_BUFFER : " << state.elementArrayBuffer << "\n"; 718 719 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++) 720 { 721 message 722 << "attribute : " << attribNdx << "\n" 723 << "\tGL_VERTEX_ATTRIB_ARRAY_ENABLED : " << (state.attributes[attribNdx].enabled ? "GL_TRUE" : "GL_FALSE") << "\n" 724 << "\tGL_VERTEX_ATTRIB_ARRAY_SIZE : " << state.attributes[attribNdx].size << "\n" 725 << "\tGL_VERTEX_ATTRIB_ARRAY_STRIDE : " << state.attributes[attribNdx].stride << "\n" 726 << "\tGL_VERTEX_ATTRIB_ARRAY_TYPE : " << state.attributes[attribNdx].type << "\n" 727 << "\tGL_VERTEX_ATTRIB_ARRAY_NORMALIZED : " << (state.attributes[attribNdx].normalized ? "GL_TRUE" : "GL_FALSE") << "\n" 728 << "\tGL_VERTEX_ATTRIB_ARRAY_INTEGER : " << (state.attributes[attribNdx].integer ? "GL_TRUE" : "GL_FALSE") << "\n" 729 << "\tGL_VERTEX_ATTRIB_ARRAY_DIVISOR : " << state.attributes[attribNdx].divisor << "\n" 730 << "\tGL_VERTEX_ATTRIB_ARRAY_POINTER : " << state.attributes[attribNdx].offset << "\n" 731 << "\t GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : " << m_buffers[state.attributes[attribNdx].bufferNdx] << "\n"; 732 } 733 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; 734 } 735 736 737 void MultiVertexArrayObjectTest::init (void) 738 { 739 GLint attribCount; 740 741 GLU_CHECK_CALL(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribCount)); 742 743 m_spec.useDrawElements = false; 744 m_spec.instances = 0; 745 m_spec.count = 24; 746 m_spec.indexOffset = 0; 747 m_spec.indexRangeMin = 0; 748 m_spec.indexRangeMax = 0; 749 m_spec.indexType = GL_NONE; 750 m_spec.indexCount = 0; 751 m_spec.vao.elementArrayBuffer = 0; 752 m_spec.state.elementArrayBuffer = 0; 753 754 for (int attribNdx = 0; attribNdx < attribCount; attribNdx++) 755 { 756 BufferSpec shortCoordBuffer48 = { 48, 2*384, 4, 0, 0, GL_SHORT, -32768, 32768, 0.0f, 0.0f }; 757 m_spec.buffers.push_back(shortCoordBuffer48); 758 759 m_spec.state.attributes.push_back(Attribute()); 760 m_spec.state.attributes[attribNdx].enabled = (m_random.getInt(0, 4) == 0) ? GL_FALSE : GL_TRUE; 761 m_spec.state.attributes[attribNdx].size = m_random.getInt(2,4); 762 m_spec.state.attributes[attribNdx].stride = 2*m_random.getInt(1, 3); 763 m_spec.state.attributes[attribNdx].type = GL_SHORT; 764 m_spec.state.attributes[attribNdx].integer = m_random.getBool(); 765 m_spec.state.attributes[attribNdx].divisor = m_random.getInt(0, 1); 766 m_spec.state.attributes[attribNdx].offset = 2*m_random.getInt(0, 2); 767 m_spec.state.attributes[attribNdx].normalized = m_random.getBool(); 768 m_spec.state.attributes[attribNdx].bufferNdx = attribNdx+1; 769 770 if (attribNdx == 0) 771 { 772 m_spec.state.attributes[attribNdx].divisor = 0; 773 m_spec.state.attributes[attribNdx].enabled = GL_TRUE; 774 m_spec.state.attributes[attribNdx].size = 2; 775 } 776 777 m_spec.vao.attributes.push_back(Attribute()); 778 m_spec.vao.attributes[attribNdx].enabled = (m_random.getInt(0, 4) == 0) ? GL_FALSE : GL_TRUE; 779 m_spec.vao.attributes[attribNdx].size = m_random.getInt(2,4); 780 m_spec.vao.attributes[attribNdx].stride = 2*m_random.getInt(1, 3); 781 m_spec.vao.attributes[attribNdx].type = GL_SHORT; 782 m_spec.vao.attributes[attribNdx].integer = m_random.getBool(); 783 m_spec.vao.attributes[attribNdx].divisor = m_random.getInt(0, 1); 784 m_spec.vao.attributes[attribNdx].offset = 2*m_random.getInt(0, 2); 785 m_spec.vao.attributes[attribNdx].normalized = m_random.getBool(); 786 m_spec.vao.attributes[attribNdx].bufferNdx = attribCount - attribNdx; 787 788 if (attribNdx == 0) 789 { 790 m_spec.vao.attributes[attribNdx].divisor = 0; 791 m_spec.vao.attributes[attribNdx].enabled = GL_TRUE; 792 m_spec.vao.attributes[attribNdx].size = 2; 793 } 794 795 } 796 797 // \note [mika] Index 0 is reserved for 0 buffer 798 for (int bufferNdx = 0; bufferNdx < (int)m_spec.buffers.size(); bufferNdx++) 799 { 800 deUint8* data = createRandomBufferData(m_spec.buffers[bufferNdx]); 801 802 try 803 { 804 GLuint buffer; 805 GLU_CHECK_CALL(glGenBuffers(1, &buffer)); 806 m_buffers.push_back(buffer); 807 808 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, buffer)); 809 GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, m_spec.buffers[bufferNdx].size, data, GL_DYNAMIC_DRAW)); 810 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0)); 811 812 } catch (...) { 813 delete[] data; 814 throw; 815 } 816 817 delete[] data; 818 } 819 820 m_vaoProgram = createProgram(m_spec.vao); 821 m_log << tcu::TestLog::Message << "Program used with Vertex Array Object" << tcu::TestLog::EndMessage; 822 m_log << *m_vaoProgram; 823 m_stateProgram = createProgram(m_spec.state); 824 m_log << tcu::TestLog::Message << "Program used with Vertex Array State" << tcu::TestLog::EndMessage; 825 m_log << *m_stateProgram; 826 827 if (!m_vaoProgram->isOk() || !m_stateProgram->isOk()) 828 TCU_FAIL("Failed to compile shaders"); 829 830 if (m_spec.useDrawElements && (m_spec.vao.elementArrayBuffer == 0 || m_spec.state.elementArrayBuffer == 0)) 831 m_indices = generateIndices(); 832 } 833 834 void MultiVertexArrayObjectTest::deinit (void) 835 { 836 GLU_CHECK_CALL(glDeleteBuffers((GLsizei)m_buffers.size(), &(m_buffers[0]))); 837 m_buffers.clear(); 838 delete m_vaoProgram; 839 delete m_stateProgram; 840 delete[] m_indices; 841 } 842 843 deUint8* MultiVertexArrayObjectTest::generateIndices (void) 844 { 845 int typeSize = 0; 846 switch (m_spec.indexType) 847 { 848 case GL_UNSIGNED_INT: typeSize = sizeof(GLuint); break; 849 case GL_UNSIGNED_SHORT: typeSize = sizeof(GLushort); break; 850 case GL_UNSIGNED_BYTE: typeSize = sizeof(GLubyte); break; 851 default: 852 DE_ASSERT(false); 853 } 854 855 deUint8* indices = new deUint8[m_spec.indexCount * typeSize]; 856 857 for (int i = 0; i < m_spec.indexCount; i++) 858 { 859 deUint8* pos = indices + typeSize * i; 860 861 switch (m_spec.indexType) 862 { 863 case GL_UNSIGNED_INT: 864 { 865 GLuint v = (GLuint)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax); 866 deMemcpy(pos, &v, sizeof(v)); 867 break; 868 } 869 870 case GL_UNSIGNED_SHORT: 871 { 872 GLushort v = (GLushort)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax); 873 deMemcpy(pos, &v, sizeof(v)); 874 break; 875 } 876 877 case GL_UNSIGNED_BYTE: 878 { 879 GLubyte v = (GLubyte)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax); 880 deMemcpy(pos, &v, sizeof(v)); 881 break; 882 } 883 884 default: 885 DE_ASSERT(false); 886 } 887 } 888 889 return indices; 890 } 891 892 deUint8* MultiVertexArrayObjectTest::createRandomBufferData (const BufferSpec& buffer) 893 { 894 deUint8* data = new deUint8[buffer.size]; 895 896 int stride; 897 898 if (buffer.stride != 0) 899 { 900 stride = buffer.stride; 901 } 902 else 903 { 904 switch (buffer.type) 905 { 906 case GL_FLOAT: stride = buffer.componentCount * sizeof(GLfloat); break; 907 case GL_INT: stride = buffer.componentCount * sizeof(GLint); break; 908 case GL_UNSIGNED_INT: stride = buffer.componentCount * sizeof(GLuint); break; 909 case GL_SHORT: stride = buffer.componentCount * sizeof(GLshort); break; 910 case GL_UNSIGNED_SHORT: stride = buffer.componentCount * sizeof(GLushort); break; 911 case GL_BYTE: stride = buffer.componentCount * sizeof(GLbyte); break; 912 case GL_UNSIGNED_BYTE: stride = buffer.componentCount * sizeof(GLubyte); break; 913 914 default: 915 stride = 0; 916 DE_ASSERT(DE_FALSE); 917 } 918 } 919 920 deUint8* itr = data; 921 922 for (int pos = 0; pos < buffer.count; pos++) 923 { 924 deUint8* componentItr = itr; 925 for (int componentNdx = 0; componentNdx < buffer.componentCount; componentNdx++) 926 { 927 switch (buffer.type) 928 { 929 case GL_FLOAT: 930 { 931 float v = buffer.floatRangeMin + (buffer.floatRangeMax - buffer.floatRangeMin) * m_random.getFloat(); 932 deMemcpy(componentItr, &v, sizeof(v)); 933 componentItr += sizeof(v); 934 break; 935 } 936 937 case GL_INT: 938 { 939 GLint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax); 940 deMemcpy(componentItr, &v, sizeof(v)); 941 componentItr += sizeof(v); 942 break; 943 } 944 945 case GL_UNSIGNED_INT: 946 { 947 GLuint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax); 948 deMemcpy(componentItr, &v, sizeof(v)); 949 componentItr += sizeof(v); 950 break; 951 } 952 953 case GL_SHORT: 954 { 955 GLshort v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax); 956 deMemcpy(componentItr, &v, sizeof(v)); 957 componentItr += sizeof(v); 958 break; 959 } 960 961 case GL_UNSIGNED_SHORT: 962 { 963 GLushort v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax); 964 deMemcpy(componentItr, &v, sizeof(v)); 965 componentItr += sizeof(v); 966 break; 967 } 968 969 case GL_BYTE: 970 { 971 GLbyte v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax); 972 deMemcpy(componentItr, &v, sizeof(v)); 973 componentItr += sizeof(v); 974 break; 975 } 976 977 case GL_UNSIGNED_BYTE: 978 { 979 GLubyte v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax); 980 deMemcpy(componentItr, &v, sizeof(v)); 981 componentItr += sizeof(v); 982 break; 983 } 984 985 default: 986 DE_ASSERT(false); 987 }; 988 } 989 990 itr += stride; 991 } 992 993 return data; 994 } 995 996 glu::ShaderProgram* MultiVertexArrayObjectTest::createProgram (const VertexArrayState& state) 997 { 998 std::stringstream vertexShaderStream; 999 std::stringstream value; 1000 1001 vertexShaderStream << "#version 300 es\n"; 1002 1003 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++) 1004 { 1005 if (state.attributes[attribNdx].integer) 1006 vertexShaderStream << "layout(location = " << attribNdx << ") in mediump ivec4 a_attrib" << attribNdx << ";\n"; 1007 else 1008 vertexShaderStream << "layout(location = " << attribNdx << ") in mediump vec4 a_attrib" << attribNdx << ";\n"; 1009 1010 if (state.attributes[attribNdx].integer) 1011 { 1012 float scale = 0.0f; 1013 1014 switch (state.attributes[0].type) 1015 { 1016 case GL_SHORT: scale = (1.0f/((1u<<14)-1)); break; 1017 case GL_UNSIGNED_SHORT: scale = (1.0f/((1u<<15)-1)); break; 1018 case GL_INT: scale = (1.0f/((1u<<30)-1)); break; 1019 case GL_UNSIGNED_INT: scale = (1.0f/((1u<<31)-1)); break; 1020 case GL_BYTE: scale = (1.0f/((1u<<6)-1)); break; 1021 case GL_UNSIGNED_BYTE: scale = (1.0f/((1u<<7)-1)); break; 1022 1023 default: 1024 DE_ASSERT(DE_FALSE); 1025 } 1026 value << (attribNdx != 0 ? " + " : "" ) << scale << " * vec4(a_attrib" << attribNdx << ")"; 1027 } 1028 else if (state.attributes[attribNdx].type != GL_FLOAT && !state.attributes[attribNdx].normalized) 1029 { 1030 float scale = 0.0f; 1031 1032 switch (state.attributes[0].type) 1033 { 1034 case GL_SHORT: scale = (0.5f/((1u<<14)-1)); break; 1035 case GL_UNSIGNED_SHORT: scale = (0.5f/((1u<<15)-1)); break; 1036 case GL_INT: scale = (0.5f/((1u<<30)-1)); break; 1037 case GL_UNSIGNED_INT: scale = (0.5f/((1u<<31)-1)); break; 1038 case GL_BYTE: scale = (0.5f/((1u<<6)-1)); break; 1039 case GL_UNSIGNED_BYTE: scale = (0.5f/((1u<<7)-1)); break; 1040 1041 default: 1042 DE_ASSERT(DE_FALSE); 1043 } 1044 value << (attribNdx != 0 ? " + " : "" ) << scale << " * a_attrib" << attribNdx; 1045 } 1046 else 1047 value << (attribNdx != 0 ? " + " : "" ) << "a_attrib" << attribNdx; 1048 } 1049 1050 vertexShaderStream 1051 << "out mediump vec4 v_value;\n" 1052 << "void main (void)\n" 1053 << "{\n" 1054 << "\tv_value = " << value.str() << ";\n"; 1055 1056 if (state.attributes[0].integer) 1057 { 1058 float scale = 0.0f; 1059 1060 switch (state.attributes[0].type) 1061 { 1062 case GL_SHORT: scale = (1.0f/((1u<<14)-1)); break; 1063 case GL_UNSIGNED_SHORT: scale = (1.0f/((1u<<15)-1)); break; 1064 case GL_INT: scale = (1.0f/((1u<<30)-1)); break; 1065 case GL_UNSIGNED_INT: scale = (1.0f/((1u<<31)-1)); break; 1066 case GL_BYTE: scale = (1.0f/((1u<<6)-1)); break; 1067 case GL_UNSIGNED_BYTE: scale = (1.0f/((1u<<7)-1)); break; 1068 1069 1070 default: 1071 DE_ASSERT(DE_FALSE); 1072 } 1073 1074 vertexShaderStream 1075 << "\tgl_Position = vec4(" << scale << " * " << "a_attrib0.xyz, 1.0);\n" 1076 << "}"; 1077 } 1078 else 1079 { 1080 if (state.attributes[0].normalized || state.attributes[0].type == GL_FLOAT) 1081 { 1082 vertexShaderStream 1083 << "\tgl_Position = vec4(a_attrib0.xyz, 1.0);\n" 1084 << "}"; 1085 } 1086 else 1087 { 1088 float scale = 0.0f; 1089 1090 switch (state.attributes[0].type) 1091 { 1092 case GL_SHORT: scale = (1.0f/((1u<<14)-1)); break; 1093 case GL_UNSIGNED_SHORT: scale = (1.0f/((1u<<15)-1)); break; 1094 case GL_INT: scale = (1.0f/((1u<<30)-1)); break; 1095 case GL_UNSIGNED_INT: scale = (1.0f/((1u<<31)-1)); break; 1096 case GL_BYTE: scale = (1.0f/((1u<<6)-1)); break; 1097 case GL_UNSIGNED_BYTE: scale = (1.0f/((1u<<7)-1)); break; 1098 1099 default: 1100 DE_ASSERT(DE_FALSE); 1101 } 1102 1103 scale *= 0.5; 1104 1105 vertexShaderStream 1106 << "\tgl_Position = vec4(" << scale << " * " << "vec3(a_attrib0.xyz), 1.0);\n" 1107 << "}"; 1108 } 1109 } 1110 1111 const char* fragmentShader = 1112 "#version 300 es\n" 1113 "in mediump vec4 v_value;\n" 1114 "layout(location = 0) out mediump vec4 fragColor;\n" 1115 "void main (void)\n" 1116 "{\n" 1117 "\tfragColor = vec4(v_value.xyz, 1.0);\n" 1118 "}"; 1119 1120 return new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderStream.str(), fragmentShader)); 1121 } 1122 1123 void MultiVertexArrayObjectTest::setState (const VertexArrayState& state) 1124 { 1125 GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[state.elementArrayBuffer])); 1126 1127 for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++) 1128 { 1129 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_buffers[state.attributes[attribNdx].bufferNdx])); 1130 if (state.attributes[attribNdx].enabled) 1131 GLU_CHECK_CALL(glEnableVertexAttribArray(attribNdx)); 1132 else 1133 GLU_CHECK_CALL(glDisableVertexAttribArray(attribNdx)); 1134 1135 if (state.attributes[attribNdx].integer) 1136 GLU_CHECK_CALL(glVertexAttribIPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset))); 1137 else 1138 GLU_CHECK_CALL(glVertexAttribPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].normalized, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset))); 1139 1140 GLU_CHECK_CALL(glVertexAttribDivisor(attribNdx, state.attributes[attribNdx].divisor)); 1141 } 1142 } 1143 1144 void MultiVertexArrayObjectTest::makeDrawCall (const VertexArrayState& state) 1145 { 1146 GLU_CHECK_CALL(glClearColor(0.7f, 0.7f, 0.7f, 1.0f)); 1147 GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT)); 1148 1149 if (m_spec.useDrawElements) 1150 { 1151 if (state.elementArrayBuffer == 0) 1152 { 1153 if (m_spec.instances == 0) 1154 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices)); 1155 else 1156 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices, m_spec.instances)); 1157 } 1158 else 1159 { 1160 if (m_spec.instances == 0) 1161 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset))); 1162 else 1163 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset), m_spec.instances)); 1164 } 1165 } 1166 else 1167 { 1168 if (m_spec.instances == 0) 1169 GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, m_spec.count)); 1170 else 1171 GLU_CHECK_CALL(glDrawArraysInstanced(GL_TRIANGLES, 0, m_spec.count, m_spec.instances)); 1172 } 1173 } 1174 1175 void MultiVertexArrayObjectTest::render (tcu::Surface& vaoResult, tcu::Surface& defaultResult) 1176 { 1177 GLuint vao = 0; 1178 1179 GLU_CHECK_CALL(glGenVertexArrays(1, &vao)); 1180 GLU_CHECK_CALL(glBindVertexArray(vao)); 1181 setState(m_spec.vao); 1182 GLU_CHECK_CALL(glBindVertexArray(0)); 1183 1184 setState(m_spec.state); 1185 1186 GLU_CHECK_CALL(glBindVertexArray(vao)); 1187 GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram())); 1188 makeDrawCall(m_spec.vao); 1189 glu::readPixels(m_context.getRenderContext(), 0, 0, vaoResult.getAccess()); 1190 setState(m_spec.vao); 1191 GLU_CHECK_CALL(glBindVertexArray(0)); 1192 1193 GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram())); 1194 makeDrawCall(m_spec.state); 1195 glu::readPixels(m_context.getRenderContext(), 0, 0, defaultResult.getAccess()); 1196 } 1197 1198 void MultiVertexArrayObjectTest::genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef) 1199 { 1200 setState(m_spec.vao); 1201 GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram())); 1202 makeDrawCall(m_spec.vao); 1203 glu::readPixels(m_context.getRenderContext(), 0, 0, vaoRef.getAccess()); 1204 1205 setState(m_spec.state); 1206 GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram())); 1207 makeDrawCall(m_spec.state); 1208 glu::readPixels(m_context.getRenderContext(), 0, 0, defaultRef.getAccess()); 1209 } 1210 1211 TestCase::IterateResult MultiVertexArrayObjectTest::iterate (void) 1212 { 1213 tcu::Surface vaoReference (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight()); 1214 tcu::Surface stateReference (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight()); 1215 1216 tcu::Surface vaoResult (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight()); 1217 tcu::Surface stateResult (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight()); 1218 1219 bool isOk; 1220 1221 logVertexArrayState(m_log, m_spec.vao, "Vertex Array Object State"); 1222 logVertexArrayState(m_log, m_spec.state, "OpenGL Vertex Array State"); 1223 genReferences(stateReference, vaoReference); 1224 render(stateResult, vaoResult); 1225 1226 isOk = tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array State", stateReference, stateResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT); 1227 isOk = isOk && tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array Object", vaoReference, vaoResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT); 1228 1229 if (isOk) 1230 { 1231 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1232 return STOP; 1233 } 1234 else 1235 { 1236 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1237 return STOP; 1238 } 1239 } 1240 1241 VertexArrayObjectTestGroup::VertexArrayObjectTestGroup (Context& context) 1242 : TestCaseGroup(context, "vertex_array_objects", "Vertex array object test cases") 1243 { 1244 } 1245 1246 VertexArrayObjectTestGroup::~VertexArrayObjectTestGroup (void) 1247 { 1248 } 1249 1250 void VertexArrayObjectTestGroup::init (void) 1251 { 1252 BufferSpec floatCoordBuffer48_1 = { 48, 384, 2, 0, 0, GL_FLOAT, 0, 0, -1.0f, 1.0f }; 1253 BufferSpec floatCoordBuffer48_2 = { 48, 384, 2, 0, 0, GL_FLOAT, 0, 0, -1.0f, 1.0f }; 1254 1255 BufferSpec shortCoordBuffer48 = { 48, 192, 2, 0, 0, GL_SHORT, -32768, 32768, 0.0f, 0.0f }; 1256 1257 // Different buffer 1258 { 1259 Spec spec; 1260 1261 VertexArrayState state; 1262 1263 state.attributes.push_back(Attribute()); 1264 1265 state.attributes[0].enabled = true; 1266 state.attributes[0].size = 2; 1267 state.attributes[0].stride = 0; 1268 state.attributes[0].type = GL_FLOAT; 1269 state.attributes[0].integer = GL_FALSE; 1270 state.attributes[0].divisor = 0; 1271 state.attributes[0].offset = 0; 1272 state.attributes[0].normalized = GL_FALSE; 1273 1274 state.elementArrayBuffer = 0; 1275 1276 spec.buffers.push_back(floatCoordBuffer48_1); 1277 spec.buffers.push_back(floatCoordBuffer48_2); 1278 1279 spec.useDrawElements = false; 1280 spec.instances = 0; 1281 spec.count = 48; 1282 spec.vao = state; 1283 spec.state = state; 1284 spec.indexOffset = 0; 1285 spec.indexRangeMin = 0; 1286 spec.indexRangeMax = 0; 1287 spec.indexType = GL_NONE; 1288 spec.indexCount = 0; 1289 1290 spec.state.attributes[0].bufferNdx = 1; 1291 spec.vao.attributes[0].bufferNdx = 2; 1292 addChild(new VertexArrayObjectTest(m_context, spec, "diff_buffer", "diff_buffer")); 1293 } 1294 // Different size 1295 { 1296 Spec spec; 1297 1298 VertexArrayState state; 1299 1300 state.attributes.push_back(Attribute()); 1301 1302 state.attributes[0].enabled = true; 1303 state.attributes[0].size = 2; 1304 state.attributes[0].stride = 0; 1305 state.attributes[0].type = GL_FLOAT; 1306 state.attributes[0].integer = GL_FALSE; 1307 state.attributes[0].divisor = 0; 1308 state.attributes[0].offset = 0; 1309 state.attributes[0].normalized = GL_FALSE; 1310 state.attributes[0].bufferNdx = 1; 1311 1312 state.elementArrayBuffer = 0; 1313 1314 spec.buffers.push_back(floatCoordBuffer48_1); 1315 1316 spec.useDrawElements = false; 1317 spec.instances = 0; 1318 spec.count = 24; 1319 spec.vao = state; 1320 spec.state = state; 1321 spec.indexOffset = 0; 1322 spec.indexRangeMin = 0; 1323 spec.indexRangeMax = 0; 1324 spec.indexType = GL_NONE; 1325 spec.indexCount = 0; 1326 1327 spec.state.attributes[0].size = 2; 1328 spec.vao.attributes[0].size = 3; 1329 addChild(new VertexArrayObjectTest(m_context, spec, "diff_size", "diff_size")); 1330 } 1331 1332 // Different stride 1333 { 1334 Spec spec; 1335 1336 VertexArrayState state; 1337 1338 state.attributes.push_back(Attribute()); 1339 1340 state.attributes[0].enabled = true; 1341 state.attributes[0].size = 2; 1342 state.attributes[0].stride = 0; 1343 state.attributes[0].type = GL_SHORT; 1344 state.attributes[0].integer = GL_FALSE; 1345 state.attributes[0].divisor = 0; 1346 state.attributes[0].offset = 0; 1347 state.attributes[0].normalized = GL_TRUE; 1348 state.attributes[0].bufferNdx = 1; 1349 1350 state.elementArrayBuffer = 0; 1351 1352 spec.buffers.push_back(shortCoordBuffer48); 1353 1354 spec.useDrawElements = false; 1355 spec.instances = 0; 1356 spec.count = 24; 1357 spec.vao = state; 1358 spec.state = state; 1359 spec.indexOffset = 0; 1360 spec.indexRangeMin = 0; 1361 spec.indexRangeMax = 0; 1362 spec.indexType = GL_NONE; 1363 spec.indexCount = 0; 1364 1365 spec.vao.attributes[0].stride = 2; 1366 spec.state.attributes[0].stride = 4; 1367 addChild(new VertexArrayObjectTest(m_context, spec, "diff_stride", "diff_stride")); 1368 } 1369 1370 // Different types 1371 { 1372 Spec spec; 1373 1374 VertexArrayState state; 1375 1376 state.attributes.push_back(Attribute()); 1377 1378 state.attributes[0].enabled = true; 1379 state.attributes[0].size = 2; 1380 state.attributes[0].stride = 0; 1381 state.attributes[0].type = GL_SHORT; 1382 state.attributes[0].integer = GL_FALSE; 1383 state.attributes[0].divisor = 0; 1384 state.attributes[0].offset = 0; 1385 state.attributes[0].normalized = GL_TRUE; 1386 state.attributes[0].bufferNdx = 1; 1387 1388 state.elementArrayBuffer = 0; 1389 1390 spec.buffers.push_back(shortCoordBuffer48); 1391 1392 spec.useDrawElements = false; 1393 spec.instances = 0; 1394 spec.count = 24; 1395 spec.vao = state; 1396 spec.state = state; 1397 spec.indexOffset = 0; 1398 spec.indexRangeMin = 0; 1399 spec.indexRangeMax = 0; 1400 spec.indexType = GL_NONE; 1401 spec.indexCount = 0; 1402 1403 spec.vao.attributes[0].type = GL_SHORT; 1404 spec.state.attributes[0].type = GL_BYTE; 1405 addChild(new VertexArrayObjectTest(m_context, spec, "diff_type", "diff_type")); 1406 } 1407 // Different "integer" 1408 { 1409 Spec spec; 1410 1411 VertexArrayState state; 1412 1413 state.attributes.push_back(Attribute()); 1414 1415 state.attributes[0].enabled = true; 1416 state.attributes[0].size = 2; 1417 state.attributes[0].stride = 0; 1418 state.attributes[0].type = GL_BYTE; 1419 state.attributes[0].integer = GL_TRUE; 1420 state.attributes[0].divisor = 0; 1421 state.attributes[0].offset = 0; 1422 state.attributes[0].normalized = GL_FALSE; 1423 state.attributes[0].bufferNdx = 1; 1424 1425 state.elementArrayBuffer = 0; 1426 1427 spec.buffers.push_back(shortCoordBuffer48); 1428 1429 spec.useDrawElements = false; 1430 spec.count = 24; 1431 spec.vao = state; 1432 spec.state = state; 1433 spec.instances = 0; 1434 spec.indexOffset = 0; 1435 spec.indexRangeMin = 0; 1436 spec.indexRangeMax = 0; 1437 spec.indexType = GL_NONE; 1438 spec.indexCount = 0; 1439 1440 spec.state.attributes[0].integer = GL_FALSE; 1441 spec.vao.attributes[0].integer = GL_TRUE; 1442 addChild(new VertexArrayObjectTest(m_context, spec, "diff_integer", "diff_integer")); 1443 } 1444 // Different divisor 1445 { 1446 Spec spec; 1447 1448 VertexArrayState state; 1449 1450 state.attributes.push_back(Attribute()); 1451 state.attributes.push_back(Attribute()); 1452 1453 state.attributes[0].enabled = true; 1454 state.attributes[0].size = 2; 1455 state.attributes[0].stride = 0; 1456 state.attributes[0].type = GL_SHORT; 1457 state.attributes[0].integer = GL_FALSE; 1458 state.attributes[0].divisor = 0; 1459 state.attributes[0].offset = 0; 1460 state.attributes[0].normalized = GL_TRUE; 1461 state.attributes[0].bufferNdx = 1; 1462 1463 state.attributes[1].enabled = true; 1464 state.attributes[1].size = 4; 1465 state.attributes[1].stride = 0; 1466 state.attributes[1].type = GL_FLOAT; 1467 state.attributes[1].integer = GL_FALSE; 1468 state.attributes[1].divisor = 0; 1469 state.attributes[1].offset = 0; 1470 state.attributes[1].normalized = GL_FALSE; 1471 state.attributes[1].bufferNdx = 2; 1472 1473 state.elementArrayBuffer = 0; 1474 1475 spec.buffers.push_back(shortCoordBuffer48); 1476 spec.buffers.push_back(floatCoordBuffer48_1); 1477 1478 spec.useDrawElements = false; 1479 spec.instances = 10; 1480 spec.count = 12; 1481 spec.vao = state; 1482 spec.state = state; 1483 spec.indexOffset = 0; 1484 spec.indexRangeMin = 0; 1485 spec.indexRangeMax = 0; 1486 spec.indexType = GL_NONE; 1487 spec.indexCount = 0; 1488 1489 spec.vao.attributes[1].divisor = 3; 1490 spec.state.attributes[1].divisor = 2; 1491 1492 addChild(new VertexArrayObjectTest(m_context, spec, "diff_divisor", "diff_divisor")); 1493 } 1494 // Different offset 1495 { 1496 Spec spec; 1497 1498 VertexArrayState state; 1499 1500 state.attributes.push_back(Attribute()); 1501 1502 state.attributes[0].enabled = true; 1503 state.attributes[0].size = 2; 1504 state.attributes[0].stride = 0; 1505 state.attributes[0].type = GL_SHORT; 1506 state.attributes[0].integer = GL_FALSE; 1507 state.attributes[0].divisor = 0; 1508 state.attributes[0].offset = 0; 1509 state.attributes[0].normalized = GL_TRUE; 1510 state.attributes[0].bufferNdx = 1; 1511 1512 state.elementArrayBuffer = 0; 1513 1514 spec.buffers.push_back(shortCoordBuffer48); 1515 1516 spec.useDrawElements = false; 1517 spec.instances = 0; 1518 spec.count = 24; 1519 spec.vao = state; 1520 spec.state = state; 1521 spec.indexOffset = 0; 1522 spec.indexRangeMin = 0; 1523 spec.indexRangeMax = 0; 1524 spec.indexType = GL_NONE; 1525 spec.indexCount = 0; 1526 1527 spec.vao.attributes[0].offset = 2; 1528 spec.state.attributes[0].offset = 4; 1529 addChild(new VertexArrayObjectTest(m_context, spec, "diff_offset", "diff_offset")); 1530 } 1531 // Different normalize 1532 { 1533 Spec spec; 1534 1535 VertexArrayState state; 1536 1537 state.attributes.push_back(Attribute()); 1538 1539 state.attributes[0].enabled = true; 1540 state.attributes[0].size = 2; 1541 state.attributes[0].stride = 0; 1542 state.attributes[0].type = GL_SHORT; 1543 state.attributes[0].integer = GL_FALSE; 1544 state.attributes[0].divisor = 0; 1545 state.attributes[0].offset = 0; 1546 state.attributes[0].normalized = GL_TRUE; 1547 state.attributes[0].bufferNdx = 1; 1548 1549 state.elementArrayBuffer = 0; 1550 1551 spec.buffers.push_back(shortCoordBuffer48); 1552 1553 spec.useDrawElements = false; 1554 spec.instances = 0; 1555 spec.count = 48; 1556 spec.vao = state; 1557 spec.state = state; 1558 spec.indexOffset = 0; 1559 spec.indexRangeMin = 0; 1560 spec.indexRangeMax = 0; 1561 spec.indexType = GL_NONE; 1562 spec.indexCount = 0; 1563 1564 spec.vao.attributes[0].normalized = GL_TRUE; 1565 spec.state.attributes[0].normalized = GL_FALSE;; 1566 addChild(new VertexArrayObjectTest(m_context, spec, "diff_normalize", "diff_normalize")); 1567 } 1568 // DrawElements with buffer / Pointer 1569 { 1570 Spec spec; 1571 1572 VertexArrayState state; 1573 1574 state.attributes.push_back(Attribute()); 1575 1576 state.attributes[0].enabled = true; 1577 state.attributes[0].size = 2; 1578 state.attributes[0].stride = 0; 1579 state.attributes[0].type = GL_FLOAT; 1580 state.attributes[0].integer = GL_FALSE; 1581 state.attributes[0].divisor = 0; 1582 state.attributes[0].offset = 0; 1583 state.attributes[0].normalized = GL_TRUE; 1584 state.attributes[0].bufferNdx = 1; 1585 1586 state.elementArrayBuffer = 0; 1587 1588 spec.buffers.push_back(floatCoordBuffer48_1); 1589 1590 BufferSpec indexBuffer = { 24, 192, 1, 0, 0, GL_UNSIGNED_SHORT, 0, 48, 0.0f, 0.0f }; 1591 spec.buffers.push_back(indexBuffer); 1592 1593 spec.useDrawElements = true; 1594 spec.count = 24; 1595 spec.vao = state; 1596 spec.state = state; 1597 spec.instances = 0; 1598 spec.indexOffset = 0; 1599 spec.indexRangeMin = 0; 1600 spec.indexRangeMax = 48; 1601 spec.indexType = GL_UNSIGNED_SHORT; 1602 spec.indexCount = 24; 1603 1604 spec.state.elementArrayBuffer = 0; 1605 spec.vao.elementArrayBuffer = 2; 1606 addChild(new VertexArrayObjectTest(m_context, spec, "diff_indices", "diff_indices")); 1607 } 1608 // Use all attributes 1609 1610 addChild(new MultiVertexArrayObjectTest(m_context, "all_attributes", "all_attributes")); 1611 } 1612 1613 } // Functional 1614 } // gles3 1615 } // deqp 1616