1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2017 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 GL_EXT_draw_elements_base_vertex tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es31fDrawElementsBaseVertexTests.hpp" 25#include "deRandom.hpp" 26#include "deStringUtil.hpp" 27#include "tcuRenderTarget.hpp" 28#include "tcuVectorUtil.hpp" 29#include "sglrGLContext.hpp" 30#include "glsDrawTest.hpp" 31#include "gluStrUtil.hpp" 32#include "gluPixelTransfer.hpp" 33#include "gluContextInfo.hpp" 34 35#include "glwEnums.hpp" 36#include "glwFunctions.hpp" 37 38#include <string> 39#include <set> 40 41using std::vector; 42using std::string; 43using tcu::TestLog; 44 45using namespace glw; 46 47namespace deqp 48{ 49namespace gles31 50{ 51namespace Functional 52{ 53namespace 54{ 55 56enum TestIterationType 57{ 58 TYPE_DRAW_COUNT, // !< test with 1, 5, and 25 primitives 59 TYPE_INSTANCE_COUNT, // !< test with 1, 4, and 11 instances 60 61 TYPE_LAST 62}; 63 64static size_t getElementCount (gls::DrawTestSpec::Primitive primitive, size_t primitiveCount) 65{ 66 switch (primitive) 67 { 68 case gls::DrawTestSpec::PRIMITIVE_POINTS: return primitiveCount; 69 case gls::DrawTestSpec::PRIMITIVE_TRIANGLES: return primitiveCount * 3; 70 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN: return primitiveCount + 2; 71 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP: return primitiveCount + 2; 72 case gls::DrawTestSpec::PRIMITIVE_LINES: return primitiveCount * 2; 73 case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP: return primitiveCount + 1; 74 case gls::DrawTestSpec::PRIMITIVE_LINE_LOOP: return (primitiveCount==1) ? (2) : (primitiveCount); 75 case gls::DrawTestSpec::PRIMITIVE_LINES_ADJACENCY: return primitiveCount * 4; 76 case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY: return primitiveCount + 3; 77 case gls::DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY: return primitiveCount * 6; 78 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY: return primitiveCount * 2 + 4; 79 default: 80 DE_ASSERT(false); 81 return 0; 82 } 83} 84 85static void addRangeElementsToSpec (gls::DrawTestSpec& spec) 86{ 87 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX) 88 { 89 spec.indexMin = 0; 90 spec.indexMax = (int)getElementCount(spec.primitive, spec.primitiveCount); 91 } 92} 93 94static void addTestIterations (gls::DrawTest* test, gls::DrawTestSpec& spec, TestIterationType type) 95{ 96 if (type == TYPE_DRAW_COUNT) 97 { 98 spec.primitiveCount = 1; 99 addRangeElementsToSpec(spec); 100 test->addIteration(spec, "draw count = 1"); 101 102 spec.primitiveCount = 5; 103 addRangeElementsToSpec(spec); 104 test->addIteration(spec, "draw count = 5"); 105 106 spec.primitiveCount = 25; 107 addRangeElementsToSpec(spec); 108 test->addIteration(spec, "draw count = 25"); 109 } 110 else if (type == TYPE_INSTANCE_COUNT) 111 { 112 spec.instanceCount = 1; 113 addRangeElementsToSpec(spec); 114 test->addIteration(spec, "instance count = 1"); 115 116 spec.instanceCount = 4; 117 addRangeElementsToSpec(spec); 118 test->addIteration(spec, "instance count = 4"); 119 120 spec.instanceCount = 11; 121 addRangeElementsToSpec(spec); 122 test->addIteration(spec, "instance count = 11"); 123 } 124 else 125 DE_ASSERT(false); 126} 127 128static void genBasicSpec (gls::DrawTestSpec& spec, glu::ContextType& contextType, gls::DrawTestSpec::DrawMethod method) 129{ 130 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3,1) : contextType.getAPI(); 131 spec.primitive = gls::DrawTestSpec::PRIMITIVE_TRIANGLES; 132 spec.primitiveCount = 5; 133 spec.drawMethod = method; 134 spec.indexType = gls::DrawTestSpec::INDEXTYPE_LAST; 135 spec.indexPointerOffset = 0; 136 spec.indexStorage = gls::DrawTestSpec::STORAGE_LAST; 137 spec.first = 0; 138 spec.indexMin = 0; 139 spec.indexMax = 0; 140 spec.instanceCount = 1; 141 spec.indirectOffset = 0; 142 143 spec.attribs.resize(2); 144 145 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 146 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 147 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 148 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 149 spec.attribs[0].componentCount = 4; 150 spec.attribs[0].offset = 0; 151 spec.attribs[0].stride = 0; 152 spec.attribs[0].normalize = false; 153 spec.attribs[0].instanceDivisor = 0; 154 spec.attribs[0].useDefaultAttribute = false; 155 156 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 157 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 158 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER; 159 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 160 spec.attribs[1].componentCount = 2; 161 spec.attribs[1].offset = 0; 162 spec.attribs[1].stride = 0; 163 spec.attribs[1].normalize = false; 164 spec.attribs[1].instanceDivisor = 0; 165 spec.attribs[1].useDefaultAttribute = false; 166 167 addRangeElementsToSpec(spec); 168} 169 170class VertexIDCase : public TestCase 171{ 172public: 173 VertexIDCase (Context& context, gls::DrawTestSpec::DrawMethod drawMethod); 174 ~VertexIDCase (void); 175 176 void init (void); 177 void deinit (void); 178 IterateResult iterate (void); 179 180 void draw (GLenum mode, GLsizei count, GLenum type, GLvoid* indices, GLint baseVertex); 181 void verifyImage (const tcu::Surface& image); 182 183private: 184 const glw::Functions& m_gl; 185 glu::ShaderProgram* m_program; 186 GLuint m_vao; 187 GLuint m_coordinatesBuffer; 188 GLuint m_elementsBuffer; 189 int m_iterNdx; 190 gls::DrawTestSpec::DrawMethod m_method; 191 192 enum 193 { 194 VIEWPORT_WIDTH = 64, 195 VIEWPORT_HEIGHT = 64 196 }; 197 198 enum 199 { 200 MAX_VERTICES = 2*3 //!< 2 triangles, totals 6 vertices 201 }; 202}; 203 204VertexIDCase::VertexIDCase (Context& context, gls::DrawTestSpec::DrawMethod drawMethod) 205 : TestCase (context, "vertex_id", "gl_VertexID Test") 206 , m_gl (m_context.getRenderContext().getFunctions()) 207 , m_program (DE_NULL) 208 , m_vao (0) 209 , m_coordinatesBuffer (0) 210 , m_elementsBuffer (0) 211 , m_iterNdx (0) 212 , m_method (drawMethod) 213{ 214} 215 216VertexIDCase::~VertexIDCase (void) 217{ 218 VertexIDCase::deinit(); 219} 220 221void VertexIDCase::init (void) 222{ 223 auto ctxType = m_context.getRenderContext().getType(); 224 if (m_method == deqp::gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX || 225 m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX || 226 m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX) 227 { 228 const bool supportsES32orGL45 = contextSupports(ctxType, glu::ApiType::es(3, 2)) || contextSupports(ctxType, glu::ApiType::core(4, 5)); 229 TCU_CHECK_AND_THROW(NotSupportedError, supportsES32orGL45 || m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_elements_base_vertex"), "GL_EXT_draw_elements_base_vertex is not supported."); 230 } 231 232 m_testCtx.getLog() << TestLog::Message 233 << "gl_VertexID should be the index of the vertex that is being passed to the shader. i.e. indices[i] + basevertex" 234 << TestLog::EndMessage; 235 236 DE_ASSERT(!m_program); 237 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources( 238 "#version 310 es\n" 239 "in highp vec4 a_position;\n" 240 "out mediump vec4 v_color;\n" 241 "uniform highp vec4 u_colors[8];\n" 242 "void main (void)\n" 243 "{\n" 244 " gl_Position = a_position;\n" 245 " v_color = u_colors[gl_VertexID];\n" 246 "}\n", 247 248 "#version 310 es\n" 249 "in mediump vec4 v_color;\n" 250 "layout(location = 0) out mediump vec4 o_color;\n" 251 "void main (void)\n" 252 "{\n" 253 " o_color = v_color;\n" 254 "}\n")); 255 256 m_testCtx.getLog() << *m_program; 257 258 if (!m_program->isOk()) 259 { 260 delete m_program; 261 m_program = DE_NULL; 262 TCU_FAIL("Failed to compile shader program"); 263 } 264 265 GLU_CHECK_GLW_CALL(m_gl, useProgram(m_program->getProgram())); 266 267 GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer)); 268 GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_elementsBuffer)); 269 270 if (!glu::isContextTypeES(ctxType)) 271 GLU_CHECK_GLW_CALL(m_gl, genVertexArrays(1, &m_vao)); 272} 273 274void VertexIDCase::deinit (void) 275{ 276 delete m_program; 277 m_program = DE_NULL; 278 279 if (m_elementsBuffer) 280 { 281 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_elementsBuffer)); 282 m_elementsBuffer = 0; 283 } 284 285 if (m_coordinatesBuffer) 286 { 287 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer)); 288 m_coordinatesBuffer = 0; 289 } 290 291 if (m_vao) 292 { 293 GLU_CHECK_GLW_CALL(m_gl, deleteVertexArrays(1, &m_vao)); 294 m_vao = 0; 295 } 296} 297 298void VertexIDCase::draw (GLenum mode, GLsizei count, GLenum type, GLvoid* indices, GLint baseVertex) 299{ 300 switch (m_method) 301 { 302 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX: 303 GLU_CHECK_GLW_CALL(m_gl, drawElementsBaseVertex(mode, count, type, indices, baseVertex)); 304 break; 305 306 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX: 307 { 308 GLint maxElementsVertices = 0; 309 GLU_CHECK_GLW_CALL(m_gl, getIntegerv(GL_MAX_ELEMENTS_VERTICES, &maxElementsVertices)); 310 GLU_CHECK_GLW_CALL(m_gl, drawRangeElementsBaseVertex(mode, 0, maxElementsVertices, count, type, indices, baseVertex)); 311 break; 312 } 313 314 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX: 315 GLU_CHECK_GLW_CALL(m_gl, drawElementsInstancedBaseVertex(mode, count, type, indices, 1, baseVertex)); 316 break; 317 318 default: 319 DE_FATAL("Draw method not supported"); 320 } 321} 322 323void VertexIDCase::verifyImage (const tcu::Surface& image) 324{ 325 tcu::TestLog& log = m_testCtx.getLog(); 326 bool isOk = true; 327 328 const int colorThreshold = 0; // expect perfect match 329 tcu::Surface error (image.getWidth(), image.getHeight()); 330 331 for (int y = 0; y < image.getHeight(); y++) 332 for (int x = 0; x < image.getWidth(); x++) 333 { 334 const tcu::RGBA pixel = image.getPixel(x, y); 335 bool pixelOk = true; 336 337 // Ignore pixels not drawn with basevertex 338 if ((x < image.getWidth()* 1/4) || (x > image.getWidth() * 3/4) 339 || (y < image.getHeight() * 1/4) || (y > image.getHeight() * 3/4)) 340 continue; 341 342 // Any pixel with !(B ~= 255) is faulty 343 if (de::abs(pixel.getBlue() - 255) > colorThreshold) 344 pixelOk = false; 345 346 error.setPixel(x, y, (pixelOk) ? (tcu::RGBA(0, 255, 0, 255)) : (tcu::RGBA(255, 0, 0, 255))); 347 isOk = isOk && pixelOk; 348 } 349 350 if (!isOk) 351 { 352 log << TestLog::Message << "Image verification failed." << TestLog::EndMessage; 353 log << TestLog::ImageSet("Verification result", "Result of rendering") 354 << TestLog::Image("Result", "Result", image) 355 << TestLog::Image("Error Mask", "Error mask", error) 356 << TestLog::EndImageSet; 357 } 358 else 359 { 360 log << TestLog::ImageSet("Verification result", "Result of rendering") 361 << TestLog::Image("Result", "Result", image) 362 << TestLog::EndImageSet; 363 } 364 365 if (isOk) 366 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 367 else 368 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result image invalid"); 369} 370 371VertexIDCase::IterateResult VertexIDCase::iterate (void) 372{ 373 const GLuint drawCount = 6; 374 const GLuint baseVertex = 4; 375 const GLuint coordLocation = m_gl.getAttribLocation(m_program->getProgram(), "a_position"); 376 const GLuint colorLocation = m_gl.getUniformLocation(m_program->getProgram(), "u_colors[0]"); 377 378 tcu::Surface surface(VIEWPORT_WIDTH, VIEWPORT_HEIGHT); 379 380 const GLfloat coords[] = 381 { 382 // full viewport quad 383 -1.0f, -1.0f, 384 +1.0f, -1.0f, 385 +1.0f, +1.0f, 386 -1.0f, +1.0f, 387 388 // half viewport quad centred 389 -0.5f, -0.5f, 390 +0.5f, -0.5f, 391 +0.5f, +0.5f, 392 -0.5f, +0.5f, 393 }; 394 395 const GLushort indices[] = 396 { 397 0, 1, 2, 2, 3, 0, 398 }; 399 400 const GLfloat colors[] = 401 { 402 0.0f, 0.0f, 0.0f, 1.0f, 403 0.5f, 1.0f, 0.5f, 1.0f, 404 0.0f, 0.5f, 1.0f, 1.0f, 405 0.0f, 1.0f, 0.0f, 1.0f, 406 407 0.0f, 0.0f, 1.0f, 1.0f, // blue 408 0.0f, 0.0f, 1.0f, 1.0f, // blue 409 0.0f, 0.0f, 1.0f, 1.0f, // blue 410 0.0f, 0.0f, 1.0f, 1.0f, // blue 411 }; 412 413 GLU_CHECK_GLW_CALL(m_gl, viewport(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT)); 414 GLU_CHECK_GLW_CALL(m_gl, clearColor(1.0f, 1.0f, 1.0f, 1.0f)); // white 415 GLU_CHECK_GLW_CALL(m_gl, clear(GL_COLOR_BUFFER_BIT)); 416 417 GLU_CHECK_GLW_CALL(m_gl, uniform4fv(colorLocation, DE_LENGTH_OF_ARRAY(colors), &colors[0])); 418 419 GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer)); 420 GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW)); 421 422 if (m_vao) 423 GLU_CHECK_GLW_CALL(m_gl, bindVertexArray(m_vao)); 424 GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(coordLocation)); 425 GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL)); 426 427 if (m_iterNdx == 0) 428 { 429 tcu::ScopedLogSection logSection (m_testCtx.getLog(), "Iter0", "Indices in client-side array"); 430 draw(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, (GLvoid*)indices, baseVertex); 431 } 432 433 if (m_iterNdx == 1) 434 { 435 tcu::ScopedLogSection logSection (m_testCtx.getLog(), "Iter1", "Indices in element array buffer"); 436 GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementsBuffer)); 437 GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)sizeof(indices), &indices[0], GL_STATIC_DRAW)); 438 draw(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, DE_NULL, baseVertex); 439 } 440 441 glu::readPixels(m_context.getRenderContext(), 0, 0, surface.getAccess()); 442 verifyImage(surface); 443 444 m_iterNdx += 1; 445 446 return (m_iterNdx < 2) ? CONTINUE : STOP; 447} 448 449class BuiltInVariableGroup : public TestCaseGroup 450{ 451public: 452 BuiltInVariableGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod); 453 ~BuiltInVariableGroup (void); 454 455 void init (void); 456 457private: 458 gls::DrawTestSpec::DrawMethod m_method; 459}; 460 461BuiltInVariableGroup::BuiltInVariableGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod) 462 : TestCaseGroup (context, name, descr) 463 , m_method (drawMethod) 464{ 465} 466 467BuiltInVariableGroup::~BuiltInVariableGroup (void) 468{ 469} 470 471void BuiltInVariableGroup::init (void) 472{ 473 addChild(new VertexIDCase(m_context, m_method)); 474} 475 476class IndexGroup : public TestCaseGroup 477{ 478public: 479 IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod); 480 ~IndexGroup (void); 481 482 void init (void); 483 484private: 485 gls::DrawTestSpec::DrawMethod m_method; 486}; 487 488IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod) 489 : TestCaseGroup (context, name, descr) 490 , m_method (drawMethod) 491{ 492} 493 494IndexGroup::~IndexGroup (void) 495{ 496} 497 498void IndexGroup::init (void) 499{ 500 struct IndexTest 501 { 502 gls::DrawTestSpec::IndexType type; 503 int offsets[3]; 504 }; 505 506 const IndexTest tests[] = 507 { 508 { gls::DrawTestSpec::INDEXTYPE_BYTE, { 0, 1, -1 } }, 509 { gls::DrawTestSpec::INDEXTYPE_SHORT, { 0, 2, -1 } }, 510 { gls::DrawTestSpec::INDEXTYPE_INT, { 0, 4, -1 } }, 511 }; 512 513 gls::DrawTestSpec spec; 514 glu::ContextType contextType = m_context.getRenderContext().getType(); 515 genBasicSpec(spec, contextType, m_method); 516 517 spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER; 518 519 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx) 520 { 521 const IndexTest& indexTest = tests[testNdx]; 522 523 const std::string name = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type); 524 const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type); 525 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()); 526 527 spec.indexType = indexTest.type; 528 529 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx) 530 { 531 const std::string iterationDesc = std::string("first vertex ") + de::toString(indexTest.offsets[iterationNdx] / gls::DrawTestSpec::indexTypeSize(indexTest.type)); 532 spec.indexPointerOffset = indexTest.offsets[iterationNdx]; 533 test->addIteration(spec, iterationDesc.c_str()); 534 } 535 536 addChild(test); 537 } 538} 539 540class BaseVertexGroup : public TestCaseGroup 541{ 542public: 543 BaseVertexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod); 544 ~BaseVertexGroup (void); 545 546 void init (void); 547 548private: 549 gls::DrawTestSpec::DrawMethod m_method; 550}; 551 552BaseVertexGroup::BaseVertexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod) 553 : TestCaseGroup (context, name, descr) 554 , m_method (drawMethod) 555{ 556} 557 558BaseVertexGroup::~BaseVertexGroup (void) 559{ 560} 561 562void BaseVertexGroup::init (void) 563{ 564 struct IndexTest 565 { 566 bool positiveBase; 567 gls::DrawTestSpec::IndexType type; 568 int baseVertex[2]; 569 }; 570 571 const IndexTest tests[] = 572 { 573 { true, gls::DrawTestSpec::INDEXTYPE_BYTE, { 1, 2 } }, 574 { true, gls::DrawTestSpec::INDEXTYPE_SHORT, { 1, 2 } }, 575 { true, gls::DrawTestSpec::INDEXTYPE_INT, { 1, 2 } }, 576 { false, gls::DrawTestSpec::INDEXTYPE_BYTE, { -1, -2 } }, 577 { false, gls::DrawTestSpec::INDEXTYPE_SHORT, { -1, -2 } }, 578 { false, gls::DrawTestSpec::INDEXTYPE_INT, { -1, -2 } }, 579 }; 580 581 gls::DrawTestSpec spec; 582 glu::ContextType contextType = m_context.getRenderContext().getType(); 583 genBasicSpec(spec, contextType, m_method); 584 585 spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER; 586 587 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx) 588 { 589 const IndexTest& indexTest = tests[testNdx]; 590 591 const std::string name = std::string("index_") + (indexTest.positiveBase ? "" : "neg_") + gls::DrawTestSpec::indexTypeToString(indexTest.type); 592 const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type); 593 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()); 594 595 spec.indexType = indexTest.type; 596 597 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.baseVertex); ++iterationNdx) 598 { 599 const std::string iterationDesc = std::string("base vertex ") + de::toString(indexTest.baseVertex[iterationNdx]); 600 spec.baseVertex = indexTest.baseVertex[iterationNdx]; 601 // spec.indexMin + spec.baseVertex can not be a negative value 602 if (spec.indexMin + spec.baseVertex < 0) 603 { 604 spec.indexMax -= (spec.indexMin + spec.baseVertex); 605 spec.indexMin -= (spec.indexMin + spec.baseVertex); 606 } 607 test->addIteration(spec, iterationDesc.c_str()); 608 } 609 610 addChild(test); 611 } 612} 613 614class AttributeGroup : public TestCaseGroup 615{ 616public: 617 AttributeGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod, gls::DrawTestSpec::Primitive primitive, gls::DrawTestSpec::IndexType indexType, gls::DrawTestSpec::Storage indexStorage); 618 ~AttributeGroup (void); 619 620 void init (void); 621 622private: 623 gls::DrawTestSpec::DrawMethod m_method; 624 gls::DrawTestSpec::Primitive m_primitive; 625 gls::DrawTestSpec::IndexType m_indexType; 626 gls::DrawTestSpec::Storage m_indexStorage; 627}; 628 629AttributeGroup::AttributeGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod, gls::DrawTestSpec::Primitive primitive, gls::DrawTestSpec::IndexType indexType, gls::DrawTestSpec::Storage indexStorage) 630 : TestCaseGroup (context, name, descr) 631 , m_method (drawMethod) 632 , m_primitive (primitive) 633 , m_indexType (indexType) 634 , m_indexStorage (indexStorage) 635{ 636} 637 638AttributeGroup::~AttributeGroup (void) 639{ 640} 641 642void AttributeGroup::init (void) 643{ 644 // Single attribute 645 { 646 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array."); 647 gls::DrawTestSpec spec; 648 glu::ContextType contextType = m_context.getRenderContext().getType(); 649 650 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3,1) : contextType.getAPI(); 651 spec.primitive = m_primitive; 652 spec.primitiveCount = 5; 653 spec.drawMethod = m_method; 654 spec.indexType = m_indexType; 655 spec.indexPointerOffset = 0; 656 spec.indexStorage = m_indexStorage; 657 spec.first = 0; 658 spec.indexMin = 0; 659 spec.indexMax = 0; 660 spec.instanceCount = 1; 661 spec.indirectOffset = 0; 662 663 spec.attribs.resize(1); 664 665 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 666 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 667 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 668 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 669 spec.attribs[0].componentCount = 2; 670 spec.attribs[0].offset = 0; 671 spec.attribs[0].stride = 0; 672 spec.attribs[0].normalize = false; 673 spec.attribs[0].instanceDivisor = 0; 674 spec.attribs[0].useDefaultAttribute = false; 675 676 addTestIterations(test, spec, TYPE_DRAW_COUNT); 677 678 this->addChild(test); 679 } 680 681 // Multiple attribute 682 { 683 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays."); 684 gls::DrawTestSpec spec; 685 glu::ContextType contextType = m_context.getRenderContext().getType(); 686 687 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3,1) : contextType.getAPI(); 688 spec.primitive = m_primitive; 689 spec.primitiveCount = 5; 690 spec.drawMethod = m_method; 691 spec.indexType = m_indexType; 692 spec.indexPointerOffset = 0; 693 spec.indexStorage = m_indexStorage; 694 spec.first = 0; 695 spec.indexMin = 0; 696 spec.indexMax = 0; 697 spec.instanceCount = 1; 698 spec.indirectOffset = 0; 699 700 spec.attribs.resize(2); 701 702 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 703 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 704 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 705 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 706 spec.attribs[0].componentCount = 4; 707 spec.attribs[0].offset = 0; 708 spec.attribs[0].stride = 0; 709 spec.attribs[0].normalize = false; 710 spec.attribs[0].instanceDivisor = 0; 711 spec.attribs[0].useDefaultAttribute = false; 712 713 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 714 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 715 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER; 716 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 717 spec.attribs[1].componentCount = 2; 718 spec.attribs[1].offset = 0; 719 spec.attribs[1].stride = 0; 720 spec.attribs[1].normalize = false; 721 spec.attribs[1].instanceDivisor = 0; 722 spec.attribs[1].useDefaultAttribute = false; 723 724 addTestIterations(test, spec, TYPE_DRAW_COUNT); 725 726 this->addChild(test); 727 } 728 729 // Multiple attribute, second one divided 730 { 731 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "instanced_attributes", "Instanced attribute array."); 732 gls::DrawTestSpec spec; 733 glu::ContextType contextType = m_context.getRenderContext().getType(); 734 735 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3,1) : contextType.getAPI(); 736 spec.primitive = m_primitive; 737 spec.primitiveCount = 5; 738 spec.drawMethod = m_method; 739 spec.indexType = m_indexType; 740 spec.indexPointerOffset = 0; 741 spec.indexStorage = m_indexStorage; 742 spec.first = 0; 743 spec.indexMin = 0; 744 spec.indexMax = 0; 745 spec.instanceCount = 1; 746 spec.indirectOffset = 0; 747 748 spec.attribs.resize(3); 749 750 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 751 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 752 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 753 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 754 spec.attribs[0].componentCount = 4; 755 spec.attribs[0].offset = 0; 756 spec.attribs[0].stride = 0; 757 spec.attribs[0].normalize = false; 758 spec.attribs[0].instanceDivisor = 0; 759 spec.attribs[0].useDefaultAttribute = false; 760 761 // Add another position component so the instances wont be drawn on each other 762 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 763 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 764 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER; 765 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 766 spec.attribs[1].componentCount = 2; 767 spec.attribs[1].offset = 0; 768 spec.attribs[1].stride = 0; 769 spec.attribs[1].normalize = false; 770 spec.attribs[1].instanceDivisor = 1; 771 spec.attribs[1].useDefaultAttribute = false; 772 spec.attribs[1].additionalPositionAttribute = true; 773 774 // Instanced color 775 spec.attribs[2].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 776 spec.attribs[2].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 777 spec.attribs[2].storage = gls::DrawTestSpec::STORAGE_BUFFER; 778 spec.attribs[2].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 779 spec.attribs[2].componentCount = 3; 780 spec.attribs[2].offset = 0; 781 spec.attribs[2].stride = 0; 782 spec.attribs[2].normalize = false; 783 spec.attribs[2].instanceDivisor = 1; 784 spec.attribs[2].useDefaultAttribute = false; 785 786 addTestIterations(test, spec, TYPE_INSTANCE_COUNT); 787 788 this->addChild(test); 789 } 790 791 // Multiple attribute, second one default 792 { 793 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*."); 794 gls::DrawTestSpec spec; 795 glu::ContextType contextType = m_context.getRenderContext().getType(); 796 797 spec.apiType = glu::isContextTypeES(contextType) ? glu::ApiType::es(3,1) : contextType.getAPI(); 798 spec.primitive = m_primitive; 799 spec.primitiveCount = 5; 800 spec.drawMethod = m_method; 801 spec.indexType = m_indexType; 802 spec.indexPointerOffset = 0; 803 spec.indexStorage = m_indexStorage; 804 spec.first = 0; 805 spec.indexMin = 0; 806 spec.indexMax = 0; 807 spec.instanceCount = 1; 808 spec.indirectOffset = 0; 809 810 spec.attribs.resize(2); 811 812 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 813 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 814 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 815 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 816 spec.attribs[0].componentCount = 2; 817 spec.attribs[0].offset = 0; 818 spec.attribs[0].stride = 0; 819 spec.attribs[0].normalize = false; 820 spec.attribs[0].instanceDivisor = 0; 821 spec.attribs[0].useDefaultAttribute = false; 822 823 struct IOPair 824 { 825 gls::DrawTestSpec::InputType input; 826 gls::DrawTestSpec::OutputType output; 827 int componentCount; 828 } iopairs[] = 829 { 830 { gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC2, 4 }, 831 { gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC4, 2 }, 832 { gls::DrawTestSpec::INPUTTYPE_INT, gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 4 }, 833 { gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 4 }, 834 }; 835 836 for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx) 837 { 838 const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output); 839 840 spec.attribs[1].inputType = iopairs[ioNdx].input; 841 spec.attribs[1].outputType = iopairs[ioNdx].output; 842 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER; 843 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 844 spec.attribs[1].componentCount = iopairs[ioNdx].componentCount; 845 spec.attribs[1].offset = 0; 846 spec.attribs[1].stride = 0; 847 spec.attribs[1].normalize = false; 848 spec.attribs[1].instanceDivisor = 0; 849 spec.attribs[1].useDefaultAttribute = true; 850 851 test->addIteration(spec, desc.c_str()); 852 } 853 854 this->addChild(test); 855 } 856} 857 858class MethodGroup : public TestCaseGroup 859{ 860public: 861 MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod); 862 ~MethodGroup (void); 863 864 void init (void); 865 866private: 867 gls::DrawTestSpec::DrawMethod m_method; 868}; 869 870MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod) 871 : TestCaseGroup (context, name, descr) 872 , m_method (drawMethod) 873{ 874} 875 876MethodGroup::~MethodGroup (void) 877{ 878} 879 880void MethodGroup::init (void) 881{ 882 const bool indexed = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX) 883 || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX) 884 || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX); 885 886 const gls::DrawTestSpec::Primitive primitive[] = 887 { 888 gls::DrawTestSpec::PRIMITIVE_POINTS, 889 gls::DrawTestSpec::PRIMITIVE_TRIANGLES, 890 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN, 891 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP, 892 gls::DrawTestSpec::PRIMITIVE_LINES, 893 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP, 894 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP 895 }; 896 897 if (indexed) 898 { 899 // Index-tests 900 this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method)); 901 this->addChild(new BaseVertexGroup(m_context, "base_vertex", "Base vertex tests", m_method)); 902 this->addChild(new BuiltInVariableGroup(m_context, "builtin_variable", "Built in shader variable tests", m_method)); 903 } 904 905 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx) 906 { 907 const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]); 908 const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]); 909 910 this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER)); 911 } 912} 913 914} // anonymous 915 916DrawElementsBaseVertexTests::DrawElementsBaseVertexTests (Context& context) 917 : TestCaseGroup(context, "draw_base_vertex", "Base vertex extension drawing tests") 918{ 919} 920 921DrawElementsBaseVertexTests::~DrawElementsBaseVertexTests (void) 922{ 923} 924 925void DrawElementsBaseVertexTests::init (void) 926{ 927 const gls::DrawTestSpec::DrawMethod basicMethods[] = 928 { 929 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX, 930 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX, 931 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX, 932 }; 933 934 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx) 935 { 936 const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]); 937 const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]); 938 939 this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx])); 940 } 941} 942 943} // Functional 944} // gles31 945} // deqp 946