1 /*------------------------------------------------------------------------- 2 * drawElements Internal Test 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 Miscellaneous framework tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "ditFrameworkTests.hpp" 25 #include "ditTextureFormatTests.hpp" 26 #include "ditAstcTests.hpp" 27 #include "ditVulkanTests.hpp" 28 29 #include "tcuFloatFormat.hpp" 30 #include "tcuEither.hpp" 31 #include "tcuTestLog.hpp" 32 #include "tcuCommandLine.hpp" 33 34 #include "rrRenderer.hpp" 35 #include "tcuTextureUtil.hpp" 36 #include "tcuVectorUtil.hpp" 37 #include "tcuFloat.hpp" 38 39 #include "deRandom.hpp" 40 #include "deArrayUtil.hpp" 41 42 #include <stdexcept> 43 44 namespace dit 45 { 46 47 namespace 48 { 49 50 using std::string; 51 using std::vector; 52 using tcu::TestLog; 53 54 struct MatchCase 55 { 56 enum Expected { NO_MATCH, MATCH_GROUP, MATCH_CASE, EXPECTED_LAST }; 57 58 const char* path; 59 Expected expected; 60 }; 61 62 const char* getMatchCaseExpectedDesc (MatchCase::Expected expected) 63 { 64 static const char* descs[] = 65 { 66 "no match", 67 "group to match", 68 "case to match" 69 }; 70 return de::getSizedArrayElement<MatchCase::EXPECTED_LAST>(descs, expected); 71 } 72 73 class CaseListParserCase : public tcu::TestCase 74 { 75 public: 76 CaseListParserCase (tcu::TestContext& testCtx, const char* name, const char* caseList, const MatchCase* subCases, int numSubCases) 77 : tcu::TestCase (testCtx, name, "") 78 , m_caseList (caseList) 79 , m_subCases (subCases) 80 , m_numSubCases (numSubCases) 81 { 82 } 83 84 IterateResult iterate (void) 85 { 86 TestLog& log = m_testCtx.getLog(); 87 tcu::CommandLine cmdLine; 88 de::MovePtr<tcu::CaseListFilter> caseListFilter; 89 int numPass = 0; 90 91 log << TestLog::Message << "Input:\n\"" << m_caseList << "\"" << TestLog::EndMessage; 92 93 { 94 const char* argv[] = 95 { 96 "deqp", 97 "--deqp-caselist", 98 m_caseList 99 }; 100 101 if (!cmdLine.parse(DE_LENGTH_OF_ARRAY(argv), argv)) 102 TCU_FAIL("Failed to parse command line"); 103 } 104 105 caseListFilter = cmdLine.createCaseListFilter(m_testCtx.getArchive()); 106 107 for (int subCaseNdx = 0; subCaseNdx < m_numSubCases; subCaseNdx++) 108 { 109 const MatchCase& curCase = m_subCases[subCaseNdx]; 110 bool matchGroup; 111 bool matchCase; 112 113 log << TestLog::Message << "Checking \"" << curCase.path << "\"" 114 << ", expecting " << getMatchCaseExpectedDesc(curCase.expected) 115 << TestLog::EndMessage; 116 117 matchGroup = caseListFilter->checkTestGroupName(curCase.path); 118 matchCase = caseListFilter->checkTestCaseName(curCase.path); 119 120 if ((matchGroup == (curCase.expected == MatchCase::MATCH_GROUP)) && 121 (matchCase == (curCase.expected == MatchCase::MATCH_CASE))) 122 { 123 log << TestLog::Message << " pass" << TestLog::EndMessage; 124 numPass += 1; 125 } 126 else 127 log << TestLog::Message << " FAIL!" << TestLog::EndMessage; 128 } 129 130 m_testCtx.setTestResult((numPass == m_numSubCases) ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 131 (numPass == m_numSubCases) ? "All passed" : "Unexpected match result"); 132 133 return STOP; 134 } 135 136 private: 137 const char* const m_caseList; 138 const MatchCase* const m_subCases; 139 const int m_numSubCases; 140 }; 141 142 class NegativeCaseListCase : public tcu::TestCase 143 { 144 public: 145 NegativeCaseListCase (tcu::TestContext& testCtx, const char* name, const char* caseList) 146 : tcu::TestCase (testCtx, name, "") 147 , m_caseList (caseList) 148 { 149 } 150 151 IterateResult iterate (void) 152 { 153 TestLog& log = m_testCtx.getLog(); 154 tcu::CommandLine cmdLine; 155 156 log << TestLog::Message << "Input:\n\"" << m_caseList << "\"" << TestLog::EndMessage; 157 158 { 159 const char* argv[] = 160 { 161 "deqp", 162 "--deqp-caselist", 163 m_caseList 164 }; 165 166 TCU_CHECK(cmdLine.parse(DE_LENGTH_OF_ARRAY(argv), argv)); 167 168 try 169 { 170 de::UniquePtr<tcu::CaseListFilter> filter (cmdLine.createCaseListFilter(m_testCtx.getArchive())); 171 172 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Parsing passed, should have failed"); 173 } 174 catch (const std::invalid_argument& e) 175 { 176 log << TestLog::Message << e.what() << TestLog::EndMessage; 177 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Parsing failed as expected"); 178 } 179 } 180 181 return STOP; 182 } 183 184 private: 185 const char* const m_caseList; 186 }; 187 188 class TrieParserTests : public tcu::TestCaseGroup 189 { 190 public: 191 TrieParserTests (tcu::TestContext& testCtx) 192 : tcu::TestCaseGroup(testCtx, "trie", "Test case trie parser tests") 193 { 194 } 195 196 void init (void) 197 { 198 { 199 static const char* const caseList = "{test}"; 200 static const MatchCase subCases[] = 201 { 202 { "test", MatchCase::MATCH_CASE }, 203 { "test.cd", MatchCase::NO_MATCH }, 204 }; 205 addChild(new CaseListParserCase(m_testCtx, "single_case", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 206 } 207 { 208 static const char* const caseList = "{a{b}}"; 209 static const MatchCase subCases[] = 210 { 211 { "a", MatchCase::MATCH_GROUP }, 212 { "b", MatchCase::NO_MATCH }, 213 { "a.b", MatchCase::MATCH_CASE }, 214 { "a.a", MatchCase::NO_MATCH }, 215 }; 216 addChild(new CaseListParserCase(m_testCtx, "simple_group_1", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 217 } 218 { 219 static const char* const caseList = "{a{b,c}}"; 220 static const MatchCase subCases[] = 221 { 222 { "a", MatchCase::MATCH_GROUP }, 223 { "b", MatchCase::NO_MATCH }, 224 { "a.b", MatchCase::MATCH_CASE }, 225 { "a.a", MatchCase::NO_MATCH }, 226 { "a.c", MatchCase::MATCH_CASE }, 227 }; 228 addChild(new CaseListParserCase(m_testCtx, "simple_group_2", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 229 } 230 { 231 static const char* const caseList = "{a{b},c{d,e}}"; 232 static const MatchCase subCases[] = 233 { 234 { "a", MatchCase::MATCH_GROUP }, 235 { "b", MatchCase::NO_MATCH }, 236 { "a.b", MatchCase::MATCH_CASE }, 237 { "a.c", MatchCase::NO_MATCH }, 238 { "a.d", MatchCase::NO_MATCH }, 239 { "a.e", MatchCase::NO_MATCH }, 240 { "c", MatchCase::MATCH_GROUP }, 241 { "c.b", MatchCase::NO_MATCH }, 242 { "c.d", MatchCase::MATCH_CASE }, 243 { "c.e", MatchCase::MATCH_CASE }, 244 }; 245 addChild(new CaseListParserCase(m_testCtx, "two_groups", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 246 } 247 { 248 static const char* const caseList = "{a,c{d,e}}"; 249 static const MatchCase subCases[] = 250 { 251 { "a", MatchCase::MATCH_CASE }, 252 { "b", MatchCase::NO_MATCH }, 253 { "a.b", MatchCase::NO_MATCH }, 254 { "a.c", MatchCase::NO_MATCH }, 255 { "a.d", MatchCase::NO_MATCH }, 256 { "a.e", MatchCase::NO_MATCH }, 257 { "c", MatchCase::MATCH_GROUP }, 258 { "c.b", MatchCase::NO_MATCH }, 259 { "c.d", MatchCase::MATCH_CASE }, 260 { "c.e", MatchCase::MATCH_CASE }, 261 }; 262 addChild(new CaseListParserCase(m_testCtx, "case_group", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 263 } 264 { 265 static const char* const caseList = "{c{d,e},a}"; 266 static const MatchCase subCases[] = 267 { 268 { "a", MatchCase::MATCH_CASE }, 269 { "b", MatchCase::NO_MATCH }, 270 { "a.b", MatchCase::NO_MATCH }, 271 { "a.c", MatchCase::NO_MATCH }, 272 { "a.d", MatchCase::NO_MATCH }, 273 { "a.e", MatchCase::NO_MATCH }, 274 { "c", MatchCase::MATCH_GROUP }, 275 { "c.b", MatchCase::NO_MATCH }, 276 { "c.d", MatchCase::MATCH_CASE }, 277 { "c.e", MatchCase::MATCH_CASE }, 278 }; 279 addChild(new CaseListParserCase(m_testCtx, "group_case", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 280 } 281 { 282 static const char* const caseList = "{test}\r"; 283 static const MatchCase subCases[] = 284 { 285 { "test", MatchCase::MATCH_CASE }, 286 { "test.cd", MatchCase::NO_MATCH }, 287 }; 288 addChild(new CaseListParserCase(m_testCtx, "trailing_cr", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 289 } 290 { 291 static const char* const caseList = "{test}\n"; 292 static const MatchCase subCases[] = 293 { 294 { "test", MatchCase::MATCH_CASE }, 295 { "test.cd", MatchCase::NO_MATCH }, 296 }; 297 addChild(new CaseListParserCase(m_testCtx, "trailing_lf", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 298 } 299 { 300 static const char* const caseList = "{test}\r\n"; 301 static const MatchCase subCases[] = 302 { 303 { "test", MatchCase::MATCH_CASE }, 304 { "test.cd", MatchCase::NO_MATCH }, 305 }; 306 addChild(new CaseListParserCase(m_testCtx, "trailing_crlf", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 307 } 308 309 // Negative tests 310 addChild(new NegativeCaseListCase(m_testCtx, "empty_string", "")); 311 addChild(new NegativeCaseListCase(m_testCtx, "empty_line", "\n")); 312 addChild(new NegativeCaseListCase(m_testCtx, "empty_root", "{}")); 313 addChild(new NegativeCaseListCase(m_testCtx, "empty_group", "{test{}}")); 314 addChild(new NegativeCaseListCase(m_testCtx, "empty_group_name_1", "{{}}")); 315 addChild(new NegativeCaseListCase(m_testCtx, "empty_group_name_2", "{{test}}")); 316 addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_1", "{")); 317 addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_2", "{test")); 318 addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_3", "{test,")); 319 addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_4", "{test{a}")); 320 addChild(new NegativeCaseListCase(m_testCtx, "unterminated_root_5", "{a,b")); 321 addChild(new NegativeCaseListCase(m_testCtx, "unterminated_group_1", "{test{")); 322 addChild(new NegativeCaseListCase(m_testCtx, "unterminated_group_2", "{test{a")); 323 addChild(new NegativeCaseListCase(m_testCtx, "unterminated_group_3", "{test{a,")); 324 addChild(new NegativeCaseListCase(m_testCtx, "unterminated_group_4", "{test{a,b")); 325 addChild(new NegativeCaseListCase(m_testCtx, "empty_case_name_1", "{a,,b}")); 326 addChild(new NegativeCaseListCase(m_testCtx, "empty_case_name_2", "{,b}")); 327 addChild(new NegativeCaseListCase(m_testCtx, "empty_case_name_3", "{a,}")); 328 addChild(new NegativeCaseListCase(m_testCtx, "no_separator", "{a{b}c}")); 329 addChild(new NegativeCaseListCase(m_testCtx, "invalid_char_1", "{a.b}")); 330 addChild(new NegativeCaseListCase(m_testCtx, "invalid_char_2", "{a[]}")); 331 addChild(new NegativeCaseListCase(m_testCtx, "trailing_char_1", "{a}}")); 332 addChild(new NegativeCaseListCase(m_testCtx, "trailing_char_2", "{a}x")); 333 addChild(new NegativeCaseListCase(m_testCtx, "embedded_newline_1", "{\na}")); 334 addChild(new NegativeCaseListCase(m_testCtx, "embedded_newline_2", "{a\n,b}")); 335 addChild(new NegativeCaseListCase(m_testCtx, "embedded_newline_3", "{a,\nb}")); 336 addChild(new NegativeCaseListCase(m_testCtx, "embedded_newline_4", "{a{b\n}}")); 337 addChild(new NegativeCaseListCase(m_testCtx, "embedded_newline_5", "{a{b}\n}")); 338 } 339 }; 340 341 class ListParserTests : public tcu::TestCaseGroup 342 { 343 public: 344 ListParserTests (tcu::TestContext& testCtx) 345 : tcu::TestCaseGroup(testCtx, "list", "Test case list parser tests") 346 { 347 } 348 349 void init (void) 350 { 351 { 352 static const char* const caseList = "test"; 353 static const MatchCase subCases[] = 354 { 355 { "test", MatchCase::MATCH_CASE }, 356 { "test.cd", MatchCase::NO_MATCH }, 357 }; 358 addChild(new CaseListParserCase(m_testCtx, "single_case", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 359 } 360 { 361 static const char* const caseList = "a.b"; 362 static const MatchCase subCases[] = 363 { 364 { "a", MatchCase::MATCH_GROUP }, 365 { "b", MatchCase::NO_MATCH }, 366 { "a.b", MatchCase::MATCH_CASE }, 367 { "a.a", MatchCase::NO_MATCH }, 368 }; 369 addChild(new CaseListParserCase(m_testCtx, "simple_group_1", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 370 } 371 { 372 static const char* const caseList = "a.b\na.c"; 373 static const MatchCase subCases[] = 374 { 375 { "a", MatchCase::MATCH_GROUP }, 376 { "b", MatchCase::NO_MATCH }, 377 { "a.b", MatchCase::MATCH_CASE }, 378 { "a.a", MatchCase::NO_MATCH }, 379 { "a.c", MatchCase::MATCH_CASE }, 380 }; 381 addChild(new CaseListParserCase(m_testCtx, "simple_group_2", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 382 } 383 { 384 static const char* const caseList = "a.b\na.c"; 385 static const MatchCase subCases[] = 386 { 387 { "a", MatchCase::MATCH_GROUP }, 388 { "b", MatchCase::NO_MATCH }, 389 { "a.b", MatchCase::MATCH_CASE }, 390 { "a.a", MatchCase::NO_MATCH }, 391 { "a.c", MatchCase::MATCH_CASE }, 392 }; 393 addChild(new CaseListParserCase(m_testCtx, "separator_ln", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 394 } 395 { 396 static const char* const caseList = "a.b\ra.c"; 397 static const MatchCase subCases[] = 398 { 399 { "a", MatchCase::MATCH_GROUP }, 400 { "b", MatchCase::NO_MATCH }, 401 { "a.b", MatchCase::MATCH_CASE }, 402 { "a.a", MatchCase::NO_MATCH }, 403 { "a.c", MatchCase::MATCH_CASE }, 404 }; 405 addChild(new CaseListParserCase(m_testCtx, "separator_cr", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 406 } 407 { 408 static const char* const caseList = "a.b\r\na.c"; 409 static const MatchCase subCases[] = 410 { 411 { "a", MatchCase::MATCH_GROUP }, 412 { "b", MatchCase::NO_MATCH }, 413 { "a.b", MatchCase::MATCH_CASE }, 414 { "a.a", MatchCase::NO_MATCH }, 415 { "a.c", MatchCase::MATCH_CASE }, 416 }; 417 addChild(new CaseListParserCase(m_testCtx, "separator_crlf", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 418 } 419 { 420 static const char* const caseList = "a.b\na.c\n"; 421 static const MatchCase subCases[] = 422 { 423 { "a", MatchCase::MATCH_GROUP }, 424 { "b", MatchCase::NO_MATCH }, 425 { "a.b", MatchCase::MATCH_CASE }, 426 { "a.a", MatchCase::NO_MATCH }, 427 { "a.c", MatchCase::MATCH_CASE }, 428 }; 429 addChild(new CaseListParserCase(m_testCtx, "end_ln", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 430 } 431 { 432 static const char* const caseList = "a.b\na.c\r"; 433 static const MatchCase subCases[] = 434 { 435 { "a", MatchCase::MATCH_GROUP }, 436 { "b", MatchCase::NO_MATCH }, 437 { "a.b", MatchCase::MATCH_CASE }, 438 { "a.a", MatchCase::NO_MATCH }, 439 { "a.c", MatchCase::MATCH_CASE }, 440 }; 441 addChild(new CaseListParserCase(m_testCtx, "end_cr", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 442 } 443 { 444 static const char* const caseList = "a.b\na.c\r\n"; 445 static const MatchCase subCases[] = 446 { 447 { "a", MatchCase::MATCH_GROUP }, 448 { "b", MatchCase::NO_MATCH }, 449 { "a.b", MatchCase::MATCH_CASE }, 450 { "a.a", MatchCase::NO_MATCH }, 451 { "a.c", MatchCase::MATCH_CASE }, 452 }; 453 addChild(new CaseListParserCase(m_testCtx, "end_crlf", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 454 } 455 { 456 static const char* const caseList = "a.b\nc.d\nc.e"; 457 static const MatchCase subCases[] = 458 { 459 { "a", MatchCase::MATCH_GROUP }, 460 { "b", MatchCase::NO_MATCH }, 461 { "a.b", MatchCase::MATCH_CASE }, 462 { "a.c", MatchCase::NO_MATCH }, 463 { "a.d", MatchCase::NO_MATCH }, 464 { "a.e", MatchCase::NO_MATCH }, 465 { "c", MatchCase::MATCH_GROUP }, 466 { "c.b", MatchCase::NO_MATCH }, 467 { "c.d", MatchCase::MATCH_CASE }, 468 { "c.e", MatchCase::MATCH_CASE }, 469 }; 470 addChild(new CaseListParserCase(m_testCtx, "two_groups", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 471 } 472 { 473 static const char* const caseList = "a\nc.d\nc.e"; 474 static const MatchCase subCases[] = 475 { 476 { "a", MatchCase::MATCH_CASE }, 477 { "b", MatchCase::NO_MATCH }, 478 { "a.b", MatchCase::NO_MATCH }, 479 { "a.c", MatchCase::NO_MATCH }, 480 { "a.d", MatchCase::NO_MATCH }, 481 { "a.e", MatchCase::NO_MATCH }, 482 { "c", MatchCase::MATCH_GROUP }, 483 { "c.b", MatchCase::NO_MATCH }, 484 { "c.d", MatchCase::MATCH_CASE }, 485 { "c.e", MatchCase::MATCH_CASE }, 486 }; 487 addChild(new CaseListParserCase(m_testCtx, "case_group", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 488 } 489 { 490 static const char* const caseList = "c.d\nc.e\na"; 491 static const MatchCase subCases[] = 492 { 493 { "a", MatchCase::MATCH_CASE }, 494 { "b", MatchCase::NO_MATCH }, 495 { "a.b", MatchCase::NO_MATCH }, 496 { "a.c", MatchCase::NO_MATCH }, 497 { "a.d", MatchCase::NO_MATCH }, 498 { "a.e", MatchCase::NO_MATCH }, 499 { "c", MatchCase::MATCH_GROUP }, 500 { "c.b", MatchCase::NO_MATCH }, 501 { "c.d", MatchCase::MATCH_CASE }, 502 { "c.e", MatchCase::MATCH_CASE }, 503 }; 504 addChild(new CaseListParserCase(m_testCtx, "group_case", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 505 } 506 { 507 static const char* const caseList = "a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.x"; 508 static const MatchCase subCases[] = 509 { 510 { "a", MatchCase::MATCH_GROUP }, 511 { "b", MatchCase::NO_MATCH }, 512 { "a.b", MatchCase::MATCH_GROUP }, 513 { "a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.x", MatchCase::MATCH_CASE }, 514 }; 515 addChild(new CaseListParserCase(m_testCtx, "long_name", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 516 } 517 { 518 static const char* const caseList = 519 "a.b.c.d.e\n" 520 "a.b.c.f\n" 521 "x.y.z\n" 522 "a.b.c.d.g\n" 523 "a.b.c.x\n"; 524 static const MatchCase subCases[] = 525 { 526 { "a", MatchCase::MATCH_GROUP }, 527 { "a.b", MatchCase::MATCH_GROUP }, 528 { "a.b.c.d.e", MatchCase::MATCH_CASE }, 529 { "a.b.c.d.g", MatchCase::MATCH_CASE }, 530 { "x.y", MatchCase::MATCH_GROUP }, 531 { "x.y.z", MatchCase::MATCH_CASE }, 532 { "a.b.c.f", MatchCase::MATCH_CASE }, 533 { "a.b.c.x", MatchCase::MATCH_CASE }, 534 }; 535 addChild(new CaseListParserCase(m_testCtx, "partial_prefix", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 536 } 537 { 538 static const char* const caseList = 539 "a.a.c.d\n" 540 "a.b.c.d\n"; 541 static const MatchCase subCases[] = 542 { 543 { "a", MatchCase::MATCH_GROUP }, 544 { "a.a", MatchCase::MATCH_GROUP }, 545 { "a.b.c.d", MatchCase::MATCH_CASE }, 546 { "a.b.c.d", MatchCase::MATCH_CASE }, 547 }; 548 addChild(new CaseListParserCase(m_testCtx, "reparenting", caseList, subCases, DE_LENGTH_OF_ARRAY(subCases))); 549 } 550 551 // Negative tests 552 addChild(new NegativeCaseListCase(m_testCtx, "empty_string", "")); 553 addChild(new NegativeCaseListCase(m_testCtx, "empty_line", "\n")); 554 addChild(new NegativeCaseListCase(m_testCtx, "empty_group_name", ".test")); 555 addChild(new NegativeCaseListCase(m_testCtx, "empty_case_name", "test.")); 556 } 557 }; 558 559 class CaseListParserTests : public tcu::TestCaseGroup 560 { 561 public: 562 CaseListParserTests (tcu::TestContext& testCtx) 563 : tcu::TestCaseGroup(testCtx, "case_list_parser", "Test case list parser tests") 564 { 565 } 566 567 void init (void) 568 { 569 addChild(new TrieParserTests(m_testCtx)); 570 addChild(new ListParserTests(m_testCtx)); 571 } 572 }; 573 574 inline deUint32 ulpDiff (float a, float b) 575 { 576 const deUint32 ab = tcu::Float32(a).bits(); 577 const deUint32 bb = tcu::Float32(b).bits(); 578 return de::max(ab, bb) - de::min(ab, bb); 579 } 580 581 template<int Size> 582 inline tcu::Vector<deUint32, Size> ulpDiff (const tcu::Vector<float, Size>& a, const tcu::Vector<float, Size>& b) 583 { 584 tcu::Vector<deUint32, Size> res; 585 for (int ndx = 0; ndx < Size; ndx++) 586 res[ndx] = ulpDiff(a[ndx], b[ndx]); 587 return res; 588 } 589 590 class ConstantInterpolationTest : public tcu::TestCase 591 { 592 public: 593 ConstantInterpolationTest (tcu::TestContext& testCtx) 594 : tcu::TestCase(testCtx, "const_interpolation", "Constant value interpolation") 595 { 596 const int supportedMsaaLevels[] = {1, 2, 4, 8, 16}; 597 598 for (int msaaNdx = 0; msaaNdx < DE_LENGTH_OF_ARRAY(supportedMsaaLevels); msaaNdx++) 599 { 600 const int numSamples = supportedMsaaLevels[msaaNdx]; 601 { 602 SubCase c; 603 c.rtSize = tcu::IVec3(128, 128, numSamples); 604 c.vtx[0] = tcu::Vec4(-1.0f, -1.0f, 0.5f, 1.0f); 605 c.vtx[1] = tcu::Vec4(-1.0f, +1.0f, 0.5f, 1.0f); 606 c.vtx[2] = tcu::Vec4(+1.0f, -1.0f, 0.5f, 1.0f); 607 c.varying = tcu::Vec4(0.0f, 1.0f, 8.0f, -8.0f); 608 m_cases.push_back(c); 609 } 610 611 { 612 SubCase c; 613 c.rtSize = tcu::IVec3(128, 128, numSamples); 614 c.vtx[0] = tcu::Vec4(-1.0f, +1.0f, 0.5f, 1.0f); 615 c.vtx[1] = tcu::Vec4(+1.0f, -1.0f, 0.5f, 1.0f); 616 c.vtx[2] = tcu::Vec4(+1.0f, +1.0f, 0.5f, 1.0f); 617 c.varying = tcu::Vec4(0.0f, 1.0f, 8.0f, -8.0f); 618 m_cases.push_back(c); 619 } 620 { 621 SubCase c; 622 c.rtSize = tcu::IVec3(129, 113, numSamples); 623 c.vtx[0] = tcu::Vec4(-1.0f, -1.0f, 0.5f, 1.0f); 624 c.vtx[1] = tcu::Vec4(-1.0f, +1.0f, 0.5f, 1.0f); 625 c.vtx[2] = tcu::Vec4(+1.0f, -1.0f, 0.5f, 1.0f); 626 c.varying = tcu::Vec4(0.0f, 1.0f, 8.0f, -8.0f); 627 m_cases.push_back(c); 628 } 629 { 630 SubCase c; 631 c.rtSize = tcu::IVec3(107, 131, numSamples); 632 c.vtx[0] = tcu::Vec4(-1.0f, +1.0f, 0.5f, 1.0f); 633 c.vtx[1] = tcu::Vec4(+1.0f, -1.0f, 0.5f, 1.0f); 634 c.vtx[2] = tcu::Vec4(+1.0f, +1.0f, 0.5f, 1.0f); 635 c.varying = tcu::Vec4(0.0f, 1.0f, 8.0f, -8.0f); 636 m_cases.push_back(c); 637 } 638 } 639 640 { 641 de::Random rnd(0x89423f); 642 for (int ndx = 0; ndx < 25; ndx++) 643 { 644 const float depth = rnd.getFloat()*2.0f - 1.0f; 645 SubCase c; 646 647 c.rtSize.x() = rnd.getInt(16, 256); 648 c.rtSize.y() = rnd.getInt(16, 256); 649 c.rtSize.z() = rnd.choose<int>(DE_ARRAY_BEGIN(supportedMsaaLevels), DE_ARRAY_END(supportedMsaaLevels)); 650 651 for (int vtxNdx = 0; vtxNdx < DE_LENGTH_OF_ARRAY(c.vtx); vtxNdx++) 652 { 653 c.vtx[vtxNdx].x() = rnd.getFloat()*2.0f - 1.0f; 654 c.vtx[vtxNdx].y() = rnd.getFloat()*2.0f - 1.0f; 655 c.vtx[vtxNdx].z() = depth; 656 c.vtx[vtxNdx].w() = 1.0f; 657 } 658 659 for (int compNdx = 0; compNdx < 4; compNdx++) 660 { 661 float v; 662 do 663 { 664 v = tcu::Float32(rnd.getUint32()).asFloat(); 665 } while (deFloatIsInf(v) || deFloatIsNaN(v)); 666 c.varying[compNdx] = v; 667 } 668 m_cases.push_back(c); 669 } 670 } 671 } 672 673 void init (void) 674 { 675 m_caseIter = m_cases.begin(); 676 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "All iterations passed"); 677 } 678 679 IterateResult iterate (void) 680 { 681 { 682 tcu::ScopedLogSection section(m_testCtx.getLog(), "SubCase", ""); 683 runCase(*m_caseIter); 684 } 685 return (++m_caseIter != m_cases.end()) ? CONTINUE : STOP; 686 } 687 688 protected: 689 struct SubCase 690 { 691 tcu::IVec3 rtSize; // (width, height, samples) 692 tcu::Vec4 vtx[3]; 693 tcu::Vec4 varying; 694 }; 695 696 void runCase (const SubCase& subCase) 697 { 698 using namespace tcu; 699 700 const deUint32 maxColorUlpDiff = 2; 701 const deUint32 maxDepthUlpDiff = 0; 702 703 const int width = subCase.rtSize.x(); 704 const int height = subCase.rtSize.y(); 705 const int numSamples = subCase.rtSize.z(); 706 const float zn = 0.0f; 707 const float zf = 1.0f; 708 709 TextureLevel interpolated (TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT), numSamples, width, height); 710 TextureLevel depthStencil (TextureFormat(TextureFormat::DS, TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV), numSamples, width, height); 711 712 m_testCtx.getLog() << TestLog::Message 713 << "RT size (w, h, #samples) = " << subCase.rtSize << "\n" 714 << "vtx[0] = " << subCase.vtx[0] << "\n" 715 << "vtx[1] = " << subCase.vtx[1] << "\n" 716 << "vtx[2] = " << subCase.vtx[2] << "\n" 717 << "color = " << subCase.varying 718 << TestLog::EndMessage; 719 720 clear (interpolated.getAccess(), subCase.varying - Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 721 clearDepth (depthStencil.getAccess(), 0.0f); 722 clearStencil (depthStencil.getAccess(), 0); 723 724 { 725 class VtxShader : public rr::VertexShader 726 { 727 public: 728 VtxShader (void) 729 : rr::VertexShader(2, 1) 730 { 731 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT; 732 m_inputs[1].type = rr::GENERICVECTYPE_FLOAT; 733 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT; 734 } 735 736 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 737 { 738 for (int packetNdx = 0; packetNdx < numPackets; packetNdx++) 739 { 740 rr::readVertexAttrib(packets[packetNdx]->position, inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx); 741 packets[packetNdx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx); 742 } 743 } 744 } vtxShader; 745 746 class FragShader : public rr::FragmentShader 747 { 748 public: 749 FragShader (void) 750 : rr::FragmentShader(1, 1) 751 { 752 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT; 753 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT; 754 } 755 756 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 757 { 758 for (int packetNdx = 0; packetNdx < numPackets; packetNdx++) 759 { 760 for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; fragNdx++) 761 { 762 const tcu::Vec4 interp = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx); 763 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, interp); 764 } 765 } 766 } 767 } fragShader; 768 769 const rr::Program program (&vtxShader, &fragShader); 770 771 const rr::MultisamplePixelBufferAccess colorAccess = rr::MultisamplePixelBufferAccess::fromMultisampleAccess(interpolated.getAccess()); 772 const rr::MultisamplePixelBufferAccess dsAccess = rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthStencil.getAccess()); 773 const rr::RenderTarget renderTarget (colorAccess, dsAccess, dsAccess); 774 const rr::VertexAttrib vertexAttribs[] = 775 { 776 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, 0, 0, subCase.vtx), 777 rr::VertexAttrib(subCase.varying) 778 }; 779 rr::ViewportState viewport (colorAccess); 780 rr::RenderState state (viewport); 781 const rr::DrawCommand drawCmd (state, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), vertexAttribs, rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, 3, 0)); 782 const rr::Renderer renderer; 783 784 viewport.zn = zn; 785 viewport.zf = zf; 786 787 state.fragOps.depthTestEnabled = true; 788 state.fragOps.depthFunc = rr::TESTFUNC_ALWAYS; 789 state.fragOps.stencilTestEnabled = true; 790 state.fragOps.stencilStates[rr::FACETYPE_BACK].func = rr::TESTFUNC_ALWAYS; 791 state.fragOps.stencilStates[rr::FACETYPE_BACK].dpPass = rr::STENCILOP_INCR; 792 state.fragOps.stencilStates[rr::FACETYPE_FRONT] = state.fragOps.stencilStates[rr::FACETYPE_BACK]; 793 794 renderer.draw(drawCmd); 795 } 796 797 // Verify interpolated values 798 { 799 TextureLevel resolvedColor (interpolated.getFormat(), width, height); // For debugging 800 TextureLevel resolvedDepthStencil (depthStencil.getFormat(), width, height); // For debugging 801 TextureLevel errorMask (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height); 802 const ConstPixelBufferAccess interpAccess = interpolated.getAccess(); 803 const ConstPixelBufferAccess dsAccess = depthStencil.getAccess(); 804 const PixelBufferAccess errorAccess = errorMask.getAccess(); 805 int numCoveredSamples = 0; 806 int numFailedColorSamples = 0; 807 int numFailedDepthSamples = 0; 808 const bool verifyDepth = (subCase.vtx[0].z() == subCase.vtx[1].z()) && 809 (subCase.vtx[1].z() == subCase.vtx[2].z()); 810 const float refDepth = subCase.vtx[0].z()*(zf - zn)/2.0f + (zn + zf)/2.0f; 811 812 rr::resolveMultisampleBuffer(resolvedColor.getAccess(), rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(interpolated.getAccess())); 813 rr::resolveMultisampleBuffer(resolvedDepthStencil.getAccess(), rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(depthStencil.getAccess())); 814 clear(errorAccess, Vec4(0.0f, 1.0f, 0.0f, 1.0f)); 815 816 for (int y = 0; y < height; y++) 817 { 818 for (int x = 0; x < width; x++) 819 { 820 for (int sampleNdx = 0; sampleNdx < numSamples; sampleNdx++) 821 { 822 if (dsAccess.getPixStencil(sampleNdx, x, y) != 0) 823 { 824 const Vec4 color = interpAccess.getPixel(sampleNdx, x, y); 825 const UVec4 colorDiff = ulpDiff(color, subCase.varying); 826 const bool colorOk = boolAll(lessThanEqual(colorDiff, tcu::UVec4(maxColorUlpDiff))); 827 828 const float depth = dsAccess.getPixDepth(sampleNdx, x, y); 829 const deUint32 depthDiff = ulpDiff(depth, refDepth); 830 const bool depthOk = verifyDepth && (depthDiff <= maxDepthUlpDiff); 831 832 const int maxMsgs = 10; 833 834 numCoveredSamples += 1; 835 836 if (!colorOk) 837 { 838 numFailedColorSamples += 1; 839 840 if (numFailedColorSamples <= maxMsgs) 841 m_testCtx.getLog() << TestLog::Message 842 << "FAIL: " << tcu::IVec3(x, y, sampleNdx) 843 << " color ulp diff = " << colorDiff 844 << TestLog::EndMessage; 845 } 846 847 if (!depthOk) 848 numFailedDepthSamples += 1; 849 850 if (!colorOk || !depthOk) 851 errorAccess.setPixel(errorAccess.getPixel(x, y) + Vec4(1.0f, -1.0f, 0.0f, 0.0f) / float(numSamples-1), x, y); 852 } 853 } 854 } 855 } 856 857 m_testCtx.getLog() << TestLog::Image("ResolvedColor", "Resolved colorbuffer", resolvedColor) 858 << TestLog::Image("ResolvedDepthStencil", "Resolved depth- & stencilbuffer", resolvedDepthStencil); 859 860 if (numFailedColorSamples != 0 || numFailedDepthSamples != 0) 861 { 862 m_testCtx.getLog() << TestLog::Image("ErrorMask", "Error mask", errorMask); 863 864 if (numFailedColorSamples != 0) 865 m_testCtx.getLog() << TestLog::Message << "FAIL: Found " << numFailedColorSamples << " invalid color samples!" << TestLog::EndMessage; 866 867 if (numFailedDepthSamples != 0) 868 m_testCtx.getLog() << TestLog::Message << "FAIL: Found " << numFailedDepthSamples << " invalid depth samples!" << TestLog::EndMessage; 869 870 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 871 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid samples found"); 872 } 873 874 m_testCtx.getLog() << TestLog::Message << (numCoveredSamples-numFailedColorSamples) << " / " << numCoveredSamples << " color samples passed" << TestLog::EndMessage; 875 m_testCtx.getLog() << TestLog::Message << (numCoveredSamples-numFailedDepthSamples) << " / " << numCoveredSamples << " depth samples passed" << TestLog::EndMessage; 876 } 877 } 878 879 vector<SubCase> m_cases; 880 vector<SubCase>::const_iterator m_caseIter; 881 }; 882 883 class CommonFrameworkTests : public tcu::TestCaseGroup 884 { 885 public: 886 CommonFrameworkTests (tcu::TestContext& testCtx) 887 : tcu::TestCaseGroup(testCtx, "common", "Tests for the common utility framework") 888 { 889 } 890 891 void init (void) 892 { 893 addChild(new SelfCheckCase(m_testCtx, "float_format","tcu::FloatFormat_selfTest()", 894 tcu::FloatFormat_selfTest)); 895 addChild(new SelfCheckCase(m_testCtx, "either","tcu::Either_selfTest()", 896 tcu::Either_selfTest)); 897 } 898 }; 899 900 class ReferenceRendererTests : public tcu::TestCaseGroup 901 { 902 public: 903 ReferenceRendererTests (tcu::TestContext& testCtx) 904 : tcu::TestCaseGroup(testCtx, "reference_renderer", "Reference renderer tests") 905 { 906 } 907 908 void init (void) 909 { 910 addChild(new ConstantInterpolationTest(m_testCtx)); 911 } 912 }; 913 914 } // anonymous 915 916 FrameworkTests::FrameworkTests (tcu::TestContext& testCtx) 917 : tcu::TestCaseGroup(testCtx, "framework", "Miscellaneous framework tests") 918 { 919 } 920 921 FrameworkTests::~FrameworkTests (void) 922 { 923 } 924 925 void FrameworkTests::init (void) 926 { 927 addChild(new CommonFrameworkTests (m_testCtx)); 928 addChild(new CaseListParserTests (m_testCtx)); 929 addChild(new ReferenceRendererTests (m_testCtx)); 930 addChild(createTextureFormatTests (m_testCtx)); 931 addChild(createAstcTests (m_testCtx)); 932 addChild(createVulkanTests (m_testCtx)); 933 } 934 935 } // dit 936