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