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 Buffer data upload tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es2fBufferWriteTests.hpp" 25 #include "es2fBufferTestUtil.hpp" 26 #include "tcuTestLog.hpp" 27 #include "gluStrUtil.hpp" 28 #include "deMemory.h" 29 #include "deString.h" 30 #include "deRandom.hpp" 31 #include "deStringUtil.hpp" 32 #include "deMath.h" 33 #include "glwEnums.hpp" 34 #include "glwFunctions.hpp" 35 36 #include <algorithm> 37 #include <list> 38 39 using std::set; 40 using std::vector; 41 using std::string; 42 using tcu::TestLog; 43 using tcu::IVec2; 44 45 namespace deqp 46 { 47 namespace gles2 48 { 49 namespace Functional 50 { 51 52 using namespace BufferTestUtil; 53 54 struct DataStoreSpec 55 { 56 DataStoreSpec (void) 57 : target (0) 58 , usage (0) 59 , size (0) 60 { 61 } 62 63 DataStoreSpec (deUint32 target_, deUint32 usage_, int size_) 64 : target (target_) 65 , usage (usage_) 66 , size (size_) 67 { 68 } 69 70 deUint32 target; 71 deUint32 usage; 72 int size; 73 }; 74 75 struct DataStoreSpecVecBuilder 76 { 77 std::vector<DataStoreSpec>& list; 78 79 DataStoreSpecVecBuilder (std::vector<DataStoreSpec>& list_) 80 : list(list_) 81 { 82 } 83 84 DataStoreSpecVecBuilder& operator<< (const DataStoreSpec& spec) 85 { 86 list.push_back(spec); 87 return *this; 88 } 89 }; 90 91 struct RangeVecBuilder 92 { 93 std::vector<tcu::IVec2>& list; 94 95 RangeVecBuilder (std::vector<tcu::IVec2>& list_) 96 : list(list_) 97 { 98 } 99 100 RangeVecBuilder& operator<< (const tcu::IVec2& vec) 101 { 102 list.push_back(vec); 103 return *this; 104 } 105 }; 106 107 template<typename Iterator> 108 static bool isRangeListValid (Iterator begin, Iterator end) 109 { 110 if (begin != end) 111 { 112 // Fetch first. 113 tcu::IVec2 prev = *begin; 114 ++begin; 115 116 for (; begin != end; ++begin) 117 { 118 tcu::IVec2 cur = *begin; 119 if (cur.x() <= prev.x() || cur.x() <= prev.x()+prev.y()) 120 return false; 121 prev = cur; 122 } 123 } 124 125 return true; 126 } 127 128 inline bool rangesIntersect (const tcu::IVec2& a, const tcu::IVec2& b) 129 { 130 return de::inRange(a.x(), b.x(), b.x()+b.y()) || de::inRange(a.x()+a.y(), b.x(), b.x()+b.y()) || 131 de::inRange(b.x(), a.x(), a.x()+a.y()) || de::inRange(b.x()+b.y(), a.x(), a.x()+a.y()); 132 } 133 134 inline tcu::IVec2 unionRanges (const tcu::IVec2& a, const tcu::IVec2& b) 135 { 136 DE_ASSERT(rangesIntersect(a, b)); 137 138 int start = de::min(a.x(), b.x()); 139 int end = de::max(a.x()+a.y(), b.x()+b.y()); 140 141 return tcu::IVec2(start, end-start); 142 } 143 144 //! Updates range list (start, len) with a new range. 145 std::vector<tcu::IVec2> addRangeToList (const std::vector<tcu::IVec2>& oldList, const tcu::IVec2& newRange) 146 { 147 DE_ASSERT(newRange.y() > 0); 148 149 std::vector<tcu::IVec2> newList; 150 std::vector<tcu::IVec2>::const_iterator oldListIter = oldList.begin(); 151 152 // Append ranges that end before the new range. 153 for (; oldListIter != oldList.end() && oldListIter->x()+oldListIter->y() < newRange.x(); ++oldListIter) 154 newList.push_back(*oldListIter); 155 156 // Join any ranges that intersect new range 157 { 158 tcu::IVec2 curRange = newRange; 159 while (oldListIter != oldList.end() && rangesIntersect(curRange, *oldListIter)) 160 { 161 curRange = unionRanges(curRange, *oldListIter); 162 ++oldListIter; 163 } 164 165 newList.push_back(curRange); 166 } 167 168 // Append remaining ranges. 169 for (; oldListIter != oldList.end(); oldListIter++) 170 newList.push_back(*oldListIter); 171 172 DE_ASSERT(isRangeListValid(newList.begin(), newList.end())); 173 174 return newList; 175 } 176 177 class BasicBufferDataCase : public BufferCase 178 { 179 public: 180 BasicBufferDataCase (Context& context, const char* name, const char* desc, deUint32 target, deUint32 usage, int size, VerifyType verify) 181 : BufferCase (context, name, desc) 182 , m_target (target) 183 , m_usage (usage) 184 , m_size (size) 185 , m_verify (verify) 186 { 187 } 188 189 IterateResult iterate (void) 190 { 191 const deUint32 dataSeed = deStringHash(getName()) ^ 0x125; 192 BufferVerifier verifier (m_context, m_verify); 193 ReferenceBuffer refBuf; 194 bool isOk = false; 195 196 refBuf.setSize(m_size); 197 fillWithRandomBytes(refBuf.getPtr(), m_size, dataSeed); 198 199 deUint32 buf = genBuffer(); 200 glBindBuffer(m_target, buf); 201 glBufferData(m_target, m_size, refBuf.getPtr(), m_usage); 202 203 checkError(); 204 205 isOk = verifier.verify(buf, refBuf.getPtr(), 0, m_size); 206 207 deleteBuffer(buf); 208 209 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 210 isOk ? "Pass" : "Buffer verification failed"); 211 return STOP; 212 } 213 214 private: 215 deUint32 m_target; 216 deUint32 m_usage; 217 int m_size; 218 VerifyType m_verify; 219 }; 220 221 class RecreateBufferDataStoreCase : public BufferCase 222 { 223 public: 224 RecreateBufferDataStoreCase (Context& context, const char* name, const char* desc, const DataStoreSpec* specs, int numSpecs, VerifyType verify) 225 : BufferCase(context, name, desc) 226 , m_specs (specs, specs+numSpecs) 227 , m_verify (verify) 228 { 229 } 230 231 IterateResult iterate (void) 232 { 233 const deUint32 baseSeed = deStringHash(getName()) ^ 0xbeef; 234 BufferVerifier verifier (m_context, m_verify); 235 ReferenceBuffer refBuf; 236 const deUint32 buf = genBuffer(); 237 238 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 239 240 for (vector<DataStoreSpec>::const_iterator spec = m_specs.begin(); spec != m_specs.end(); spec++) 241 { 242 bool iterOk = false; 243 244 refBuf.setSize(spec->size); 245 fillWithRandomBytes(refBuf.getPtr(), spec->size, baseSeed ^ deInt32Hash(spec->size+spec->target+spec->usage)); 246 247 glBindBuffer(spec->target, buf); 248 glBufferData(spec->target, spec->size, refBuf.getPtr(), spec->usage); 249 250 checkError(); 251 252 iterOk = verifier.verify(buf, refBuf.getPtr(), 0, spec->size); 253 254 if (!iterOk) 255 { 256 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 257 break; 258 } 259 } 260 261 deleteBuffer(buf); 262 return STOP; 263 } 264 265 private: 266 std::vector<DataStoreSpec> m_specs; 267 VerifyType m_verify; 268 }; 269 270 class BasicBufferSubDataCase : public BufferCase 271 { 272 public: 273 BasicBufferSubDataCase (Context& context, const char* name, const char* desc, deUint32 target, deUint32 usage, int size, int subDataOffs, int subDataSize, VerifyType verify) 274 : BufferCase (context, name, desc) 275 , m_target (target) 276 , m_usage (usage) 277 , m_size (size) 278 , m_subDataOffs (subDataOffs) 279 , m_subDataSize (subDataSize) 280 , m_verify (verify) 281 { 282 DE_ASSERT(de::inBounds(subDataOffs, 0, size) && de::inRange(subDataOffs+subDataSize, 0, size)); 283 } 284 285 IterateResult iterate (void) 286 { 287 const deUint32 dataSeed = deStringHash(getName()); 288 BufferVerifier verifier (m_context, m_verify); 289 ReferenceBuffer refBuf; 290 bool isOk = false; 291 292 refBuf.setSize(m_size); 293 294 deUint32 buf = genBuffer(); 295 glBindBuffer(m_target, buf); 296 297 // Initialize with glBufferData() 298 fillWithRandomBytes(refBuf.getPtr(), m_size, dataSeed ^ 0x80354f); 299 glBufferData(m_target, m_size, refBuf.getPtr(), m_usage); 300 checkError(); 301 302 // Re-specify part of buffer 303 fillWithRandomBytes(refBuf.getPtr()+m_subDataOffs, m_subDataSize, dataSeed ^ 0xfac425c); 304 glBufferSubData(m_target, m_subDataOffs, m_subDataSize, refBuf.getPtr()+m_subDataOffs); 305 306 isOk = verifier.verify(buf, refBuf.getPtr(), 0, m_size); 307 308 deleteBuffer(buf); 309 310 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 311 isOk ? "Pass" : "Buffer verification failed"); 312 return STOP; 313 } 314 315 private: 316 deUint32 m_target; 317 deUint32 m_usage; 318 int m_size; 319 int m_subDataOffs; 320 int m_subDataSize; 321 VerifyType m_verify; 322 }; 323 324 class SubDataToUndefinedCase : public BufferCase 325 { 326 public: 327 SubDataToUndefinedCase (Context& context, const char* name, const char* desc, deUint32 target, deUint32 usage, int size, const tcu::IVec2* ranges, int numRanges, VerifyType verify) 328 : BufferCase (context, name, desc) 329 , m_target (target) 330 , m_usage (usage) 331 , m_size (size) 332 , m_ranges (ranges, ranges+numRanges) 333 , m_verify (verify) 334 { 335 } 336 337 IterateResult iterate (void) 338 { 339 const deUint32 dataSeed = deStringHash(getName()); 340 BufferVerifier verifier (m_context, m_verify); 341 ReferenceBuffer refBuf; 342 bool isOk = true; 343 std::vector<tcu::IVec2> definedRanges; 344 345 refBuf.setSize(m_size); 346 347 deUint32 buf = genBuffer(); 348 glBindBuffer(m_target, buf); 349 350 // Initialize storage with glBufferData() 351 glBufferData(m_target, m_size, DE_NULL, m_usage); 352 checkError(); 353 354 // Fill specified ranges with glBufferSubData() 355 for (vector<tcu::IVec2>::const_iterator range = m_ranges.begin(); range != m_ranges.end(); range++) 356 { 357 fillWithRandomBytes(refBuf.getPtr()+range->x(), range->y(), dataSeed ^ deInt32Hash(range->x()+range->y())); 358 glBufferSubData(m_target, range->x(), range->y(), refBuf.getPtr()+range->x()); 359 360 // Mark range as defined 361 definedRanges = addRangeToList(definedRanges, *range); 362 } 363 364 // Verify defined parts 365 for (vector<tcu::IVec2>::const_iterator range = definedRanges.begin(); range != definedRanges.end(); range++) 366 { 367 if (!verifier.verify(buf, refBuf.getPtr(), range->x(), range->y())) 368 isOk = false; 369 } 370 371 deleteBuffer(buf); 372 373 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 374 isOk ? "Pass" : "Buffer verification failed"); 375 return STOP; 376 } 377 378 private: 379 deUint32 m_target; 380 deUint32 m_usage; 381 int m_size; 382 std::vector<tcu::IVec2> m_ranges; 383 VerifyType m_verify; 384 }; 385 386 class RandomBufferWriteCase : public BufferCase 387 { 388 public: 389 RandomBufferWriteCase (Context& context, const char* name, const char* desc, deUint32 seed) 390 : BufferCase(context, name, desc) 391 , m_seed (seed) 392 , m_verifier (DE_NULL) 393 , m_buffer (0) 394 , m_curSize (0) 395 , m_iterNdx (0) 396 { 397 } 398 399 ~RandomBufferWriteCase (void) 400 { 401 delete m_verifier; 402 } 403 404 void init (void) 405 { 406 BufferCase::init(); 407 408 m_iterNdx = 0; 409 m_buffer = genBuffer(); 410 m_curSize = 0; 411 m_verifier = new BufferVerifier(m_context, VERIFY_AS_VERTEX_ARRAY); 412 413 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 414 } 415 416 void deinit (void) 417 { 418 deleteBuffer(m_buffer); 419 m_refBuffer.setSize(0); 420 421 delete m_verifier; 422 m_verifier = DE_NULL; 423 424 BufferCase::deinit(); 425 } 426 427 IterateResult iterate (void) 428 { 429 // Parameters. 430 const int numIterations = 5; 431 const int uploadsPerIteration = 7; 432 const int minSize = 12; 433 const int maxSize = 32*1024; 434 const float respecifyProbability = 0.07f; 435 const float respecifyDataProbability = 0.2f; 436 437 static const deUint32 bufferTargets[] = 438 { 439 GL_ARRAY_BUFFER, 440 GL_ELEMENT_ARRAY_BUFFER 441 }; 442 443 static const deUint32 usageHints[] = 444 { 445 GL_STREAM_DRAW, 446 GL_STATIC_DRAW, 447 GL_DYNAMIC_DRAW, 448 }; 449 450 bool iterOk = true; 451 deUint32 curBoundTarget = GL_NONE; 452 de::Random rnd (m_seed ^ deInt32Hash(m_iterNdx) ^ 0xacf92e); 453 454 m_testCtx.getLog() << TestLog::Section(string("Iteration") + de::toString(m_iterNdx+1), string("Iteration ") + de::toString(m_iterNdx+1) + " / " + de::toString(numIterations)); 455 456 for (int uploadNdx = 0; uploadNdx < uploadsPerIteration; uploadNdx++) 457 { 458 const deUint32 target = bufferTargets[rnd.getInt(0, DE_LENGTH_OF_ARRAY(bufferTargets)-1)]; 459 const bool respecify = m_curSize == 0 || rnd.getFloat() < respecifyProbability; 460 461 if (target != curBoundTarget) 462 { 463 glBindBuffer(target, m_buffer); 464 curBoundTarget = target; 465 } 466 467 if (respecify) 468 { 469 const int size = rnd.getInt(minSize, maxSize); 470 const deUint32 hint = usageHints[rnd.getInt(0, DE_LENGTH_OF_ARRAY(usageHints)-1)]; 471 const bool fillWithData = rnd.getFloat() < respecifyDataProbability; 472 473 m_refBuffer.setSize(size); 474 if (fillWithData) 475 fillWithRandomBytes(m_refBuffer.getPtr(), size, rnd.getUint32()); 476 477 glBufferData(target, size, fillWithData ? m_refBuffer.getPtr() : DE_NULL, hint); 478 479 m_validRanges.clear(); 480 if (fillWithData) 481 m_validRanges.push_back(tcu::IVec2(0, size)); 482 483 m_curSize = size; 484 } 485 else 486 { 487 // \note Non-uniform size distribution. 488 const int size = de::clamp(deRoundFloatToInt32((float)m_curSize * deFloatPow(rnd.getFloat(0.0f, 0.7f), 3.0f)), minSize, m_curSize); 489 const int offset = rnd.getInt(0, m_curSize-size); 490 491 fillWithRandomBytes(m_refBuffer.getPtr()+offset, size, rnd.getUint32()); 492 glBufferSubData(target, offset, size, m_refBuffer.getPtr()+offset); 493 494 m_validRanges = addRangeToList(m_validRanges, tcu::IVec2(offset, size)); 495 } 496 } 497 498 // Check error. 499 { 500 deUint32 err = glGetError(); 501 if (err != GL_NO_ERROR) 502 throw tcu::TestError(string("Got ") + glu::getErrorStr(err).toString()); 503 } 504 505 // Verify valid ranges. 506 for (vector<IVec2>::const_iterator range = m_validRanges.begin(); range != m_validRanges.end(); range++) 507 { 508 if (!m_verifier->verify(m_buffer, m_refBuffer.getPtr(), range->x(), range->y())) 509 { 510 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer verification failed"); 511 iterOk = false; 512 break; 513 } 514 } 515 516 m_testCtx.getLog() << TestLog::EndSection; 517 518 DE_ASSERT(iterOk || m_testCtx.getTestResult() != QP_TEST_RESULT_PASS); 519 520 m_iterNdx += 1; 521 return (iterOk && m_iterNdx < numIterations) ? CONTINUE : STOP; 522 } 523 524 private: 525 deUint32 m_seed; 526 527 BufferVerifier* m_verifier; 528 deUint32 m_buffer; 529 ReferenceBuffer m_refBuffer; 530 std::vector<tcu::IVec2> m_validRanges; 531 int m_curSize; 532 int m_iterNdx; 533 }; 534 535 BufferWriteTests::BufferWriteTests (Context& context) 536 : TestCaseGroup(context, "write", "Buffer data upload tests") 537 { 538 } 539 540 BufferWriteTests::~BufferWriteTests (void) 541 { 542 } 543 544 void BufferWriteTests::init (void) 545 { 546 static const deUint32 bufferTargets[] = 547 { 548 GL_ARRAY_BUFFER, 549 GL_ELEMENT_ARRAY_BUFFER 550 }; 551 552 static const deUint32 usageHints[] = 553 { 554 GL_STREAM_DRAW, 555 GL_STATIC_DRAW, 556 GL_DYNAMIC_DRAW 557 }; 558 559 static const struct 560 { 561 const char* name; 562 VerifyType verify; 563 } verifyTypes[] = 564 { 565 { "vertex_array", VERIFY_AS_VERTEX_ARRAY }, 566 { "index_array", VERIFY_AS_INDEX_ARRAY } 567 }; 568 569 // .basic 570 { 571 tcu::TestCaseGroup* const basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic upload with glBufferData()"); 572 addChild(basicGroup); 573 574 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++) 575 { 576 for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usageHints); usageNdx++) 577 { 578 const deUint32 target = bufferTargets[targetNdx]; 579 const deUint32 usage = usageHints[usageNdx]; 580 const int size = 1020; 581 const VerifyType verify = VERIFY_AS_VERTEX_ARRAY; 582 const string name = string(getBufferTargetName(target)) + "_" + getUsageHintName(usage); 583 584 basicGroup->addChild(new BasicBufferDataCase(m_context, name.c_str(), "", target, usage, size, verify)); 585 } 586 } 587 } 588 589 // .use 590 { 591 tcu::TestCaseGroup* const useGroup = new tcu::TestCaseGroup(m_testCtx, "use", "Buffer uses"); 592 addChild(useGroup); 593 594 for (int verifyNdx = 0; verifyNdx < DE_LENGTH_OF_ARRAY(verifyTypes); verifyNdx++) 595 { 596 tcu::TestCaseGroup* const verifyGroup = new tcu::TestCaseGroup(m_testCtx, verifyTypes[verifyNdx].name, ""); 597 useGroup->addChild(verifyGroup); 598 599 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++) 600 { 601 const deUint32 target = bufferTargets[targetNdx]; 602 const deUint32 usage = GL_STATIC_DRAW; 603 const int size = 763; 604 const VerifyType verify = verifyTypes[verifyNdx].verify; 605 const string name = getBufferTargetName(target); 606 607 verifyGroup->addChild(new BasicBufferDataCase(m_context, name.c_str(), "", target, usage, size, verify)); 608 } 609 } 610 } 611 612 // .recreate_store 613 { 614 tcu::TestCaseGroup* const recreateStoreGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_store", "Data store recreate using glBufferData()"); 615 addChild(recreateStoreGroup); 616 617 #define RECREATE_STORE_CASE(NAME, DESC, SPECLIST) \ 618 do { \ 619 std::vector<DataStoreSpec> specs; \ 620 DataStoreSpecVecBuilder builder(specs); \ 621 builder SPECLIST; \ 622 recreateStoreGroup->addChild(new RecreateBufferDataStoreCase(m_context, #NAME, DESC, &specs[0], (int)specs.size(), VERIFY_AS_VERTEX_ARRAY)); \ 623 } while (deGetFalse()) 624 625 RECREATE_STORE_CASE(identical_1, "Recreate with identical parameters", 626 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996) 627 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996) 628 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996)); 629 630 RECREATE_STORE_CASE(identical_2, "Recreate with identical parameters", 631 << DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 72) 632 << DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 72) 633 << DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 72)); 634 635 RECREATE_STORE_CASE(different_target_1, "Recreate with different target", 636 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 504) 637 << DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 504)); 638 639 RECREATE_STORE_CASE(different_target_2, "Recreate with different target", 640 << DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 716) 641 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 716) 642 << DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 716)); 643 644 RECREATE_STORE_CASE(different_usage, "Recreate with different usage", 645 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW, 1644) 646 << DataStoreSpec(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, 1644) 647 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 1644) 648 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW, 1644)); 649 650 RECREATE_STORE_CASE(different_size, "Recreate with different size", 651 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW, 1024) 652 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW, 12) 653 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW, 3327) 654 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW, 92) 655 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW, 12379) 656 << DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW, 571)); 657 658 #undef RECREATE_STORE_CASE 659 660 // Random cases. 661 { 662 const int numRandomCases = 4; 663 const int numUploadsPerCase = 10; 664 const int minSize = 12; 665 const int maxSize = 65536; 666 const VerifyType verify = VERIFY_AS_VERTEX_ARRAY; 667 de::Random rnd (23921); 668 669 for (int caseNdx = 0; caseNdx < numRandomCases; caseNdx++) 670 { 671 vector<DataStoreSpec> specs(numUploadsPerCase); 672 673 for (vector<DataStoreSpec>::iterator spec = specs.begin(); spec != specs.end(); spec++) 674 { 675 spec->target = bufferTargets[rnd.getInt(0, DE_LENGTH_OF_ARRAY(bufferTargets)-1)]; 676 spec->usage = usageHints[rnd.getInt(0, DE_LENGTH_OF_ARRAY(usageHints)-1)]; 677 spec->size = rnd.getInt(minSize, maxSize); 678 } 679 680 recreateStoreGroup->addChild(new RecreateBufferDataStoreCase(m_context, (string("random_") + de::toString(caseNdx+1)).c_str(), "", &specs[0], (int)specs.size(), verify)); 681 } 682 } 683 } 684 685 // .basic_subdata 686 { 687 tcu::TestCaseGroup* const basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic_subdata", "Basic glBufferSubData() usage"); 688 addChild(basicGroup); 689 690 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++) 691 { 692 for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usageHints); usageNdx++) 693 { 694 const deUint32 target = bufferTargets[targetNdx]; 695 const deUint32 usage = usageHints[usageNdx]; 696 const int size = 1020; 697 const VerifyType verify = VERIFY_AS_VERTEX_ARRAY; 698 const string name = string(getBufferTargetName(target)) + "_" + getUsageHintName(usage); 699 700 basicGroup->addChild(new BasicBufferDataCase(m_context, name.c_str(), "", target, usage, size, verify)); 701 } 702 } 703 } 704 705 // .partial_specify 706 { 707 tcu::TestCaseGroup* const partialSpecifyGroup = new tcu::TestCaseGroup(m_testCtx, "partial_specify", "Partial buffer data specification with glBufferSubData()"); 708 addChild(partialSpecifyGroup); 709 710 #define PARTIAL_SPECIFY_CASE(NAME, DESC, TARGET, USAGE, SIZE, RANGELIST) \ 711 do { \ 712 std::vector<tcu::IVec2> ranges; \ 713 RangeVecBuilder builder(ranges); \ 714 builder RANGELIST; \ 715 partialSpecifyGroup->addChild(new SubDataToUndefinedCase(m_context, #NAME, DESC, TARGET, USAGE, SIZE, &ranges[0], (int)ranges.size(), VERIFY_AS_VERTEX_ARRAY)); \ 716 } while (deGetFalse()) 717 718 PARTIAL_SPECIFY_CASE(whole_1, "Whole buffer specification with single glBufferSubData()", GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996, 719 << IVec2(0, 996)); 720 PARTIAL_SPECIFY_CASE(whole_2, "Whole buffer specification with two calls", GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, 1728, 721 << IVec2(729, 999) 722 << IVec2(0, 729)); 723 PARTIAL_SPECIFY_CASE(whole_3, "Whole buffer specification with three calls", GL_ARRAY_BUFFER, GL_STREAM_DRAW, 1944, 724 << IVec2(0, 421) 725 << IVec2(1421, 523) 726 << IVec2(421, 1000)); 727 PARTIAL_SPECIFY_CASE(whole_4, "Whole buffer specification with three calls", GL_ELEMENT_ARRAY_BUFFER, GL_STREAM_DRAW, 1200, 728 << IVec2(0, 500) 729 << IVec2(429, 200) 730 << IVec2(513, 687)); 731 732 PARTIAL_SPECIFY_CASE(low_1, "Low part of buffer specified with single call", GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 1000, 733 << IVec2(0, 513)); 734 PARTIAL_SPECIFY_CASE(low_2, "Low part of buffer specified with two calls", GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996, 735 << IVec2(0, 98) 736 << IVec2(98, 511)); 737 PARTIAL_SPECIFY_CASE(low_3, "Low part of buffer specified with two calls", GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, 1200, 738 << IVec2(0, 591) 739 << IVec2(371, 400)); 740 741 PARTIAL_SPECIFY_CASE(high_1, "High part of buffer specified with single call", GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 1000, 742 << IVec2(500, 500)); 743 PARTIAL_SPECIFY_CASE(high_2, "High part of buffer specified with two calls", GL_ARRAY_BUFFER, GL_STREAM_DRAW, 1200, 744 << IVec2(600, 123) 745 << IVec2(723, 477)); 746 PARTIAL_SPECIFY_CASE(high_3, "High part of buffer specified with two calls", GL_ARRAY_BUFFER, GL_STREAM_DRAW, 1200, 747 << IVec2(600, 200) 748 << IVec2(601, 599)); 749 750 PARTIAL_SPECIFY_CASE(middle_1, "Middle part of buffer specified with single call", GL_ELEMENT_ARRAY_BUFFER, GL_STREAM_DRAW, 2500, 751 << IVec2(1000, 799)); 752 PARTIAL_SPECIFY_CASE(middle_2, "Middle part of buffer specified with two calls", GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 2500, 753 << IVec2(780, 220) 754 << IVec2(1000, 500)); 755 PARTIAL_SPECIFY_CASE(middle_3, "Middle part of buffer specified with two calls", GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, 2500, 756 << IVec2(780, 321) 757 << IVec2(1000, 501)); 758 759 #undef PARTIAL_SPECIFY_CASE 760 } 761 762 // .random 763 { 764 tcu::TestCaseGroup* const randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Randomized buffer data cases"); 765 addChild(randomGroup); 766 767 for (int i = 0; i < 10; i++) 768 randomGroup->addChild(new RandomBufferWriteCase(m_context, de::toString(i).c_str(), "", deInt32Hash(i))); 769 } 770 } 771 772 } // Functional 773 } // gles2 774 } // deqp 775