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