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