xref: /aosp_15_r20/external/deqp/modules/internal/ditFrameworkTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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