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 Drawing tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es3fDrawTests.hpp" 25 #include "glsDrawTest.hpp" 26 #include "tcuRenderTarget.hpp" 27 #include "sglrGLContext.hpp" 28 #include "glwEnums.hpp" 29 #include "deRandom.hpp" 30 #include "deStringUtil.hpp" 31 #include "deUniquePtr.hpp" 32 #include "deSTLUtil.hpp" 33 34 #include <set> 35 36 namespace deqp 37 { 38 namespace gles3 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 TYPE_INSTANCE_COUNT, // !< test with 1, 4, and 11 instances 49 TYPE_INDEX_RANGE, // !< test with index range of [0, 23], [23, 40], and [5, 5] 50 51 TYPE_LAST 52 }; 53 54 static void addTestIterations (gls::DrawTest* test, const gls::DrawTestSpec& baseSpec, TestIterationType type) 55 { 56 gls::DrawTestSpec spec(baseSpec); 57 58 if (type == TYPE_DRAW_COUNT) 59 { 60 spec.primitiveCount = 1; 61 test->addIteration(spec, "draw count = 1"); 62 63 spec.primitiveCount = 5; 64 test->addIteration(spec, "draw count = 5"); 65 66 spec.primitiveCount = 25; 67 test->addIteration(spec, "draw count = 25"); 68 } 69 else if (type == TYPE_INSTANCE_COUNT) 70 { 71 spec.instanceCount = 1; 72 test->addIteration(spec, "instance count = 1"); 73 74 spec.instanceCount = 4; 75 test->addIteration(spec, "instance count = 4"); 76 77 spec.instanceCount = 11; 78 test->addIteration(spec, "instance count = 11"); 79 } 80 else if (type == TYPE_INDEX_RANGE) 81 { 82 spec.indexMin = 0; 83 spec.indexMax = 23; 84 test->addIteration(spec, "index range = [0, 23]"); 85 86 spec.indexMin = 23; 87 spec.indexMax = 40; 88 test->addIteration(spec, "index range = [23, 40]"); 89 90 // Only makes sense with points 91 if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_POINTS) 92 { 93 spec.indexMin = 5; 94 spec.indexMax = 5; 95 test->addIteration(spec, "index range = [5, 5]"); 96 } 97 } 98 else 99 DE_ASSERT(false); 100 } 101 102 static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method) 103 { 104 spec.apiType = glu::ApiType::es(3,0); 105 spec.primitive = gls::DrawTestSpec::PRIMITIVE_TRIANGLES; 106 spec.primitiveCount = 5; 107 spec.drawMethod = method; 108 spec.indexType = gls::DrawTestSpec::INDEXTYPE_LAST; 109 spec.indexPointerOffset = 0; 110 spec.indexStorage = gls::DrawTestSpec::STORAGE_LAST; 111 spec.first = 0; 112 spec.indexMin = 0; 113 spec.indexMax = 0; 114 spec.instanceCount = 1; 115 116 spec.attribs.resize(2); 117 118 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 119 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 120 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 121 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 122 spec.attribs[0].componentCount = 4; 123 spec.attribs[0].offset = 0; 124 spec.attribs[0].stride = 0; 125 spec.attribs[0].normalize = false; 126 spec.attribs[0].instanceDivisor = 0; 127 spec.attribs[0].useDefaultAttribute = false; 128 129 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 130 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 131 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER; 132 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 133 spec.attribs[1].componentCount = 2; 134 spec.attribs[1].offset = 0; 135 spec.attribs[1].stride = 0; 136 spec.attribs[1].normalize = false; 137 spec.attribs[1].instanceDivisor = 0; 138 spec.attribs[1].useDefaultAttribute = false; 139 } 140 141 class AttributeGroup : public TestCaseGroup 142 { 143 public: 144 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); 145 ~AttributeGroup (void); 146 147 void init (void); 148 149 private: 150 gls::DrawTestSpec::DrawMethod m_method; 151 gls::DrawTestSpec::Primitive m_primitive; 152 gls::DrawTestSpec::IndexType m_indexType; 153 gls::DrawTestSpec::Storage m_indexStorage; 154 }; 155 156 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) 157 : TestCaseGroup (context, name, descr) 158 , m_method (drawMethod) 159 , m_primitive (primitive) 160 , m_indexType (indexType) 161 , m_indexStorage (indexStorage) 162 { 163 } 164 165 AttributeGroup::~AttributeGroup (void) 166 { 167 } 168 169 void AttributeGroup::init (void) 170 { 171 // select test type 172 const bool instanced = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED) || 173 (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED); 174 const bool ranged = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED); 175 const TestIterationType testType = (instanced) ? (TYPE_INSTANCE_COUNT) : ((ranged) ? (TYPE_INDEX_RANGE) : (TYPE_DRAW_COUNT)); 176 177 // Single attribute 178 { 179 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array."); 180 gls::DrawTestSpec spec; 181 182 spec.apiType = glu::ApiType::es(3,0); 183 spec.primitive = m_primitive; 184 spec.primitiveCount = 5; 185 spec.drawMethod = m_method; 186 spec.indexType = m_indexType; 187 spec.indexPointerOffset = 0; 188 spec.indexStorage = m_indexStorage; 189 spec.first = 0; 190 spec.indexMin = 0; 191 spec.indexMax = 0; 192 spec.instanceCount = 1; 193 194 spec.attribs.resize(1); 195 196 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 197 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 198 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 199 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 200 spec.attribs[0].componentCount = 2; 201 spec.attribs[0].offset = 0; 202 spec.attribs[0].stride = 0; 203 spec.attribs[0].normalize = false; 204 spec.attribs[0].instanceDivisor = 0; 205 spec.attribs[0].useDefaultAttribute = false; 206 207 addTestIterations(test, spec, testType); 208 209 this->addChild(test); 210 } 211 212 // Multiple attribute 213 { 214 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays."); 215 gls::DrawTestSpec spec; 216 217 spec.apiType = glu::ApiType::es(3,0); 218 spec.primitive = m_primitive; 219 spec.primitiveCount = 5; 220 spec.drawMethod = m_method; 221 spec.indexType = m_indexType; 222 spec.indexPointerOffset = 0; 223 spec.indexStorage = m_indexStorage; 224 spec.first = 0; 225 spec.indexMin = 0; 226 spec.indexMax = 0; 227 spec.instanceCount = 1; 228 229 spec.attribs.resize(2); 230 231 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 232 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 233 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 234 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 235 spec.attribs[0].componentCount = 4; 236 spec.attribs[0].offset = 0; 237 spec.attribs[0].stride = 0; 238 spec.attribs[0].normalize = false; 239 spec.attribs[0].instanceDivisor = 0; 240 spec.attribs[0].useDefaultAttribute = false; 241 242 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 243 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 244 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER; 245 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 246 spec.attribs[1].componentCount = 2; 247 spec.attribs[1].offset = 0; 248 spec.attribs[1].stride = 0; 249 spec.attribs[1].normalize = false; 250 spec.attribs[1].instanceDivisor = 0; 251 spec.attribs[1].useDefaultAttribute = false; 252 253 addTestIterations(test, spec, testType); 254 255 this->addChild(test); 256 } 257 258 // Multiple attribute, second one divided 259 { 260 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "instanced_attributes", "Instanced attribute array."); 261 gls::DrawTestSpec spec; 262 263 spec.apiType = glu::ApiType::es(3,0); 264 spec.primitive = m_primitive; 265 spec.primitiveCount = 5; 266 spec.drawMethod = m_method; 267 spec.indexType = m_indexType; 268 spec.indexPointerOffset = 0; 269 spec.indexStorage = m_indexStorage; 270 spec.first = 0; 271 spec.indexMin = 0; 272 spec.indexMax = 0; 273 spec.instanceCount = 1; 274 275 spec.attribs.resize(3); 276 277 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 278 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 279 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 280 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 281 spec.attribs[0].componentCount = 4; 282 spec.attribs[0].offset = 0; 283 spec.attribs[0].stride = 0; 284 spec.attribs[0].normalize = false; 285 spec.attribs[0].instanceDivisor = 0; 286 spec.attribs[0].useDefaultAttribute = false; 287 288 // Add another position component so the instances wont be drawn on each other 289 spec.attribs[1].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 290 spec.attribs[1].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 291 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER; 292 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 293 spec.attribs[1].componentCount = 2; 294 spec.attribs[1].offset = 0; 295 spec.attribs[1].stride = 0; 296 spec.attribs[1].normalize = false; 297 spec.attribs[1].instanceDivisor = 1; 298 spec.attribs[1].useDefaultAttribute = false; 299 spec.attribs[1].additionalPositionAttribute = true; 300 301 // Instanced color 302 spec.attribs[2].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 303 spec.attribs[2].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 304 spec.attribs[2].storage = gls::DrawTestSpec::STORAGE_BUFFER; 305 spec.attribs[2].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 306 spec.attribs[2].componentCount = 3; 307 spec.attribs[2].offset = 0; 308 spec.attribs[2].stride = 0; 309 spec.attribs[2].normalize = false; 310 spec.attribs[2].instanceDivisor = 1; 311 spec.attribs[2].useDefaultAttribute = false; 312 313 addTestIterations(test, spec, testType); 314 315 this->addChild(test); 316 } 317 318 // Multiple attribute, second one default 319 { 320 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*."); 321 gls::DrawTestSpec spec; 322 323 spec.apiType = glu::ApiType::es(3,0); 324 spec.primitive = m_primitive; 325 spec.primitiveCount = 5; 326 spec.drawMethod = m_method; 327 spec.indexType = m_indexType; 328 spec.indexPointerOffset = 0; 329 spec.indexStorage = m_indexStorage; 330 spec.first = 0; 331 spec.indexMin = 0; 332 spec.indexMax = 20; // \note addTestIterations is not called for the spec, so we must ensure [indexMin, indexMax] is a good range 333 spec.instanceCount = 1; 334 335 spec.attribs.resize(2); 336 337 spec.attribs[0].inputType = gls::DrawTestSpec::INPUTTYPE_FLOAT; 338 spec.attribs[0].outputType = gls::DrawTestSpec::OUTPUTTYPE_VEC2; 339 spec.attribs[0].storage = gls::DrawTestSpec::STORAGE_BUFFER; 340 spec.attribs[0].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 341 spec.attribs[0].componentCount = 2; 342 spec.attribs[0].offset = 0; 343 spec.attribs[0].stride = 0; 344 spec.attribs[0].normalize = false; 345 spec.attribs[0].instanceDivisor = 0; 346 spec.attribs[0].useDefaultAttribute = false; 347 348 struct IOPair 349 { 350 gls::DrawTestSpec::InputType input; 351 gls::DrawTestSpec::OutputType output; 352 int componentCount; 353 } iopairs[] = 354 { 355 { gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC2, 4 }, 356 { gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC4, 2 }, 357 { gls::DrawTestSpec::INPUTTYPE_INT, gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 4 }, 358 { gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 4 }, 359 }; 360 361 for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx) 362 { 363 const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output); 364 365 spec.attribs[1].inputType = iopairs[ioNdx].input; 366 spec.attribs[1].outputType = iopairs[ioNdx].output; 367 spec.attribs[1].storage = gls::DrawTestSpec::STORAGE_BUFFER; 368 spec.attribs[1].usage = gls::DrawTestSpec::USAGE_STATIC_DRAW; 369 spec.attribs[1].componentCount = iopairs[ioNdx].componentCount; 370 spec.attribs[1].offset = 0; 371 spec.attribs[1].stride = 0; 372 spec.attribs[1].normalize = false; 373 spec.attribs[1].instanceDivisor = 0; 374 spec.attribs[1].useDefaultAttribute = true; 375 376 test->addIteration(spec, desc.c_str()); 377 } 378 379 this->addChild(test); 380 } 381 } 382 383 class IndexGroup : public TestCaseGroup 384 { 385 public: 386 IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod); 387 ~IndexGroup (void); 388 389 void init (void); 390 391 private: 392 gls::DrawTestSpec::DrawMethod m_method; 393 }; 394 395 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod) 396 : TestCaseGroup (context, name, descr) 397 , m_method (drawMethod) 398 { 399 } 400 401 IndexGroup::~IndexGroup (void) 402 { 403 } 404 405 void IndexGroup::init (void) 406 { 407 struct IndexTest 408 { 409 gls::DrawTestSpec::Storage storage; 410 gls::DrawTestSpec::IndexType type; 411 bool aligned; 412 int offsets[3]; 413 }; 414 415 const IndexTest tests[] = 416 { 417 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, { 0, 1, -1 } }, 418 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, { 0, 2, -1 } }, 419 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_INT, true, { 0, 4, -1 } }, 420 421 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, false, { 1, 3, -1 } }, 422 { gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_INT, false, { 2, 3, -1 } }, 423 424 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, { 0, 1, -1 } }, 425 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, { 0, 2, -1 } }, 426 { gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_INT, true, { 0, 4, -1 } }, 427 }; 428 429 gls::DrawTestSpec spec; 430 431 tcu::TestCaseGroup* userPtrGroup = new tcu::TestCaseGroup(m_testCtx, "user_ptr", "user pointer"); 432 tcu::TestCaseGroup* unalignedUserPtrGroup = new tcu::TestCaseGroup(m_testCtx, "unaligned_user_ptr", "unaligned user pointer"); 433 tcu::TestCaseGroup* bufferGroup = new tcu::TestCaseGroup(m_testCtx, "buffer", "buffer"); 434 435 genBasicSpec(spec, m_method); 436 437 this->addChild(userPtrGroup); 438 this->addChild(unalignedUserPtrGroup); 439 this->addChild(bufferGroup); 440 441 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx) 442 { 443 const IndexTest& indexTest = tests[testNdx]; 444 tcu::TestCaseGroup* group = (indexTest.storage == gls::DrawTestSpec::STORAGE_USER) 445 ? ((indexTest.aligned) ? (userPtrGroup) : (unalignedUserPtrGroup)) 446 : ((indexTest.aligned) ? (bufferGroup) : (DE_NULL)); 447 448 const std::string name = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type); 449 const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage); 450 de::MovePtr<gls::DrawTest> test (new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str())); 451 452 spec.indexType = indexTest.type; 453 spec.indexStorage = indexTest.storage; 454 455 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx) 456 { 457 const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]); 458 spec.indexPointerOffset = indexTest.offsets[iterationNdx]; 459 test->addIteration(spec, iterationDesc.c_str()); 460 } 461 462 DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET); 463 DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE); 464 group->addChild(test.release()); 465 } 466 } 467 468 469 class FirstGroup : public TestCaseGroup 470 { 471 public: 472 FirstGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod); 473 ~FirstGroup (void); 474 475 void init (void); 476 477 private: 478 gls::DrawTestSpec::DrawMethod m_method; 479 }; 480 481 FirstGroup::FirstGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod) 482 : TestCaseGroup (context, name, descr) 483 , m_method (drawMethod) 484 { 485 } 486 487 FirstGroup::~FirstGroup (void) 488 { 489 } 490 491 void FirstGroup::init (void) 492 { 493 const int firsts[] = 494 { 495 1, 3, 17 496 }; 497 498 gls::DrawTestSpec spec; 499 genBasicSpec(spec, m_method); 500 501 for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); ++firstNdx) 502 { 503 const std::string name = std::string("first_") + de::toString(firsts[firstNdx]); 504 const std::string desc = std::string("first ") + de::toString(firsts[firstNdx]); 505 gls::DrawTest* test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()); 506 507 spec.first = firsts[firstNdx]; 508 509 addTestIterations(test, spec, TYPE_DRAW_COUNT); 510 511 this->addChild(test); 512 } 513 } 514 515 class MethodGroup : public TestCaseGroup 516 { 517 public: 518 MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod); 519 ~MethodGroup (void); 520 521 void init (void); 522 523 private: 524 gls::DrawTestSpec::DrawMethod m_method; 525 }; 526 527 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod) 528 : TestCaseGroup (context, name, descr) 529 , m_method (drawMethod) 530 { 531 } 532 533 MethodGroup::~MethodGroup (void) 534 { 535 } 536 537 void MethodGroup::init (void) 538 { 539 const bool indexed = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED); 540 const bool hasFirst = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED); 541 542 const gls::DrawTestSpec::Primitive primitive[] = 543 { 544 gls::DrawTestSpec::PRIMITIVE_POINTS, 545 gls::DrawTestSpec::PRIMITIVE_TRIANGLES, 546 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN, 547 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP, 548 gls::DrawTestSpec::PRIMITIVE_LINES, 549 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP, 550 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP 551 }; 552 553 if (hasFirst) 554 { 555 // First-tests 556 this->addChild(new FirstGroup(m_context, "first", "First tests", m_method)); 557 } 558 559 if (indexed) 560 { 561 // Index-tests 562 if (m_method != gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED) 563 this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method)); 564 } 565 566 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx) 567 { 568 const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]); 569 const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]); 570 571 this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER)); 572 } 573 } 574 575 class GridProgram : public sglr::ShaderProgram 576 { 577 public: 578 GridProgram (void); 579 580 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 581 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 582 }; 583 584 GridProgram::GridProgram (void) 585 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration() 586 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 587 << sglr::pdec::VertexAttribute("a_offset", rr::GENERICVECTYPE_FLOAT) 588 << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT) 589 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT) 590 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 591 << sglr::pdec::VertexSource("#version 300 es\n" 592 "in highp vec4 a_position;\n" 593 "in highp vec4 a_offset;\n" 594 "in highp vec4 a_color;\n" 595 "out mediump vec4 v_color;\n" 596 "void main(void)\n" 597 "{\n" 598 " gl_Position = a_position + a_offset;\n" 599 " v_color = a_color;\n" 600 "}\n") 601 << sglr::pdec::FragmentSource( 602 "#version 300 es\n" 603 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n" 604 "in mediump vec4 v_color;\n" 605 "void main(void)\n" 606 "{\n" 607 " dEQP_FragColor = v_color;\n" 608 "}\n")) 609 { 610 } 611 612 void GridProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 613 { 614 for (int ndx = 0; ndx < numPackets; ++ndx) 615 { 616 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx) + rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 617 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[2], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 618 } 619 } 620 621 void GridProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 622 { 623 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 624 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 625 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx)); 626 } 627 628 class InstancedGridRenderTest : public TestCase 629 { 630 public: 631 InstancedGridRenderTest (Context& context, const char* name, const char* desc, int gridSide, bool useIndices); 632 ~InstancedGridRenderTest (void); 633 634 IterateResult iterate (void); 635 636 private: 637 void renderTo (sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dst); 638 bool verifyImage (const tcu::Surface& image); 639 640 const int m_gridSide; 641 const bool m_useIndices; 642 }; 643 644 InstancedGridRenderTest::InstancedGridRenderTest (Context& context, const char* name, const char* desc, int gridSide, bool useIndices) 645 : TestCase (context, name, desc) 646 , m_gridSide (gridSide) 647 , m_useIndices (useIndices) 648 { 649 } 650 651 InstancedGridRenderTest::~InstancedGridRenderTest (void) 652 { 653 } 654 655 InstancedGridRenderTest::IterateResult InstancedGridRenderTest::iterate (void) 656 { 657 const int renderTargetWidth = de::min(1024, m_context.getRenderTarget().getWidth()); 658 const int renderTargetHeight = de::min(1024, m_context.getRenderTarget().getHeight()); 659 660 sglr::GLContext ctx (m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(0, 0, renderTargetWidth, renderTargetHeight)); 661 tcu::Surface surface (renderTargetWidth, renderTargetHeight); 662 GridProgram program; 663 664 // render 665 666 renderTo(ctx, program, surface); 667 668 // verify image 669 670 if (verifyImage(surface)) 671 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 672 else 673 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rendering result"); 674 return STOP; 675 } 676 677 void InstancedGridRenderTest::renderTo (sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dst) 678 { 679 const tcu::Vec4 green (0, 1, 0, 1); 680 const tcu::Vec4 yellow (1, 1, 0, 1); 681 682 deUint32 positionBuf = 0; 683 deUint32 offsetBuf = 0; 684 deUint32 colorBuf = 0; 685 deUint32 indexBuf = 0; 686 deUint32 programID = ctx.createProgram(&program); 687 deInt32 posLocation = ctx.getAttribLocation(programID, "a_position"); 688 deInt32 offsetLocation = ctx.getAttribLocation(programID, "a_offset"); 689 deInt32 colorLocation = ctx.getAttribLocation(programID, "a_color"); 690 691 float cellW = 2.0f / (float)m_gridSide; 692 float cellH = 2.0f / (float)m_gridSide; 693 const tcu::Vec4 vertexPositions[] = 694 { 695 tcu::Vec4(0, 0, 0, 1), 696 tcu::Vec4(cellW, 0, 0, 1), 697 tcu::Vec4(0, cellH, 0, 1), 698 699 tcu::Vec4(0, cellH, 0, 1), 700 tcu::Vec4(cellW, 0, 0, 1), 701 tcu::Vec4(cellW, cellH, 0, 1), 702 }; 703 704 const deUint16 indices[] = 705 { 706 0, 4, 3, 707 2, 1, 5 708 }; 709 710 std::vector<tcu::Vec4> offsets; 711 for (int x = 0; x < m_gridSide; ++x) 712 for (int y = 0; y < m_gridSide; ++y) 713 offsets.push_back(tcu::Vec4((float)x * cellW - 1.0f, (float)y * cellW - 1.0f, 0, 0)); 714 715 std::vector<tcu::Vec4> colors; 716 for (int x = 0; x < m_gridSide; ++x) 717 for (int y = 0; y < m_gridSide; ++y) 718 colors.push_back(((x + y) % 2 == 0) ? (green) : (yellow)); 719 720 ctx.genBuffers(1, &positionBuf); 721 ctx.bindBuffer(GL_ARRAY_BUFFER, positionBuf); 722 ctx.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW); 723 ctx.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 724 ctx.vertexAttribDivisor(posLocation, 0); 725 ctx.enableVertexAttribArray(posLocation); 726 727 ctx.genBuffers(1, &offsetBuf); 728 ctx.bindBuffer(GL_ARRAY_BUFFER, offsetBuf); 729 ctx.bufferData(GL_ARRAY_BUFFER, offsets.size() * sizeof(tcu::Vec4), &offsets[0], GL_STATIC_DRAW); 730 ctx.vertexAttribPointer(offsetLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 731 ctx.vertexAttribDivisor(offsetLocation, 1); 732 ctx.enableVertexAttribArray(offsetLocation); 733 734 ctx.genBuffers(1, &colorBuf); 735 ctx.bindBuffer(GL_ARRAY_BUFFER, colorBuf); 736 ctx.bufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(tcu::Vec4), &colors[0], GL_STATIC_DRAW); 737 ctx.vertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 738 ctx.vertexAttribDivisor(colorLocation, 1); 739 ctx.enableVertexAttribArray(colorLocation); 740 741 if (m_useIndices) 742 { 743 ctx.genBuffers(1, &indexBuf); 744 ctx.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf); 745 ctx.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); 746 } 747 748 ctx.clearColor(0, 0, 0, 1); 749 ctx.clear(GL_COLOR_BUFFER_BIT); 750 751 ctx.viewport(0, 0, dst.getWidth(), dst.getHeight()); 752 753 ctx.useProgram(programID); 754 if (m_useIndices) 755 ctx.drawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL, m_gridSide * m_gridSide); 756 else 757 ctx.drawArraysInstanced(GL_TRIANGLES, 0, 6, m_gridSide * m_gridSide); 758 ctx.useProgram(0); 759 760 if (m_useIndices) 761 ctx.deleteBuffers(1, &indexBuf); 762 ctx.deleteBuffers(1, &colorBuf); 763 ctx.deleteBuffers(1, &offsetBuf); 764 ctx.deleteBuffers(1, &positionBuf); 765 ctx.deleteProgram(programID); 766 767 ctx.finish(); 768 ctx.readPixels(dst, 0, 0, dst.getWidth(), dst.getHeight()); 769 770 glu::checkError(ctx.getError(), "", __FILE__, __LINE__); 771 } 772 773 bool InstancedGridRenderTest::verifyImage (const tcu::Surface& image) 774 { 775 // \note the green/yellow pattern is only for clarity. The test will only verify that all instances were drawn by looking for anything non-green/yellow. 776 using tcu::TestLog; 777 778 const int colorThreshold = 20; 779 780 tcu::Surface error (image.getWidth(), image.getHeight()); 781 bool isOk = true; 782 783 for (int y = 0; y < image.getHeight(); y++) 784 for (int x = 0; x < image.getWidth(); x++) 785 { 786 if (x == 0 || y == 0 || y + 1 == image.getHeight() || x + 1 == image.getWidth()) 787 { 788 // Background color might bleed in at the borders with msaa 789 error.setPixel(x, y, tcu::RGBA(0, 255, 0, 255)); 790 } 791 else 792 { 793 const tcu::RGBA pixel = image.getPixel(x, y); 794 bool pixelOk = true; 795 796 // Any pixel with !(G ~= 255) is faulty (not a linear combinations of green and yellow) 797 if (de::abs(pixel.getGreen() - 255) > colorThreshold) 798 pixelOk = false; 799 800 // Any pixel with !(B ~= 0) is faulty (not a linear combinations of green and yellow) 801 if (de::abs(pixel.getBlue() - 0) > colorThreshold) 802 pixelOk = false; 803 804 error.setPixel(x, y, (pixelOk) ? (tcu::RGBA(0, 255, 0, 255)) : (tcu::RGBA(255, 0, 0, 255))); 805 isOk = isOk && pixelOk; 806 } 807 } 808 809 if (!isOk) 810 { 811 tcu::TestLog& log = m_testCtx.getLog(); 812 813 log << TestLog::Message << "Image verification failed." << TestLog::EndMessage; 814 log << TestLog::ImageSet("Verfication result", "Result of rendering") 815 << TestLog::Image("Result", "Result", image) 816 << TestLog::Image("ErrorMask", "Error mask", error) 817 << TestLog::EndImageSet; 818 } 819 else 820 { 821 tcu::TestLog& log = m_testCtx.getLog(); 822 823 log << TestLog::ImageSet("Verfication result", "Result of rendering") 824 << TestLog::Image("Result", "Result", image) 825 << TestLog::EndImageSet; 826 } 827 828 return isOk; 829 } 830 831 class InstancingGroup : public TestCaseGroup 832 { 833 public: 834 InstancingGroup (Context& context, const char* name, const char* descr); 835 ~InstancingGroup (void); 836 837 void init (void); 838 }; 839 840 InstancingGroup::InstancingGroup (Context& context, const char* name, const char* descr) 841 : TestCaseGroup (context, name, descr) 842 { 843 } 844 845 InstancingGroup::~InstancingGroup (void) 846 { 847 } 848 849 void InstancingGroup::init (void) 850 { 851 const int gridWidths[] = 852 { 853 2, 854 5, 855 10, 856 32, 857 100, 858 }; 859 860 // drawArrays 861 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(gridWidths); ++ndx) 862 { 863 const std::string name = std::string("draw_arrays_instanced_grid_") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]); 864 const std::string desc = std::string("DrawArraysInstanced, Grid size ") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]); 865 866 this->addChild(new InstancedGridRenderTest(m_context, name.c_str(), desc.c_str(), gridWidths[ndx], false)); 867 } 868 869 // drawElements 870 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(gridWidths); ++ndx) 871 { 872 const std::string name = std::string("draw_elements_instanced_grid_") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]); 873 const std::string desc = std::string("DrawElementsInstanced, Grid size ") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]); 874 875 this->addChild(new InstancedGridRenderTest(m_context, name.c_str(), desc.c_str(), gridWidths[ndx], true)); 876 } 877 } 878 879 class RandomGroup : public TestCaseGroup 880 { 881 public: 882 RandomGroup (Context& context, const char* name, const char* descr); 883 ~RandomGroup (void); 884 885 void init (void); 886 }; 887 888 template <int SIZE> 889 struct UniformWeightArray 890 { 891 float weights[SIZE]; 892 893 UniformWeightArray (void) 894 { 895 for (int i=0; i<SIZE; ++i) 896 weights[i] = 1.0f; 897 } 898 }; 899 900 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr) 901 : TestCaseGroup (context, name, descr) 902 { 903 } 904 905 RandomGroup::~RandomGroup (void) 906 { 907 } 908 909 void RandomGroup::init (void) 910 { 911 const int numAttempts = 300; 912 913 static const int attribCounts[] = { 1, 2, 5 }; 914 static const float attribWeights[] = { 30, 10, 1 }; 915 static const int primitiveCounts[] = { 1, 5, 64 }; 916 static const float primitiveCountWeights[] = { 20, 10, 1 }; 917 static const int indexOffsets[] = { 0, 7, 13 }; 918 static const float indexOffsetWeights[] = { 20, 20, 1 }; 919 static const int firsts[] = { 0, 7, 13 }; 920 static const float firstWeights[] = { 20, 20, 1 }; 921 static const int instanceCounts[] = { 1, 2, 16, 17 }; 922 static const float instanceWeights[] = { 20, 10, 5, 1 }; 923 static const int indexMins[] = { 0, 1, 3, 8 }; 924 static const int indexMaxs[] = { 4, 8, 128, 257 }; 925 static const float indexWeights[] = { 50, 50, 50, 50 }; 926 static const int offsets[] = { 0, 1, 5, 12 }; 927 static const float offsetWeights[] = { 50, 10, 10, 10 }; 928 static const int strides[] = { 0, 7, 16, 17 }; 929 static const float strideWeights[] = { 50, 10, 10, 10 }; 930 static const int instanceDivisors[] = { 0, 1, 3, 129 }; 931 static const float instanceDivisorWeights[]= { 70, 30, 10, 10 }; 932 933 static const gls::DrawTestSpec::Primitive primitives[] = 934 { 935 gls::DrawTestSpec::PRIMITIVE_POINTS, 936 gls::DrawTestSpec::PRIMITIVE_TRIANGLES, 937 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN, 938 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP, 939 gls::DrawTestSpec::PRIMITIVE_LINES, 940 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP, 941 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP 942 }; 943 const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights; 944 945 static const gls::DrawTestSpec::DrawMethod drawMethods[] = 946 { 947 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS, 948 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED, 949 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS, 950 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED, 951 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED 952 }; 953 const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights; 954 955 static const gls::DrawTestSpec::IndexType indexTypes[] = 956 { 957 gls::DrawTestSpec::INDEXTYPE_BYTE, 958 gls::DrawTestSpec::INDEXTYPE_SHORT, 959 gls::DrawTestSpec::INDEXTYPE_INT, 960 }; 961 const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights; 962 963 static const gls::DrawTestSpec::Storage storages[] = 964 { 965 gls::DrawTestSpec::STORAGE_USER, 966 gls::DrawTestSpec::STORAGE_BUFFER, 967 }; 968 const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights; 969 970 static const gls::DrawTestSpec::InputType inputTypes[] = 971 { 972 gls::DrawTestSpec::INPUTTYPE_FLOAT, 973 gls::DrawTestSpec::INPUTTYPE_FIXED, 974 gls::DrawTestSpec::INPUTTYPE_BYTE, 975 gls::DrawTestSpec::INPUTTYPE_SHORT, 976 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE, 977 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT, 978 gls::DrawTestSpec::INPUTTYPE_INT, 979 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, 980 gls::DrawTestSpec::INPUTTYPE_HALF, 981 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10, 982 gls::DrawTestSpec::INPUTTYPE_INT_2_10_10_10, 983 }; 984 const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights; 985 986 static const gls::DrawTestSpec::OutputType outputTypes[] = 987 { 988 gls::DrawTestSpec::OUTPUTTYPE_FLOAT, 989 gls::DrawTestSpec::OUTPUTTYPE_VEC2, 990 gls::DrawTestSpec::OUTPUTTYPE_VEC3, 991 gls::DrawTestSpec::OUTPUTTYPE_VEC4, 992 gls::DrawTestSpec::OUTPUTTYPE_INT, 993 gls::DrawTestSpec::OUTPUTTYPE_UINT, 994 gls::DrawTestSpec::OUTPUTTYPE_IVEC2, 995 gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 996 gls::DrawTestSpec::OUTPUTTYPE_IVEC4, 997 gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 998 gls::DrawTestSpec::OUTPUTTYPE_UVEC3, 999 gls::DrawTestSpec::OUTPUTTYPE_UVEC4, 1000 }; 1001 const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights; 1002 1003 static const gls::DrawTestSpec::Usage usages[] = 1004 { 1005 gls::DrawTestSpec::USAGE_DYNAMIC_DRAW, 1006 gls::DrawTestSpec::USAGE_STATIC_DRAW, 1007 gls::DrawTestSpec::USAGE_STREAM_DRAW, 1008 gls::DrawTestSpec::USAGE_STREAM_READ, 1009 gls::DrawTestSpec::USAGE_STREAM_COPY, 1010 gls::DrawTestSpec::USAGE_STATIC_READ, 1011 gls::DrawTestSpec::USAGE_STATIC_COPY, 1012 gls::DrawTestSpec::USAGE_DYNAMIC_READ, 1013 gls::DrawTestSpec::USAGE_DYNAMIC_COPY, 1014 }; 1015 const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights; 1016 1017 static const deUint32 blacklistedCases[]= 1018 { 1019 544, //!< extremely narrow triangle 1020 }; 1021 1022 std::set<deUint32> insertedHashes; 1023 size_t insertedCount = 0; 1024 1025 for (int ndx = 0; ndx < numAttempts; ++ndx) 1026 { 1027 de::Random random(0xc551393 + ndx); // random does not depend on previous cases 1028 1029 int attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights); 1030 gls::DrawTestSpec spec; 1031 1032 spec.apiType = glu::ApiType::es(3,0); 1033 spec.primitive = random.chooseWeighted<gls::DrawTestSpec::Primitive> (DE_ARRAY_BEGIN(primitives), DE_ARRAY_END(primitives), primitiveWeights.weights); 1034 spec.primitiveCount = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(primitiveCounts), DE_ARRAY_END(primitiveCounts), primitiveCountWeights); 1035 spec.drawMethod = random.chooseWeighted<gls::DrawTestSpec::DrawMethod> (DE_ARRAY_BEGIN(drawMethods), DE_ARRAY_END(drawMethods), drawMethodWeights.weights); 1036 spec.indexType = random.chooseWeighted<gls::DrawTestSpec::IndexType> (DE_ARRAY_BEGIN(indexTypes), DE_ARRAY_END(indexTypes), indexTypeWeights.weights); 1037 spec.indexPointerOffset = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexOffsets), DE_ARRAY_END(indexOffsets), indexOffsetWeights); 1038 spec.indexStorage = random.chooseWeighted<gls::DrawTestSpec::Storage> (DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights); 1039 spec.first = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(firsts), DE_ARRAY_END(firsts), firstWeights); 1040 spec.indexMin = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexMins), DE_ARRAY_END(indexMins), indexWeights); 1041 spec.indexMax = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(indexMaxs), DE_ARRAY_END(indexMaxs), indexWeights); 1042 spec.instanceCount = random.chooseWeighted<int, const int*, const float*> (DE_ARRAY_BEGIN(instanceCounts), DE_ARRAY_END(instanceCounts), instanceWeights); 1043 1044 // check spec is legal 1045 if (!spec.valid()) 1046 continue; 1047 1048 for (int attrNdx = 0; attrNdx < attributeCount;) 1049 { 1050 bool valid; 1051 gls::DrawTestSpec::AttributeSpec attribSpec; 1052 1053 attribSpec.inputType = random.chooseWeighted<gls::DrawTestSpec::InputType> (DE_ARRAY_BEGIN(inputTypes), DE_ARRAY_END(inputTypes), inputTypeWeights.weights); 1054 attribSpec.outputType = random.chooseWeighted<gls::DrawTestSpec::OutputType> (DE_ARRAY_BEGIN(outputTypes), DE_ARRAY_END(outputTypes), outputTypeWeights.weights); 1055 attribSpec.storage = random.chooseWeighted<gls::DrawTestSpec::Storage> (DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights); 1056 attribSpec.usage = random.chooseWeighted<gls::DrawTestSpec::Usage> (DE_ARRAY_BEGIN(usages), DE_ARRAY_END(usages), usageWeights.weights); 1057 attribSpec.componentCount = random.getInt(1, 4); 1058 attribSpec.offset = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights); 1059 attribSpec.stride = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights); 1060 attribSpec.normalize = random.getBool(); 1061 attribSpec.instanceDivisor = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(instanceDivisors), DE_ARRAY_END(instanceDivisors), instanceDivisorWeights); 1062 attribSpec.useDefaultAttribute = random.getBool(); 1063 1064 // check spec is legal 1065 valid = attribSpec.valid(spec.apiType); 1066 1067 // we do not want interleaved elements. (Might result in some weird floating point values) 1068 if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride) 1069 valid = false; 1070 1071 // try again if not valid 1072 if (valid) 1073 { 1074 spec.attribs.push_back(attribSpec); 1075 ++attrNdx; 1076 } 1077 } 1078 1079 // Do not collapse all vertex positions to a single positions 1080 if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS) 1081 spec.attribs[0].instanceDivisor = 0; 1082 1083 // Is render result meaningful? 1084 { 1085 // Only one vertex 1086 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS) 1087 continue; 1088 if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS) 1089 continue; 1090 1091 // Triangle only on one axis 1092 if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP) 1093 { 1094 if (spec.attribs[0].componentCount == 1) 1095 continue; 1096 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) 1097 continue; 1098 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2) 1099 continue; 1100 } 1101 } 1102 1103 // Add case 1104 { 1105 deUint32 hash = spec.hash(); 1106 for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx) 1107 hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash(); 1108 1109 if (insertedHashes.find(hash) == insertedHashes.end()) 1110 { 1111 // Only properly aligned and not blacklisted cases 1112 if (spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET && 1113 spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE && 1114 !de::contains(DE_ARRAY_BEGIN(blacklistedCases), DE_ARRAY_END(blacklistedCases), hash)) 1115 { 1116 this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str())); 1117 } 1118 insertedHashes.insert(hash); 1119 1120 ++insertedCount; 1121 } 1122 } 1123 } 1124 } 1125 1126 } // anonymous 1127 1128 DrawTests::DrawTests (Context& context) 1129 : TestCaseGroup(context, "draw", "Drawing tests") 1130 { 1131 } 1132 1133 DrawTests::~DrawTests (void) 1134 { 1135 } 1136 1137 void DrawTests::init (void) 1138 { 1139 // Basic 1140 { 1141 const gls::DrawTestSpec::DrawMethod basicMethods[] = 1142 { 1143 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS, 1144 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS, 1145 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED, 1146 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED, 1147 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED, 1148 }; 1149 1150 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx) 1151 { 1152 const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]); 1153 const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]); 1154 1155 this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx])); 1156 } 1157 } 1158 1159 // extreme instancing 1160 1161 this->addChild(new InstancingGroup(m_context, "instancing", "draw tests with a large instance count.")); 1162 1163 // Random 1164 1165 this->addChild(new RandomGroup(m_context, "random", "random draw commands.")); 1166 } 1167 1168 } // Functional 1169 } // gles3 1170 } // deqp 1171