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