1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 2.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 Drawing tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es2fDrawTests.hpp" 25 #include "glsDrawTest.hpp" 26 #include "tcuRenderTarget.hpp" 27 #include "deRandom.hpp" 28 #include "deStringUtil.hpp" 29 #include "deUniquePtr.hpp" 30 #include "deSTLUtil.hpp" 31 32 #include "glwEnums.hpp" 33 34 #include <set> 35 36 namespace deqp 37 { 38 namespace gles2 39 { 40 namespace Functional 41 { 42 namespace 43 { 44 45 enum TestIterationType 46 { 47 TYPE_DRAW_COUNT, // !< test with 1, 5, and 25 primitives 48 49 TYPE_LAST 50 }; 51 52 static void addTestIterations (gls::DrawTest* test, const gls::DrawTestSpec& baseSpec, TestIterationType type) 53 { 54 gls::DrawTestSpec spec(baseSpec); 55 56 if (type == TYPE_DRAW_COUNT) 57 { 58 spec.primitiveCount = 1; 59 test->addIteration(spec, "draw count = 1"); 60 61 spec.primitiveCount = 5; 62 test->addIteration(spec, "draw count = 5"); 63 64 spec.primitiveCount = 25; 65 test->addIteration(spec, "draw count = 25"); 66 } 67 else 68 DE_ASSERT(false); 69 } 70 71 static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method) 72 { 73 spec.apiType = glu::ApiType::es(2,0); 74 spec.primitive = gls::DrawTestSpec::PRIMITIVE_TRIANGLES; 75 spec.primitiveCount = 5; 76 spec.drawMethod = method; 77 spec.indexType = gls::DrawTestSpec::INDEXTYPE_LAST; 78 spec.indexPointerOffset = 0; 79 spec.indexStorage = gls::DrawTestSpec::STORAGE_LAST; 80 spec.first = 0; 81 spec.indexMin = 0; 82 spec.indexMax = 0; 83 spec.instanceCount = 1; 84 85 spec.attribs.resize(2); 86 87 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 88 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 89 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 90 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 91 spec.attribs[0].componentCount = 4; 92 spec.attribs[0].offset = 0; 93 spec.attribs[0].stride = 0; 94 spec.attribs[0].normalize = false; 95 spec.attribs[0].instanceDivisor = 0; 96 spec.attribs[0].useDefaultAttribute = false; 97 98 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 99 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 100 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER; 101 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 102 spec.attribs[1].componentCount = 2; 103 spec.attribs[1].offset = 0; 104 spec.attribs[1].stride = 0; 105 spec.attribs[1].normalize = false; 106 spec.attribs[1].instanceDivisor = 0; 107 spec.attribs[1].useDefaultAttribute = false; 108 } 109 110 111 class AttributeGroup : public TestCaseGroup 112 { 113 public: 114 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); 115 ~AttributeGroup (void); 116 117 void init (void); 118 119 private: 120 gls::DrawTestSpec::DrawMethod m_method; 121 gls::DrawTestSpec::Primitive m_primitive; 122 gls::DrawTestSpec::IndexType m_indexType; 123 gls::DrawTestSpec::Storage m_indexStorage; 124 }; 125 126 AttributeGroup::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) 127 : TestCaseGroup (context, name, descr) 128 , m_method (drawMethod) 129 , m_primitive (primitive) 130 , m_indexType (indexType) 131 , m_indexStorage (indexStorage) 132 { 133 } 134 135 AttributeGroup::~AttributeGroup (void) 136 { 137 } 138 139 void AttributeGroup::init (void) 140 { 141 // Single attribute 142 { 143 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array."); 144 gls::DrawTestSpec spec; 145 146 spec.apiType = glu::ApiType::es(2,0); 147 spec.primitive = m_primitive; 148 spec.primitiveCount = 0; 149 spec.drawMethod = m_method; 150 spec.indexType = m_indexType; 151 spec.indexPointerOffset = 0; 152 spec.indexStorage = m_indexStorage; 153 spec.first = 0; 154 spec.indexMin = 0; 155 spec.indexMax = 0; 156 spec.instanceCount = 1; 157 158 spec.attribs.resize(1); 159 160 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 161 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 162 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 163 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 164 spec.attribs[0].componentCount = 2; 165 spec.attribs[0].offset = 0; 166 spec.attribs[0].stride = 0; 167 spec.attribs[0].normalize = false; 168 spec.attribs[0].instanceDivisor = 0; 169 spec.attribs[0].useDefaultAttribute = false; 170 171 addTestIterations(test, spec, TYPE_DRAW_COUNT); 172 173 this->addChild(test); 174 } 175 176 // Multiple attribute 177 { 178 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays"); 179 gls::DrawTestSpec spec; 180 181 spec.apiType = glu::ApiType::es(2,0); 182 spec.primitive = m_primitive; 183 spec.primitiveCount = 0; 184 spec.drawMethod = m_method; 185 spec.indexType = m_indexType; 186 spec.indexPointerOffset = 0; 187 spec.indexStorage = m_indexStorage; 188 spec.first = 0; 189 spec.indexMin = 0; 190 spec.indexMax = 0; 191 spec.instanceCount = 1; 192 193 spec.attribs.resize(2); 194 195 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 196 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 197 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 198 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 199 spec.attribs[0].componentCount = 4; 200 spec.attribs[0].offset = 0; 201 spec.attribs[0].stride = 0; 202 spec.attribs[0].normalize = false; 203 spec.attribs[0].instanceDivisor = 0; 204 spec.attribs[0].useDefaultAttribute = false; 205 206 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 207 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 208 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER; 209 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 210 spec.attribs[1].componentCount = 2; 211 spec.attribs[1].offset = 0; 212 spec.attribs[1].stride = 0; 213 spec.attribs[1].normalize = false; 214 spec.attribs[1].instanceDivisor = 0; 215 spec.attribs[1].useDefaultAttribute = false; 216 217 addTestIterations(test, spec, TYPE_DRAW_COUNT); 218 219 this->addChild(test); 220 } 221 222 // Multiple attribute, second one default. 223 { 224 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*."); 225 gls::DrawTestSpec spec; 226 227 spec.apiType = glu::ApiType::es(2,0); 228 spec.primitive = m_primitive; 229 spec.primitiveCount = 5; 230 spec.drawMethod = m_method; 231 spec.indexType = m_indexType; 232 spec.indexPointerOffset = 0; 233 spec.indexStorage = m_indexStorage; 234 spec.first = 0; 235 spec.indexMin = 0; 236 spec.indexMax = 0; 237 spec.instanceCount = 1; 238 239 spec.attribs.resize(2); 240 241 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 242 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 243 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 244 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 245 spec.attribs[0].componentCount = 2; 246 spec.attribs[0].offset = 0; 247 spec.attribs[0].stride = 0; 248 spec.attribs[0].normalize = false; 249 spec.attribs[0].instanceDivisor = 0; 250 spec.attribs[0].useDefaultAttribute = false; 251 252 struct IOPair 253 { 254 gls::DrawTestSpec::InputType input; 255 gls::DrawTestSpec::OutputType output; 256 int componentCount; 257 } iopairs[] = 258 { 259 { gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC2, 4 }, 260 { gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC4, 2 }, 261 }; 262 263 for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx) 264 { 265 const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output); 266 267 spec.attribs[1].inputType = iopairs[ioNdx].input; 268 spec.attribs[1].outputType = iopairs[ioNdx].output; 269 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER; 270 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 271 spec.attribs[1].componentCount = iopairs[ioNdx].componentCount; 272 spec.attribs[1].offset = 0; 273 spec.attribs[1].stride = 0; 274 spec.attribs[1].normalize = false; 275 spec.attribs[1].instanceDivisor = 0; 276 spec.attribs[1].useDefaultAttribute = true; 277 278 test->addIteration(spec, desc.c_str()); 279 } 280 281 this->addChild(test); 282 } 283 } 284 285 class IndexGroup : public TestCaseGroup 286 { 287 public: 288 IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod); 289 ~IndexGroup (void); 290 291 void init (void); 292 293 private: 294 gls::DrawTestSpec::DrawMethod m_method; 295 }; 296 297 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod) 298 : TestCaseGroup (context, name, descr) 299 , m_method (drawMethod) 300 { 301 } 302 303 IndexGroup::~IndexGroup (void) 304 { 305 } 306 307 void IndexGroup::init (void) 308 { 309 struct IndexTest 310 { 311 gls::DrawTestSpec::Storage storage; 312 gls::DrawTestSpec::IndexType type; 313 bool aligned; 314 int offsets[3]; 315 }; 316 317 const IndexTest tests[] = 318 { 319 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, { 0, 1, -1 } }, 320 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, { 0, 2, -1 } }, 321 322 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, false, { 1, 3, -1 } }, 323 324 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, { 0, 1, -1 } }, 325 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, { 0, 2, -1 } }, 326 327 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_SHORT, false, { 1, 3, -1 } }, 328 }; 329 330 gls::DrawTestSpec spec; 331 332 tcu::TestCaseGroup* userPtrGroup = new tcu::TestCaseGroup(m_testCtx, "user_ptr", "user pointer"); 333 tcu::TestCaseGroup* unalignedUserPtrGroup = new tcu::TestCaseGroup(m_testCtx, "unaligned_user_ptr", "unaligned user pointer"); 334 tcu::TestCaseGroup* bufferGroup = new tcu::TestCaseGroup(m_testCtx, "buffer", "buffer"); 335 tcu::TestCaseGroup* unalignedBufferGroup = new tcu::TestCaseGroup(m_testCtx, "unaligned_buffer", "unaligned buffer"); 336 337 genBasicSpec(spec, m_method); 338 339 this->addChild(userPtrGroup); 340 this->addChild(unalignedUserPtrGroup); 341 this->addChild(bufferGroup); 342 this->addChild(unalignedBufferGroup); 343 344 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx) 345 { 346 const IndexTest& indexTest = tests[testNdx]; 347 tcu::TestCaseGroup* group = (indexTest.storage == gls::DrawTestSpec::STORAGE_USER) ? ((indexTest.aligned) ? (userPtrGroup) : (unalignedUserPtrGroup)) : ((indexTest.aligned) ? (bufferGroup) : (unalignedBufferGroup)); 348 349 const std::string name = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type); 350 const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage); 351 de::MovePtr<gls::DrawTest> test (new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str())); 352 353 spec.indexType = indexTest.type; 354 spec.indexStorage = indexTest.storage; 355 356 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx) 357 { 358 const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]); 359 spec.indexPointerOffset = indexTest.offsets[iterationNdx]; 360 test->addIteration(spec, iterationDesc.c_str()); 361 } 362 363 if (spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET && 364 spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE) 365 group->addChild(test.release()); 366 } 367 } 368 369 370 class FirstGroup : public TestCaseGroup 371 { 372 public: 373 FirstGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod); 374 ~FirstGroup (void); 375 376 void init (void); 377 378 private: 379 gls::DrawTestSpec::DrawMethod m_method; 380 }; 381 382 FirstGroup::FirstGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod) 383 : TestCaseGroup (context, name, descr) 384 , m_method (drawMethod) 385 { 386 } 387 388 FirstGroup::~FirstGroup (void) 389 { 390 } 391 392 void FirstGroup::init (void) 393 { 394 const int firsts[] = 395 { 396 0, 1, 17 397 }; 398 399 gls::DrawTestSpec spec; 400 genBasicSpec(spec, m_method); 401 402 for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); ++firstNdx) 403 { 404 const std::string name = std::string("first_") + de::toString(firsts[firstNdx]); 405 const std::string desc = std::string("first ") + de::toString(firsts[firstNdx]); 406 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()); 407 408 spec.first = firsts[firstNdx]; 409 410 addTestIterations(test, spec, TYPE_DRAW_COUNT); 411 412 this->addChild(test); 413 } 414 } 415 416 class MethodGroup : public TestCaseGroup 417 { 418 public: 419 MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod); 420 ~MethodGroup (void); 421 422 void init (void); 423 424 private: 425 gls::DrawTestSpec::DrawMethod m_method; 426 }; 427 428 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod) 429 : TestCaseGroup (context, name, descr) 430 , m_method (drawMethod) 431 { 432 } 433 434 MethodGroup::~MethodGroup (void) 435 { 436 } 437 438 void MethodGroup::init (void) 439 { 440 const bool indexed = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED); 441 const bool hasFirst = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED); 442 443 const gls::DrawTestSpec::Primitive primitive[] = 444 { 445 gls::DrawTestSpec::PRIMITIVE_POINTS, 446 gls::DrawTestSpec::PRIMITIVE_TRIANGLES, 447 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN, 448 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP, 449 gls::DrawTestSpec::PRIMITIVE_LINES, 450 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP, 451 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP 452 }; 453 454 if (hasFirst) 455 { 456 // First-tests 457 this->addChild(new FirstGroup(m_context, "first", "First tests", m_method)); 458 } 459 460 if (indexed) 461 { 462 // Index-tests 463 if (m_method != gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED) 464 this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method)); 465 } 466 467 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx) 468 { 469 const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]); 470 const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]); 471 472 this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER)); 473 } 474 } 475 476 class RandomGroup : public TestCaseGroup 477 { 478 public: 479 RandomGroup (Context& context, const char* name, const char* descr); 480 ~RandomGroup (void); 481 482 void init (void); 483 }; 484 485 template <int SIZE> 486 struct UniformWeightArray 487 { 488 float weights[SIZE]; 489 490 UniformWeightArray (void) 491 { 492 for (int i=0; i<SIZE; ++i) 493 weights[i] = 1.0f; 494 } 495 }; 496 497 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr) 498 : TestCaseGroup (context, name, descr) 499 { 500 } 501 502 RandomGroup::~RandomGroup (void) 503 { 504 } 505 506 void RandomGroup::init (void) 507 { 508 const int numAttempts = 100; 509 510 static const int attribCounts[] = { 1, 2, 5 }; 511 static const float attribWeights[] = { 30, 10, 1 }; 512 static const int primitiveCounts[] = { 1, 5, 64 }; 513 static const float primitiveCountWeights[] = { 20, 10, 1 }; 514 static const int indexOffsets[] = { 0, 7, 13 }; 515 static const float indexOffsetWeights[] = { 20, 20, 1 }; 516 static const int firsts[] = { 0, 7, 13 }; 517 static const float firstWeights[] = { 20, 20, 1 }; 518 static const int offsets[] = { 0, 1, 5, 12 }; 519 static const float offsetWeights[] = { 50, 10, 10, 10 }; 520 static const int strides[] = { 0, 7, 16, 17 }; 521 static const float strideWeights[] = { 50, 10, 10, 10 }; 522 523 static const gls::DrawTestSpec::Primitive primitives[] = 524 { 525 gls::DrawTestSpec::PRIMITIVE_POINTS, 526 gls::DrawTestSpec::PRIMITIVE_TRIANGLES, 527 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN, 528 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP, 529 gls::DrawTestSpec::PRIMITIVE_LINES, 530 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP, 531 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP 532 }; 533 const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights; 534 535 static const gls::DrawTestSpec::DrawMethod drawMethods[] = 536 { 537 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS, 538 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS, 539 }; 540 const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights; 541 542 static const gls::DrawTestSpec::IndexType indexTypes[] = 543 { 544 gls::DrawTestSpec::INDEXTYPE_BYTE, 545 gls::DrawTestSpec::INDEXTYPE_SHORT, 546 }; 547 const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights; 548 549 static const gls::DrawTestSpec::Storage storages[] = 550 { 551 gls::DrawTestSpec::STORAGE_USER, 552 gls::DrawTestSpec::STORAGE_BUFFER, 553 }; 554 const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights; 555 556 static const gls::DrawTestSpec::InputType inputTypes[] = 557 { 558 gls::DrawTestSpec::INPUTTYPE_FLOAT, 559 gls::DrawTestSpec::INPUTTYPE_FIXED, 560 gls::DrawTestSpec::INPUTTYPE_BYTE, 561 gls::DrawTestSpec::INPUTTYPE_SHORT, 562 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE, 563 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT 564 }; 565 const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights; 566 567 static const gls::DrawTestSpec::OutputType outputTypes[] = 568 { 569 gls::DrawTestSpec::OUTPUTTYPE_FLOAT, 570 gls::DrawTestSpec::OUTPUTTYPE_VEC2, 571 gls::DrawTestSpec::OUTPUTTYPE_VEC3, 572 gls::DrawTestSpec::OUTPUTTYPE_VEC4, 573 }; 574 const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights; 575 576 static const gls::DrawTestSpec::Usage usages[] = 577 { 578 gls::DrawTestSpec::USAGE_STATIC_DRAW, 579 gls::DrawTestSpec::USAGE_DYNAMIC_DRAW, 580 gls::DrawTestSpec::USAGE_STREAM_DRAW, 581 }; 582 const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights; 583 584 static const deUint32 blacklistedCases[]= 585 { 586 3153, //!< extremely narrow triangle, results depend on sample positions 587 }; 588 589 std::set<deUint32> insertedHashes; 590 size_t insertedCount = 0; 591 592 for (int ndx = 0; ndx < numAttempts; ++ndx) 593 { 594 de::Random random(0xc551393 + ndx); // random does not depend on previous cases 595 596 int attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights); 597 gls::DrawTestSpec spec; 598 599 spec.apiType = glu::ApiType::es(2,0); 600 spec.primitive = random.chooseWeighted<gls::DrawTestSpec::Primitive> (DE_ARRAY_BEGIN(primitives), DE_ARRAY_END(primitives), primitiveWeights.weights); 601 spec.primitiveCount = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(primitiveCounts), DE_ARRAY_END(primitiveCounts), primitiveCountWeights); 602 spec.drawMethod = random.chooseWeighted<gls::DrawTestSpec::DrawMethod> (DE_ARRAY_BEGIN(drawMethods), DE_ARRAY_END(drawMethods), drawMethodWeights.weights); 603 spec.indexType = random.chooseWeighted<gls::DrawTestSpec::IndexType> (DE_ARRAY_BEGIN(indexTypes), DE_ARRAY_END(indexTypes), indexTypeWeights.weights); 604 spec.indexPointerOffset = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexOffsets), DE_ARRAY_END(indexOffsets), indexOffsetWeights); 605 spec.indexStorage = random.chooseWeighted<gls::DrawTestSpec::Storage> (DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights); 606 spec.first = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(firsts), DE_ARRAY_END(firsts), firstWeights); 607 spec.indexMin = 0; 608 spec.indexMax = 0; 609 spec.instanceCount = 0; 610 611 // check spec is legal 612 if (!spec.valid()) 613 continue; 614 615 for (int attrNdx = 0; attrNdx < attributeCount;) 616 { 617 bool valid; 618 gls::DrawTestSpec::AttributeSpec attribSpec; 619 620 attribSpec.inputType = random.chooseWeighted<gls::DrawTestSpec::InputType> (DE_ARRAY_BEGIN(inputTypes), DE_ARRAY_END(inputTypes), inputTypeWeights.weights); 621 attribSpec.outputType = random.chooseWeighted<gls::DrawTestSpec::OutputType> (DE_ARRAY_BEGIN(outputTypes), DE_ARRAY_END(outputTypes), outputTypeWeights.weights); 622 attribSpec.storage = random.chooseWeighted<gls::DrawTestSpec::Storage> (DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights); 623 attribSpec.usage = random.chooseWeighted<gls::DrawTestSpec::Usage> (DE_ARRAY_BEGIN(usages), DE_ARRAY_END(usages), usageWeights.weights); 624 attribSpec.componentCount = random.getInt(1, 4); 625 attribSpec.offset = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights); 626 attribSpec.stride = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights); 627 attribSpec.normalize = random.getBool(); 628 attribSpec.instanceDivisor = 0; 629 attribSpec.useDefaultAttribute = random.getBool(); 630 631 // check spec is legal 632 valid = attribSpec.valid(spec.apiType); 633 634 // we do not want interleaved elements. (Might result in some weird floating point values) 635 if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride) 636 valid = false; 637 638 // try again if not valid 639 if (valid) 640 { 641 spec.attribs.push_back(attribSpec); 642 ++attrNdx; 643 } 644 } 645 646 // Do not collapse all vertex positions to a single positions 647 if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS) 648 spec.attribs[0].instanceDivisor = 0; 649 650 // Is render result meaningful? 651 { 652 // Only one vertex 653 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS) 654 continue; 655 if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS) 656 continue; 657 658 // Triangle only on one axis 659 if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP) 660 { 661 if (spec.attribs[0].componentCount == 1) 662 continue; 663 if (spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_FLOAT || spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_INT || spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_UINT) 664 continue; 665 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2) 666 continue; 667 } 668 } 669 670 // Add case 671 { 672 deUint32 hash = spec.hash(); 673 for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx) 674 hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash(); 675 676 if (insertedHashes.find(hash) == insertedHashes.end() && 677 !de::contains(DE_ARRAY_BEGIN(blacklistedCases), DE_ARRAY_END(blacklistedCases), hash)) 678 { 679 // Only aligned cases 680 if (spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET && 681 spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE) 682 this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str())); 683 insertedHashes.insert(hash); 684 685 ++insertedCount; 686 } 687 } 688 } 689 } 690 691 } // anonymous 692 693 DrawTests::DrawTests (Context& context) 694 : TestCaseGroup(context, "draw", "Drawing tests") 695 { 696 } 697 698 DrawTests::~DrawTests (void) 699 { 700 } 701 702 void DrawTests::init (void) 703 { 704 // Basic 705 { 706 const gls::DrawTestSpec::DrawMethod basicMethods[] = 707 { 708 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS, 709 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS, 710 }; 711 712 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx) 713 { 714 std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]); 715 std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]); 716 717 this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx])); 718 } 719 } 720 721 // Random 722 723 this->addChild(new RandomGroup(m_context, "random", "random draw commands.")); 724 } 725 726 } // Functional 727 } // gles2 728 } // deqp 729