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