GetDevices: Also allow `\.` to be part of the host name
[platform/upstream/VK-GL-CTS.git] / modules / glshared / glsShaderLibrary.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL (ES) 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 Compiler test case.
22  *//*--------------------------------------------------------------------*/
23
24 #include "glsShaderLibrary.hpp"
25 #include "glsShaderLibraryCase.hpp"
26 #include "gluShaderUtil.hpp"
27 #include "tcuResource.hpp"
28 #include "glwEnums.hpp"
29
30 #include "deInt32.h"
31
32 #include <string>
33 #include <vector>
34 #include <fstream>
35 #include <sstream>
36
37 #include <string.h>
38 #include <stdarg.h>
39 #include <stdlib.h>
40
41 using std::string;
42 using std::vector;
43 using std::ostringstream;
44
45 using namespace glu;
46
47 #if 0
48 #       define PARSE_DBG(X) printf X
49 #else
50 #       define PARSE_DBG(X) DE_NULL_STATEMENT
51 #endif
52
53 namespace deqp
54 {
55 namespace gls
56 {
57 namespace sl
58 {
59
60 static const glu::GLSLVersion DEFAULT_GLSL_VERSION = glu::GLSL_VERSION_100_ES;
61
62 DE_INLINE deBool isWhitespace (char c)
63 {
64         return (c == ' ') || (c == '\t') || (c == '\r') || (c == '\n');
65 }
66
67 DE_INLINE deBool isEOL (char c)
68 {
69         return (c == '\r') || (c == '\n');
70 }
71
72 DE_INLINE deBool isNumeric (char c)
73 {
74         return deInRange32(c, '0', '9');
75 }
76
77 DE_INLINE deBool isAlpha (char c)
78 {
79         return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z');
80 }
81
82 DE_INLINE deBool isCaseNameChar (char c)
83 {
84         return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z') || deInRange32(c, '0', '9') || (c == '_') || (c == '-') || (c == '.');
85 }
86
87 // \todo [2011-02-11 pyry] Should not depend on Context or TestContext!
88 class ShaderParser
89 {
90 public:
91                                                         ShaderParser                    (tcu::TestContext& testCtx, RenderContext& renderCtx, const glu::ContextInfo& contextInfo, const char* currentDir = DE_NULL);
92                                                         ~ShaderParser                   (void);
93
94         vector<tcu::TestNode*>  parse                                   (const char* input);
95
96 private:
97         enum Token
98         {
99                 TOKEN_INVALID = 0,
100                 TOKEN_EOF,
101                 TOKEN_STRING,
102                 TOKEN_SHADER_SOURCE,
103
104                 TOKEN_INT_LITERAL,
105                 TOKEN_FLOAT_LITERAL,
106
107                 // identifiers
108                 TOKEN_IDENTIFIER,
109                 TOKEN_TRUE,
110                 TOKEN_FALSE,
111                 TOKEN_DESC,
112                 TOKEN_EXPECT,
113                 TOKEN_GROUP,
114                 TOKEN_CASE,
115                 TOKEN_END,
116                 TOKEN_VALUES,
117                 TOKEN_BOTH,
118                 TOKEN_VERTEX,
119                 TOKEN_FRAGMENT,
120                 TOKEN_UNIFORM,
121                 TOKEN_INPUT,
122                 TOKEN_OUTPUT,
123                 TOKEN_FLOAT,
124                 TOKEN_FLOAT_VEC2,
125                 TOKEN_FLOAT_VEC3,
126                 TOKEN_FLOAT_VEC4,
127                 TOKEN_FLOAT_MAT2,
128                 TOKEN_FLOAT_MAT2X3,
129                 TOKEN_FLOAT_MAT2X4,
130                 TOKEN_FLOAT_MAT3X2,
131                 TOKEN_FLOAT_MAT3,
132                 TOKEN_FLOAT_MAT3X4,
133                 TOKEN_FLOAT_MAT4X2,
134                 TOKEN_FLOAT_MAT4X3,
135                 TOKEN_FLOAT_MAT4,
136                 TOKEN_INT,
137                 TOKEN_INT_VEC2,
138                 TOKEN_INT_VEC3,
139                 TOKEN_INT_VEC4,
140                 TOKEN_UINT,
141                 TOKEN_UINT_VEC2,
142                 TOKEN_UINT_VEC3,
143                 TOKEN_UINT_VEC4,
144                 TOKEN_BOOL,
145                 TOKEN_BOOL_VEC2,
146                 TOKEN_BOOL_VEC3,
147                 TOKEN_BOOL_VEC4,
148                 TOKEN_VERSION,
149                 TOKEN_TESSELLATION_CONTROL,
150                 TOKEN_TESSELLATION_EVALUATION,
151                 TOKEN_GEOMETRY,
152                 TOKEN_REQUIRE,
153                 TOKEN_IN,
154                 TOKEN_IMPORT,
155                 TOKEN_PIPELINE_PROGRAM,
156                 TOKEN_ACTIVE_STAGES,
157
158                 // symbols
159                 TOKEN_ASSIGN,
160                 TOKEN_PLUS,
161                 TOKEN_MINUS,
162                 TOKEN_COMMA,
163                 TOKEN_VERTICAL_BAR,
164                 TOKEN_SEMI_COLON,
165                 TOKEN_LEFT_PAREN,
166                 TOKEN_RIGHT_PAREN,
167                 TOKEN_LEFT_BRACKET,
168                 TOKEN_RIGHT_BRACKET,
169                 TOKEN_LEFT_BRACE,
170                 TOKEN_RIGHT_BRACE,
171                 TOKEN_GREATER,
172
173                 TOKEN_LAST
174         };
175
176         void                                            parseError                                      (const std::string& errorStr);
177         float                                           parseFloatLiteral                       (const char* str);
178         int                                                     parseIntLiteral                         (const char* str);
179         string                                          parseStringLiteral                      (const char* str);
180         string                                          parseShaderSource                       (const char* str);
181         void                                            advanceToken                            (void);
182         void                                            advanceToken                            (Token assumed);
183         void                                            assumeToken                                     (Token token);
184         DataType                                        mapDataTypeToken                        (Token token);
185         const char*                                     getTokenName                            (Token token);
186         deUint32                                        getShaderStageLiteralFlag       (void);
187         deUint32                                        getGLEnumFromName                       (const std::string& enumName);
188
189         void                                            parseValueElement                       (DataType dataType, ShaderCase::Value& result);
190         void                                            parseValue                                      (ShaderCase::ValueBlock& valueBlock);
191         void                                            parseValueBlock                         (ShaderCase::ValueBlock& valueBlock);
192         deUint32                                        parseShaderStageList            (void);
193         void                                            parseRequirement                        (ShaderCase::CaseRequirement& valueBlock);
194         void                                            parseExpectResult                       (ShaderCase::ExpectResult& expectResult);
195         void                                            parseGLSLVersion                        (glu::GLSLVersion& version);
196         void                                            parsePipelineProgram            (ShaderCase::PipelineProgram& program);
197         void                                            parseShaderCase                         (vector<tcu::TestNode*>& shaderNodeList);
198         void                                            parseShaderGroup                        (vector<tcu::TestNode*>& shaderNodeList);
199         void                                            parseImport                                     (vector<tcu::TestNode*>& shaderNodeList);
200
201         // Member variables.
202         tcu::TestContext&                       m_testCtx;
203         RenderContext&                          m_renderCtx;
204         const glu::ContextInfo&         m_contextInfo;
205         std::string                                     m_input;
206         const char*                                     m_curPtr;
207         Token                                           m_curToken;
208         std::string                                     m_curTokenStr;
209         const char* const                       m_currentDir;
210 };
211
212 ShaderParser::ShaderParser (tcu::TestContext& testCtx, RenderContext& renderCtx, const glu::ContextInfo& contextInfo, const char* currentDir)
213         : m_testCtx                     (testCtx)
214         , m_renderCtx           (renderCtx)
215         , m_contextInfo         (contextInfo)
216         , m_curPtr                      (DE_NULL)
217         , m_curToken            (TOKEN_LAST)
218         , m_currentDir          (currentDir)
219 {
220 }
221
222 ShaderParser::~ShaderParser (void)
223 {
224         // nada
225 }
226
227 void ShaderParser::parseError (const std::string& errorStr)
228 {
229         string atStr = string(m_curPtr, 80);
230         throw tcu::InternalError((string("Parser error: ") + errorStr + " near '" + atStr + " ...'").c_str(), "", __FILE__, __LINE__);
231 }
232
233 float ShaderParser::parseFloatLiteral (const char* str)
234 {
235         return (float)atof(str);
236 }
237
238 int ShaderParser::parseIntLiteral (const char* str)
239 {
240         return atoi(str);
241 }
242
243 string ShaderParser::parseStringLiteral (const char* str)
244 {
245         const char*             p               = str;
246         char                    endChar = *p++;
247         ostringstream   o;
248
249         while (*p != endChar && *p)
250         {
251                 if (*p == '\\')
252                 {
253                         switch (p[1])
254                         {
255                                 case 0:         DE_ASSERT(DE_FALSE);    break;
256                                 case 'n':       o << '\n';                              break;
257                                 case 't':       o << '\t';                              break;
258                                 default:        o << p[1];                              break;
259                         }
260
261                         p += 2;
262                 }
263                 else
264                         o << *p++;
265         }
266
267         return o.str();
268 }
269
270 static string removeExtraIndentation (const string& source)
271 {
272         // Detect indentation from first line.
273         int numIndentChars = 0;
274         for (int ndx = 0; ndx < (int)source.length() && isWhitespace(source[ndx]); ndx++)
275                 numIndentChars += source[ndx] == '\t' ? 4 : 1;
276
277         // Process all lines and remove preceding indentation.
278         ostringstream processed;
279         {
280                 bool    atLineStart                     = true;
281                 int             indentCharsOmitted      = 0;
282
283                 for (int pos = 0; pos < (int)source.length(); pos++)
284                 {
285                         char c = source[pos];
286
287                         if (atLineStart && indentCharsOmitted < numIndentChars && (c == ' ' || c == '\t'))
288                         {
289                                 indentCharsOmitted += c == '\t' ? 4 : 1;
290                         }
291                         else if (isEOL(c))
292                         {
293                                 if (source[pos] == '\r' && source[pos+1] == '\n')
294                                 {
295                                         pos += 1;
296                                         processed << '\n';
297                                 }
298                                 else
299                                         processed << c;
300
301                                 atLineStart                     = true;
302                                 indentCharsOmitted      = 0;
303                         }
304                         else
305                         {
306                                 processed << c;
307                                 atLineStart = false;
308                         }
309                 }
310         }
311
312         return processed.str();
313 }
314
315 string ShaderParser::parseShaderSource (const char* str)
316 {
317         const char*             p = str+2;
318         ostringstream   o;
319
320         // Eat first empty line from beginning.
321         while (*p == ' ') p++;
322         if (*p == '\r') p++;
323         if (*p == '\n') p++;
324
325         while ((p[0] != '"') || (p[1] != '"'))
326         {
327                 if (*p == '\\')
328                 {
329                         switch (p[1])
330                         {
331                                 case 0:         DE_ASSERT(DE_FALSE);    break;
332                                 case 'n':       o << '\n';                              break;
333                                 case 't':       o << '\t';                              break;
334                                 default:        o << p[1];                              break;
335                         }
336
337                         p += 2;
338                 }
339                 else
340                         o << *p++;
341         }
342
343         return removeExtraIndentation(o.str());
344 }
345
346 void ShaderParser::advanceToken (void)
347 {
348         // Skip old token.
349         m_curPtr += m_curTokenStr.length();
350
351         // Reset token (for safety).
352         m_curToken              = TOKEN_INVALID;
353         m_curTokenStr   = "";
354
355         // Eat whitespace & comments while they last.
356         for (;;)
357         {
358                 while (isWhitespace(*m_curPtr))
359                         m_curPtr++;
360
361                 // Check for EOL comment.
362                 if (*m_curPtr == '#')
363                 {
364                         while (*m_curPtr && !isEOL(*m_curPtr))
365                                 m_curPtr++;
366                 }
367                 else
368                         break;
369         }
370
371         if (!*m_curPtr)
372         {
373                 m_curToken = TOKEN_EOF;
374                 m_curTokenStr = "<EOF>";
375         }
376         else if (isAlpha(*m_curPtr))
377         {
378                 struct Named
379                 {
380                         const char*             str;
381                         Token                   token;
382                 };
383
384                 static const Named s_named[] =
385                 {
386                         { "true",                                               TOKEN_TRUE                                              },
387                         { "false",                                              TOKEN_FALSE                                             },
388                         { "desc",                                               TOKEN_DESC                                              },
389                         { "expect",                                             TOKEN_EXPECT                                    },
390                         { "group",                                              TOKEN_GROUP                                             },
391                         { "case",                                               TOKEN_CASE                                              },
392                         { "end",                                                TOKEN_END                                               },
393                         { "values",                                             TOKEN_VALUES                                    },
394                         { "both",                                               TOKEN_BOTH                                              },
395                         { "vertex",                                             TOKEN_VERTEX                                    },
396                         { "fragment",                                   TOKEN_FRAGMENT                                  },
397                         { "uniform",                                    TOKEN_UNIFORM                                   },
398                         { "input",                                              TOKEN_INPUT                                             },
399                         { "output",                                             TOKEN_OUTPUT                                    },
400                         { "float",                                              TOKEN_FLOAT                                             },
401                         { "vec2",                                               TOKEN_FLOAT_VEC2                                },
402                         { "vec3",                                               TOKEN_FLOAT_VEC3                                },
403                         { "vec4",                                               TOKEN_FLOAT_VEC4                                },
404                         { "mat2",                                               TOKEN_FLOAT_MAT2                                },
405                         { "mat2x3",                                             TOKEN_FLOAT_MAT2X3                              },
406                         { "mat2x4",                                             TOKEN_FLOAT_MAT2X4                              },
407                         { "mat3x2",                                             TOKEN_FLOAT_MAT3X2                              },
408                         { "mat3",                                               TOKEN_FLOAT_MAT3                                },
409                         { "mat3x4",                                             TOKEN_FLOAT_MAT3X4                              },
410                         { "mat4x2",                                             TOKEN_FLOAT_MAT4X2                              },
411                         { "mat4x3",                                             TOKEN_FLOAT_MAT4X3                              },
412                         { "mat4",                                               TOKEN_FLOAT_MAT4                                },
413                         { "int",                                                TOKEN_INT                                               },
414                         { "ivec2",                                              TOKEN_INT_VEC2                                  },
415                         { "ivec3",                                              TOKEN_INT_VEC3                                  },
416                         { "ivec4",                                              TOKEN_INT_VEC4                                  },
417                         { "uint",                                               TOKEN_UINT                                              },
418                         { "uvec2",                                              TOKEN_UINT_VEC2                                 },
419                         { "uvec3",                                              TOKEN_UINT_VEC3                                 },
420                         { "uvec4",                                              TOKEN_UINT_VEC4                                 },
421                         { "bool",                                               TOKEN_BOOL                                              },
422                         { "bvec2",                                              TOKEN_BOOL_VEC2                                 },
423                         { "bvec3",                                              TOKEN_BOOL_VEC3                                 },
424                         { "bvec4",                                              TOKEN_BOOL_VEC4                                 },
425                         { "version",                                    TOKEN_VERSION                                   },
426                         { "tessellation_control",               TOKEN_TESSELLATION_CONTROL              },
427                         { "tessellation_evaluation",    TOKEN_TESSELLATION_EVALUATION   },
428                         { "geometry",                                   TOKEN_GEOMETRY                                  },
429                         { "require",                                    TOKEN_REQUIRE                                   },
430                         { "in",                                                 TOKEN_IN                                                },
431                         { "import",                                             TOKEN_IMPORT                                    },
432                         { "pipeline_program",                   TOKEN_PIPELINE_PROGRAM                  },
433                         { "active_stages",                              TOKEN_ACTIVE_STAGES                             },
434                 };
435
436                 const char* end = m_curPtr + 1;
437                 while (isCaseNameChar(*end))
438                         end++;
439                 m_curTokenStr = string(m_curPtr, end - m_curPtr);
440
441                 m_curToken = TOKEN_IDENTIFIER;
442
443                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_named); ndx++)
444                 {
445                         if (m_curTokenStr == s_named[ndx].str)
446                         {
447                                 m_curToken = s_named[ndx].token;
448                                 break;
449                         }
450                 }
451         }
452         else if (isNumeric(*m_curPtr))
453         {
454                 /* \todo [2010-03-31 petri] Hex? */
455                 const char* p = m_curPtr;
456                 while (isNumeric(*p))
457                         p++;
458                 if (*p == '.')
459                 {
460                         p++;
461                         while (isNumeric(*p))
462                                 p++;
463
464                         if (*p == 'e' || *p == 'E')
465                         {
466                                 p++;
467                                 if (*p == '+' || *p == '-')
468                                         p++;
469                                 DE_ASSERT(isNumeric(*p));
470                                 while (isNumeric(*p))
471                                         p++;
472                         }
473
474                         m_curToken = TOKEN_FLOAT_LITERAL;
475                         m_curTokenStr = string(m_curPtr, p - m_curPtr);
476                 }
477                 else
478                 {
479                         m_curToken = TOKEN_INT_LITERAL;
480                         m_curTokenStr = string(m_curPtr, p - m_curPtr);
481                 }
482         }
483         else if (*m_curPtr == '"' && m_curPtr[1] == '"')
484         {
485                 const char*     p = m_curPtr + 2;
486
487                 while ((p[0] != '"') || (p[1] != '"'))
488                 {
489                         DE_ASSERT(*p);
490                         if (*p == '\\')
491                         {
492                                 DE_ASSERT(p[1] != 0);
493                                 p += 2;
494                         }
495                         else
496                                 p++;
497                 }
498                 p += 2;
499
500                 m_curToken              = TOKEN_SHADER_SOURCE;
501                 m_curTokenStr   = string(m_curPtr, (int)(p - m_curPtr));
502         }
503         else if (*m_curPtr == '"' || *m_curPtr == '\'')
504         {
505                 char            endChar = *m_curPtr;
506                 const char*     p               = m_curPtr + 1;
507
508                 while (*p != endChar)
509                 {
510                         DE_ASSERT(*p);
511                         if (*p == '\\')
512                         {
513                                 DE_ASSERT(p[1] != 0);
514                                 p += 2;
515                         }
516                         else
517                                 p++;
518                 }
519                 p++;
520
521                 m_curToken              = TOKEN_STRING;
522                 m_curTokenStr   = string(m_curPtr, (int)(p - m_curPtr));
523         }
524         else
525         {
526                 struct SimpleToken
527                 {
528                         const char*             str;
529                         Token                   token;
530                 };
531
532                 static const SimpleToken s_simple[] =
533                 {
534                         { "=",                  TOKEN_ASSIGN            },
535                         { "+",                  TOKEN_PLUS                      },
536                         { "-",                  TOKEN_MINUS                     },
537                         { ",",                  TOKEN_COMMA                     },
538                         { "|",                  TOKEN_VERTICAL_BAR      },
539                         { ";",                  TOKEN_SEMI_COLON        },
540                         { "(",                  TOKEN_LEFT_PAREN        },
541                         { ")",                  TOKEN_RIGHT_PAREN       },
542                         { "[",                  TOKEN_LEFT_BRACKET      },
543                         { "]",                  TOKEN_RIGHT_BRACKET },
544                         { "{",                  TOKEN_LEFT_BRACE        },
545                         { "}",                  TOKEN_RIGHT_BRACE       },
546                         { ">",                  TOKEN_GREATER           },
547                 };
548
549                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_simple); ndx++)
550                 {
551                         if (strncmp(s_simple[ndx].str, m_curPtr, strlen(s_simple[ndx].str)) == 0)
552                         {
553                                 m_curToken              = s_simple[ndx].token;
554                                 m_curTokenStr   = s_simple[ndx].str;
555                                 return;
556                         }
557                 }
558
559                 // Otherwise invalid token.
560                 m_curToken = TOKEN_INVALID;
561                 m_curTokenStr = *m_curPtr;
562         }
563 }
564
565 void ShaderParser::advanceToken (Token assumed)
566 {
567         assumeToken(assumed);
568         advanceToken();
569 }
570
571 void ShaderParser::assumeToken (Token token)
572 {
573         if (m_curToken != token)
574                 parseError((string("unexpected token '") + m_curTokenStr + "', expecting '" + getTokenName(token) + "'").c_str());
575         DE_TEST_ASSERT(m_curToken == token);
576 }
577
578 DataType ShaderParser::mapDataTypeToken (Token token)
579 {
580         switch (token)
581         {
582                 case TOKEN_FLOAT:                       return TYPE_FLOAT;
583                 case TOKEN_FLOAT_VEC2:          return TYPE_FLOAT_VEC2;
584                 case TOKEN_FLOAT_VEC3:          return TYPE_FLOAT_VEC3;
585                 case TOKEN_FLOAT_VEC4:          return TYPE_FLOAT_VEC4;
586                 case TOKEN_FLOAT_MAT2:          return TYPE_FLOAT_MAT2;
587                 case TOKEN_FLOAT_MAT2X3:        return TYPE_FLOAT_MAT2X3;
588                 case TOKEN_FLOAT_MAT2X4:        return TYPE_FLOAT_MAT2X4;
589                 case TOKEN_FLOAT_MAT3X2:        return TYPE_FLOAT_MAT3X2;
590                 case TOKEN_FLOAT_MAT3:          return TYPE_FLOAT_MAT3;
591                 case TOKEN_FLOAT_MAT3X4:        return TYPE_FLOAT_MAT3X4;
592                 case TOKEN_FLOAT_MAT4X2:        return TYPE_FLOAT_MAT4X2;
593                 case TOKEN_FLOAT_MAT4X3:        return TYPE_FLOAT_MAT4X3;
594                 case TOKEN_FLOAT_MAT4:          return TYPE_FLOAT_MAT4;
595                 case TOKEN_INT:                         return TYPE_INT;
596                 case TOKEN_INT_VEC2:            return TYPE_INT_VEC2;
597                 case TOKEN_INT_VEC3:            return TYPE_INT_VEC3;
598                 case TOKEN_INT_VEC4:            return TYPE_INT_VEC4;
599                 case TOKEN_UINT:                        return TYPE_UINT;
600                 case TOKEN_UINT_VEC2:           return TYPE_UINT_VEC2;
601                 case TOKEN_UINT_VEC3:           return TYPE_UINT_VEC3;
602                 case TOKEN_UINT_VEC4:           return TYPE_UINT_VEC4;
603                 case TOKEN_BOOL:                        return TYPE_BOOL;
604                 case TOKEN_BOOL_VEC2:           return TYPE_BOOL_VEC2;
605                 case TOKEN_BOOL_VEC3:           return TYPE_BOOL_VEC3;
606                 case TOKEN_BOOL_VEC4:           return TYPE_BOOL_VEC4;
607                 default:                                        return TYPE_INVALID;
608         }
609 }
610
611 const char* ShaderParser::getTokenName (Token token)
612 {
613         switch (token)
614         {
615                 case TOKEN_INVALID:                                     return "<invalid>";
616                 case TOKEN_EOF:                                         return "<eof>";
617                 case TOKEN_STRING:                                      return "<string>";
618                 case TOKEN_SHADER_SOURCE:                       return "source";
619
620                 case TOKEN_INT_LITERAL:                         return "<int>";
621                 case TOKEN_FLOAT_LITERAL:                       return "<float>";
622
623                 // identifiers
624                 case TOKEN_IDENTIFIER:                          return "<identifier>";
625                 case TOKEN_TRUE:                                        return "true";
626                 case TOKEN_FALSE:                                       return "false";
627                 case TOKEN_DESC:                                        return "desc";
628                 case TOKEN_EXPECT:                                      return "expect";
629                 case TOKEN_GROUP:                                       return "group";
630                 case TOKEN_CASE:                                        return "case";
631                 case TOKEN_END:                                         return "end";
632                 case TOKEN_VALUES:                                      return "values";
633                 case TOKEN_BOTH:                                        return "both";
634                 case TOKEN_VERTEX:                                      return "vertex";
635                 case TOKEN_FRAGMENT:                            return "fragment";
636                 case TOKEN_TESSELLATION_CONTROL:        return "tessellation_control";
637                 case TOKEN_TESSELLATION_EVALUATION:     return "tessellation_evaluation";
638                 case TOKEN_GEOMETRY:                            return "geometry";
639                 case TOKEN_REQUIRE:                                     return "require";
640                 case TOKEN_UNIFORM:                                     return "uniform";
641                 case TOKEN_INPUT:                                       return "input";
642                 case TOKEN_OUTPUT:                                      return "output";
643                 case TOKEN_FLOAT:                                       return "float";
644                 case TOKEN_FLOAT_VEC2:                          return "vec2";
645                 case TOKEN_FLOAT_VEC3:                          return "vec3";
646                 case TOKEN_FLOAT_VEC4:                          return "vec4";
647                 case TOKEN_FLOAT_MAT2:                          return "mat2";
648                 case TOKEN_FLOAT_MAT2X3:                        return "mat2x3";
649                 case TOKEN_FLOAT_MAT2X4:                        return "mat2x4";
650                 case TOKEN_FLOAT_MAT3X2:                        return "mat3x2";
651                 case TOKEN_FLOAT_MAT3:                          return "mat3";
652                 case TOKEN_FLOAT_MAT3X4:                        return "mat3x4";
653                 case TOKEN_FLOAT_MAT4X2:                        return "mat4x2";
654                 case TOKEN_FLOAT_MAT4X3:                        return "mat4x3";
655                 case TOKEN_FLOAT_MAT4:                          return "mat4";
656                 case TOKEN_INT:                                         return "int";
657                 case TOKEN_INT_VEC2:                            return "ivec2";
658                 case TOKEN_INT_VEC3:                            return "ivec3";
659                 case TOKEN_INT_VEC4:                            return "ivec4";
660                 case TOKEN_UINT:                                        return "uint";
661                 case TOKEN_UINT_VEC2:                           return "uvec2";
662                 case TOKEN_UINT_VEC3:                           return "uvec3";
663                 case TOKEN_UINT_VEC4:                           return "uvec4";
664                 case TOKEN_BOOL:                                        return "bool";
665                 case TOKEN_BOOL_VEC2:                           return "bvec2";
666                 case TOKEN_BOOL_VEC3:                           return "bvec3";
667                 case TOKEN_BOOL_VEC4:                           return "bvec4";
668                 case TOKEN_IN:                                          return "in";
669                 case TOKEN_IMPORT:                                      return "import";
670                 case TOKEN_PIPELINE_PROGRAM:            return "pipeline_program";
671                 case TOKEN_ACTIVE_STAGES:                       return "active_stages";
672
673                 case TOKEN_ASSIGN:                                      return "=";
674                 case TOKEN_PLUS:                                        return "+";
675                 case TOKEN_MINUS:                                       return "-";
676                 case TOKEN_COMMA:                                       return ",";
677                 case TOKEN_VERTICAL_BAR:                        return "|";
678                 case TOKEN_SEMI_COLON:                          return ";";
679                 case TOKEN_LEFT_PAREN:                          return "(";
680                 case TOKEN_RIGHT_PAREN:                         return ")";
681                 case TOKEN_LEFT_BRACKET:                        return "[";
682                 case TOKEN_RIGHT_BRACKET:                       return "]";
683                 case TOKEN_LEFT_BRACE:                          return "{";
684                 case TOKEN_RIGHT_BRACE:                         return "}";
685                 case TOKEN_GREATER:                                     return ">";
686
687                 default:                                                        return "<unknown>";
688         }
689 }
690
691 deUint32 ShaderParser::getShaderStageLiteralFlag (void)
692 {
693         switch (m_curToken)
694         {
695                 case TOKEN_VERTEX:                                      return (1 << glu::SHADERTYPE_VERTEX);
696                 case TOKEN_FRAGMENT:                            return (1 << glu::SHADERTYPE_FRAGMENT);
697                 case TOKEN_GEOMETRY:                            return (1 << glu::SHADERTYPE_GEOMETRY);
698                 case TOKEN_TESSELLATION_CONTROL:        return (1 << glu::SHADERTYPE_TESSELLATION_CONTROL);
699                 case TOKEN_TESSELLATION_EVALUATION:     return (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION);
700
701                 default:
702                         parseError(std::string() + "invalid shader stage name, got " + m_curTokenStr);
703                         return 0;
704         }
705 }
706
707 deUint32 ShaderParser::getGLEnumFromName (const std::string& enumName)
708 {
709         static const struct
710         {
711                 const char*     name;
712                 deUint32        value;
713         } names[] =
714         {
715                 { "GL_MAX_VERTEX_IMAGE_UNIFORMS",                       GL_MAX_VERTEX_IMAGE_UNIFORMS                    },
716                 { "GL_MAX_VERTEX_ATOMIC_COUNTERS",                      GL_MAX_VERTEX_ATOMIC_COUNTERS                   },
717                 { "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS",        GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS             },
718                 { "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS",      GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS   },
719         };
720
721         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(names); ++ndx)
722                 if (names[ndx].name == enumName)
723                         return names[ndx].value;
724
725         parseError(std::string() + "unknown enum name, got " + enumName);
726         return 0;
727 }
728
729 void ShaderParser::parseValueElement (DataType expectedDataType, ShaderCase::Value& result)
730 {
731         DataType        scalarType      = getDataTypeScalarType(expectedDataType);
732         int                     scalarSize      = getDataTypeScalarSize(expectedDataType);
733
734         /* \todo [2010-04-19 petri] Support arrays. */
735         ShaderCase::Value::Element elems[16];
736
737         if (scalarSize > 1)
738         {
739                 DE_ASSERT(mapDataTypeToken(m_curToken) == expectedDataType);
740                 advanceToken(); // data type (float, vec2, etc.)
741                 advanceToken(TOKEN_LEFT_PAREN);
742         }
743
744         for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
745         {
746                 if (scalarType == TYPE_FLOAT)
747                 {
748                         float signMult = 1.0f;
749                         if (m_curToken == TOKEN_MINUS)
750                         {
751                                 signMult = -1.0f;
752                                 advanceToken();
753                         }
754
755                         assumeToken(TOKEN_FLOAT_LITERAL);
756                         elems[scalarNdx].float32 = signMult * parseFloatLiteral(m_curTokenStr.c_str());
757                         advanceToken(TOKEN_FLOAT_LITERAL);
758                 }
759                 else if (scalarType == TYPE_INT || scalarType == TYPE_UINT)
760                 {
761                         int signMult = 1;
762                         if (m_curToken == TOKEN_MINUS)
763                         {
764                                 signMult = -1;
765                                 advanceToken();
766                         }
767
768                         assumeToken(TOKEN_INT_LITERAL);
769                         elems[scalarNdx].int32 = signMult * parseIntLiteral(m_curTokenStr.c_str());
770                         advanceToken(TOKEN_INT_LITERAL);
771                 }
772                 else
773                 {
774                         DE_ASSERT(scalarType == TYPE_BOOL);
775                         elems[scalarNdx].bool32 = (m_curToken == TOKEN_TRUE);
776                         if (m_curToken != TOKEN_TRUE && m_curToken != TOKEN_FALSE)
777                                 parseError(string("unexpected token, expecting bool: " + m_curTokenStr));
778                         advanceToken(); // true/false
779                 }
780
781                 if (scalarNdx != (scalarSize - 1))
782                         advanceToken(TOKEN_COMMA);
783         }
784
785         if (scalarSize > 1)
786                 advanceToken(TOKEN_RIGHT_PAREN);
787
788         // Store results.
789         for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
790                 result.elements.push_back(elems[scalarNdx]);
791 }
792
793 void ShaderParser::parseValue (ShaderCase::ValueBlock& valueBlock)
794 {
795         PARSE_DBG(("      parseValue()\n"));
796
797         // Parsed results.
798         ShaderCase::Value result;
799
800         // Parse storage.
801         if (m_curToken == TOKEN_UNIFORM)
802                 result.storageType = ShaderCase::Value::STORAGE_UNIFORM;
803         else if (m_curToken == TOKEN_INPUT)
804                 result.storageType = ShaderCase::Value::STORAGE_INPUT;
805         else if (m_curToken == TOKEN_OUTPUT)
806                 result.storageType = ShaderCase::Value::STORAGE_OUTPUT;
807         else
808                 parseError(string("unexpected token encountered when parsing value classifier"));
809         advanceToken();
810
811         // Parse data type.
812         result.dataType = mapDataTypeToken(m_curToken);
813         if (result.dataType == TYPE_INVALID)
814                 parseError(string("unexpected token when parsing value data type: " + m_curTokenStr));
815         advanceToken();
816
817         // Parse value name.
818         if (m_curToken == TOKEN_IDENTIFIER || m_curToken == TOKEN_STRING)
819         {
820                 if (m_curToken == TOKEN_IDENTIFIER)
821                         result.valueName = m_curTokenStr;
822                 else
823                         result.valueName = parseStringLiteral(m_curTokenStr.c_str());
824         }
825         else
826                 parseError(string("unexpected token when parsing value name: " + m_curTokenStr));
827         advanceToken();
828
829         // Parse assignment operator.
830         advanceToken(TOKEN_ASSIGN);
831
832         // Parse actual value.
833         if (m_curToken == TOKEN_LEFT_BRACKET) // value list
834         {
835                 advanceToken(TOKEN_LEFT_BRACKET);
836                 result.arrayLength = 0;
837
838                 for (;;)
839                 {
840                         parseValueElement(result.dataType, result);
841                         result.arrayLength++;
842
843                         if (m_curToken == TOKEN_RIGHT_BRACKET)
844                                 break;
845                         else if (m_curToken == TOKEN_VERTICAL_BAR)
846                         {
847                                 advanceToken();
848                                 continue;
849                         }
850                         else
851                                 parseError(string("unexpected token in value element array: " + m_curTokenStr));
852                 }
853
854                 advanceToken(TOKEN_RIGHT_BRACKET);
855         }
856         else // arrays, single elements
857         {
858                 parseValueElement(result.dataType, result);
859                 result.arrayLength = 1;
860         }
861
862         advanceToken(TOKEN_SEMI_COLON); // end of declaration
863
864         valueBlock.values.push_back(result);
865 }
866
867 void ShaderParser::parseValueBlock (ShaderCase::ValueBlock& valueBlock)
868 {
869         PARSE_DBG(("    parseValueBlock()\n"));
870         advanceToken(TOKEN_VALUES);
871         advanceToken(TOKEN_LEFT_BRACE);
872
873         for (;;)
874         {
875                 if (m_curToken == TOKEN_UNIFORM || m_curToken == TOKEN_INPUT || m_curToken == TOKEN_OUTPUT)
876                         parseValue(valueBlock);
877                 else if (m_curToken == TOKEN_RIGHT_BRACE)
878                         break;
879                 else
880                         parseError(string("unexpected token when parsing a value block: " + m_curTokenStr));
881         }
882
883         advanceToken(TOKEN_RIGHT_BRACE);
884
885         // Compute combined array length of value block.
886         int arrayLength = 1;
887         for (int valueNdx = 0; valueNdx < (int)valueBlock.values.size(); valueNdx++)
888         {
889                 const ShaderCase::Value& val = valueBlock.values[valueNdx];
890                 if (val.arrayLength > 1)
891                 {
892                         DE_ASSERT(arrayLength == 1 || arrayLength == val.arrayLength);
893                         arrayLength = val.arrayLength;
894                 }
895         }
896         valueBlock.arrayLength = arrayLength;
897 }
898
899 deUint32 ShaderParser::parseShaderStageList (void)
900 {
901         deUint32 mask = 0;
902
903         assumeToken(TOKEN_LEFT_BRACE);
904
905         // don't allow 0-sized lists
906         advanceToken();
907         mask |= getShaderStageLiteralFlag();
908         advanceToken();
909
910         for (;;)
911         {
912                 if (m_curToken == TOKEN_RIGHT_BRACE)
913                         break;
914                 else if (m_curToken == TOKEN_COMMA)
915                 {
916                         deUint32 stageFlag;
917                         advanceToken();
918
919                         stageFlag = getShaderStageLiteralFlag();
920                         if (stageFlag & mask)
921                                 parseError(string("stage already set in the shader stage set: " + m_curTokenStr));
922
923                         mask |= stageFlag;
924                         advanceToken();
925                 }
926                 else
927                         parseError(string("invalid shader stage set token: " + m_curTokenStr));
928         }
929         advanceToken(TOKEN_RIGHT_BRACE);
930
931         return mask;
932 }
933
934 void ShaderParser::parseRequirement (ShaderCase::CaseRequirement& valueBlock)
935 {
936         PARSE_DBG(("    parseRequirement()\n"));
937
938         advanceToken();
939         assumeToken(TOKEN_IDENTIFIER);
940
941         if (m_curTokenStr == "extension")
942         {
943                 std::vector<std::string>        anyExtensionStringList;
944                 deUint32                                        affectedCasesFlags              = -1; // by default all stages
945
946                 advanceToken();
947                 assumeToken(TOKEN_LEFT_BRACE);
948
949                 advanceToken();
950                 assumeToken(TOKEN_STRING);
951
952                 anyExtensionStringList.push_back(parseStringLiteral(m_curTokenStr.c_str()));
953                 advanceToken();
954
955                 for (;;)
956                 {
957                         if (m_curToken == TOKEN_RIGHT_BRACE)
958                                 break;
959                         else if (m_curToken == TOKEN_VERTICAL_BAR)
960                         {
961                                 advanceToken();
962                                 assumeToken(TOKEN_STRING);
963
964                                 anyExtensionStringList.push_back(parseStringLiteral(m_curTokenStr.c_str()));
965                                 advanceToken();
966                         }
967                         else
968                                 parseError(string("invalid extension list token: " + m_curTokenStr));
969                 }
970                 advanceToken(TOKEN_RIGHT_BRACE);
971
972                 if (m_curToken == TOKEN_IN)
973                 {
974                         advanceToken();
975                         affectedCasesFlags = parseShaderStageList();
976                 }
977
978                 valueBlock = ShaderCase::CaseRequirement::createAnyExtensionRequirement(anyExtensionStringList, affectedCasesFlags);
979         }
980         else if (m_curTokenStr == "limit")
981         {
982                 deUint32        limitEnum;
983                 int                     limitValue;
984
985                 advanceToken();
986
987                 assumeToken(TOKEN_STRING);
988                 limitEnum = getGLEnumFromName(parseStringLiteral(m_curTokenStr.c_str()));
989                 advanceToken();
990
991                 assumeToken(TOKEN_GREATER);
992                 advanceToken();
993
994                 assumeToken(TOKEN_INT_LITERAL);
995                 limitValue = parseIntLiteral(m_curTokenStr.c_str());
996                 advanceToken();
997
998                 valueBlock = ShaderCase::CaseRequirement::createLimitRequirement(limitEnum, limitValue);
999         }
1000         else if (m_curTokenStr == "full_glsl_es_100_support")
1001         {
1002                 advanceToken();
1003
1004                 valueBlock = ShaderCase::CaseRequirement::createFullGLSLES100SpecificationRequirement();
1005         }
1006         else
1007                 parseError(string("invalid requirement value: " + m_curTokenStr));
1008 }
1009
1010 void ShaderParser::parseExpectResult (ShaderCase::ExpectResult& expectResult)
1011 {
1012         assumeToken(TOKEN_IDENTIFIER);
1013
1014         if (m_curTokenStr == "pass")
1015                 expectResult = ShaderCase::EXPECT_PASS;
1016         else if (m_curTokenStr == "compile_fail")
1017                 expectResult = ShaderCase::EXPECT_COMPILE_FAIL;
1018         else if (m_curTokenStr == "link_fail")
1019                 expectResult = ShaderCase::EXPECT_LINK_FAIL;
1020         else if (m_curTokenStr == "compile_or_link_fail")
1021                 expectResult = ShaderCase::EXPECT_COMPILE_LINK_FAIL;
1022         else if (m_curTokenStr == "validation_fail")
1023                 expectResult = ShaderCase::EXPECT_VALIDATION_FAIL;
1024         else if (m_curTokenStr == "build_successful")
1025                 expectResult = ShaderCase::EXPECT_BUILD_SUCCESSFUL;
1026         else
1027                 parseError(string("invalid expected result value: " + m_curTokenStr));
1028
1029         advanceToken();
1030 }
1031
1032 void ShaderParser::parseGLSLVersion (glu::GLSLVersion& version)
1033 {
1034         int                     versionNum              = 0;
1035         std::string     postfix                 = "";
1036
1037         assumeToken(TOKEN_INT_LITERAL);
1038         versionNum = parseIntLiteral(m_curTokenStr.c_str());
1039         advanceToken();
1040
1041         if (m_curToken == TOKEN_IDENTIFIER)
1042         {
1043                 postfix = m_curTokenStr;
1044                 advanceToken();
1045         }
1046
1047         if              (versionNum == 100 && postfix == "es")  version = glu::GLSL_VERSION_100_ES;
1048         else if (versionNum == 300 && postfix == "es")  version = glu::GLSL_VERSION_300_ES;
1049         else if (versionNum == 310 && postfix == "es")  version = glu::GLSL_VERSION_310_ES;
1050         else if (versionNum == 130)                                             version = glu::GLSL_VERSION_130;
1051         else if (versionNum == 140)                                             version = glu::GLSL_VERSION_140;
1052         else if (versionNum == 150)                                             version = glu::GLSL_VERSION_150;
1053         else if (versionNum == 330)                                             version = glu::GLSL_VERSION_330;
1054         else if (versionNum == 400)                                             version = glu::GLSL_VERSION_400;
1055         else if (versionNum == 410)                                             version = glu::GLSL_VERSION_410;
1056         else if (versionNum == 420)                                             version = glu::GLSL_VERSION_420;
1057         else if (versionNum == 430)                                             version = glu::GLSL_VERSION_430;
1058         else
1059                 parseError("Unknown GLSL version");
1060 }
1061
1062 void ShaderParser::parsePipelineProgram (ShaderCase::PipelineProgram& program)
1063 {
1064         deUint32                                                        activeStages                    = 0;
1065         vector<string>                                          vertexSources;
1066         vector<string>                                          fragmentSources;
1067         vector<string>                                          tessellationCtrlSources;
1068         vector<string>                                          tessellationEvalSources;
1069         vector<string>                                          geometrySources;
1070         vector<ShaderCase::CaseRequirement>     requirements;
1071
1072         advanceToken(TOKEN_PIPELINE_PROGRAM);
1073
1074         for (;;)
1075         {
1076                 if (m_curToken == TOKEN_END)
1077                         break;
1078                 else if (m_curToken == TOKEN_ACTIVE_STAGES)
1079                 {
1080                         advanceToken();
1081                         activeStages = parseShaderStageList();
1082                 }
1083                 else if (m_curToken == TOKEN_REQUIRE)
1084                 {
1085                         ShaderCase::CaseRequirement requirement;
1086                         parseRequirement(requirement);
1087                         requirements.push_back(requirement);
1088                 }
1089                 else if (m_curToken == TOKEN_VERTEX                                             ||
1090                                  m_curToken == TOKEN_FRAGMENT                                   ||
1091                                  m_curToken == TOKEN_TESSELLATION_CONTROL               ||
1092                                  m_curToken == TOKEN_TESSELLATION_EVALUATION    ||
1093                                  m_curToken == TOKEN_GEOMETRY)
1094                 {
1095                         const Token     token = m_curToken;
1096                         string          source;
1097
1098                         advanceToken();
1099                         assumeToken(TOKEN_SHADER_SOURCE);
1100                         source = parseShaderSource(m_curTokenStr.c_str());
1101                         advanceToken();
1102
1103                         switch (token)
1104                         {
1105                                 case TOKEN_VERTEX:                                      vertexSources.push_back(source);                        break;
1106                                 case TOKEN_FRAGMENT:                            fragmentSources.push_back(source);                      break;
1107                                 case TOKEN_TESSELLATION_CONTROL:        tessellationCtrlSources.push_back(source);      break;
1108                                 case TOKEN_TESSELLATION_EVALUATION:     tessellationEvalSources.push_back(source);      break;
1109                                 case TOKEN_GEOMETRY:                            geometrySources.push_back(source);                      break;
1110                                 default:
1111                                         parseError(DE_FALSE);
1112                         }
1113                 }
1114                 else
1115                         parseError(string("invalid pipeline program value: " + m_curTokenStr));
1116         }
1117         advanceToken(TOKEN_END);
1118
1119         if (activeStages == 0)
1120                 parseError("program pipeline object must have active stages");
1121
1122         // return pipeline part
1123         program.activeStageBits = activeStages;
1124         program.requirements.swap(requirements);
1125         program.vertexSources.swap(vertexSources);
1126         program.fragmentSources.swap(fragmentSources);
1127         program.tessCtrlSources.swap(tessellationCtrlSources);
1128         program.tessEvalSources.swap(tessellationEvalSources);
1129         program.geometrySources.swap(geometrySources);
1130 }
1131
1132 void ShaderParser::parseShaderCase (vector<tcu::TestNode*>& shaderNodeList)
1133 {
1134         // Parse 'case'.
1135         PARSE_DBG(("  parseShaderCase()\n"));
1136         advanceToken(TOKEN_CASE);
1137
1138         // Parse case name.
1139         string caseName = m_curTokenStr;
1140         advanceToken(); // \note [pyry] All token types are allowed here.
1141
1142         // Setup case.
1143         GLSLVersion                                                     version                 = DEFAULT_GLSL_VERSION;
1144         ShaderCase::ExpectResult                        expectResult    = ShaderCase::EXPECT_PASS;
1145         string                                                          description;
1146         string                                                          bothSource;
1147         vector<string>                                          vertexSources;
1148         vector<string>                                          fragmentSources;
1149         vector<string>                                          tessellationCtrlSources;
1150         vector<string>                                          tessellationEvalSources;
1151         vector<string>                                          geometrySources;
1152         vector<ShaderCase::ValueBlock>          valueBlockList;
1153         vector<ShaderCase::CaseRequirement>     requirements;
1154         vector<ShaderCase::PipelineProgram>     pipelinePrograms;
1155
1156         for (;;)
1157         {
1158                 if (m_curToken == TOKEN_END)
1159                         break;
1160                 else if (m_curToken == TOKEN_DESC)
1161                 {
1162                         advanceToken();
1163                         assumeToken(TOKEN_STRING);
1164                         description = parseStringLiteral(m_curTokenStr.c_str());
1165                         advanceToken();
1166                 }
1167                 else if (m_curToken == TOKEN_EXPECT)
1168                 {
1169                         advanceToken();
1170                         parseExpectResult(expectResult);
1171                 }
1172                 else if (m_curToken == TOKEN_VALUES)
1173                 {
1174                         ShaderCase::ValueBlock block;
1175                         parseValueBlock(block);
1176                         valueBlockList.push_back(block);
1177                 }
1178                 else if (m_curToken == TOKEN_BOTH                                               ||
1179                                  m_curToken == TOKEN_VERTEX                                             ||
1180                                  m_curToken == TOKEN_FRAGMENT                                   ||
1181                                  m_curToken == TOKEN_TESSELLATION_CONTROL               ||
1182                                  m_curToken == TOKEN_TESSELLATION_EVALUATION    ||
1183                                  m_curToken == TOKEN_GEOMETRY)
1184                 {
1185                         const Token     token = m_curToken;
1186                         string          source;
1187
1188                         advanceToken();
1189                         assumeToken(TOKEN_SHADER_SOURCE);
1190                         source = parseShaderSource(m_curTokenStr.c_str());
1191                         advanceToken();
1192
1193                         switch (token)
1194                         {
1195                                 case TOKEN_VERTEX:                                      vertexSources.push_back(source);                        break;
1196                                 case TOKEN_FRAGMENT:                            fragmentSources.push_back(source);                      break;
1197                                 case TOKEN_TESSELLATION_CONTROL:        tessellationCtrlSources.push_back(source);      break;
1198                                 case TOKEN_TESSELLATION_EVALUATION:     tessellationEvalSources.push_back(source);      break;
1199                                 case TOKEN_GEOMETRY:                            geometrySources.push_back(source);                      break;
1200                                 case TOKEN_BOTH:
1201                                 {
1202                                         if (!bothSource.empty())
1203                                                 parseError("multiple 'both' blocks");
1204                                         bothSource = source;
1205                                         break;
1206                                 }
1207
1208                                 default:
1209                                         parseError(DE_FALSE);
1210                         }
1211                 }
1212                 else if (m_curToken == TOKEN_VERSION)
1213                 {
1214                         advanceToken();
1215                         parseGLSLVersion(version);
1216                 }
1217                 else if (m_curToken == TOKEN_REQUIRE)
1218                 {
1219                         ShaderCase::CaseRequirement requirement;
1220                         parseRequirement(requirement);
1221                         requirements.push_back(requirement);
1222                 }
1223                 else if (m_curToken == TOKEN_PIPELINE_PROGRAM)
1224                 {
1225                         ShaderCase::PipelineProgram pipelineProgram;
1226                         parsePipelineProgram(pipelineProgram);
1227                         pipelinePrograms.push_back(pipelineProgram);
1228                 }
1229                 else
1230                         parseError(string("unexpected token while parsing shader case: " + m_curTokenStr));
1231         }
1232
1233         advanceToken(TOKEN_END); // case end
1234
1235         if (!bothSource.empty())
1236         {
1237                 if (!vertexSources.empty()                              ||
1238                         !fragmentSources.empty()                        ||
1239                         !tessellationCtrlSources.empty()        ||
1240                         !tessellationEvalSources.empty()        ||
1241                         !geometrySources.empty()                        ||
1242                         !pipelinePrograms.empty())
1243                 {
1244                         parseError("'both' cannot be mixed with other shader stages");
1245                 }
1246
1247                 // vertex
1248                 {
1249                         ShaderCase::ShaderCaseSpecification spec = ShaderCase::ShaderCaseSpecification::generateSharedSourceVertexCase(expectResult, version, valueBlockList, bothSource);
1250                         spec.requirements = requirements;
1251
1252                         shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, m_contextInfo, (caseName + "_vertex").c_str(), description.c_str(), spec));
1253                 }
1254
1255                 // fragment
1256                 {
1257                         ShaderCase::ShaderCaseSpecification spec = ShaderCase::ShaderCaseSpecification::generateSharedSourceFragmentCase(expectResult, version, valueBlockList, bothSource);
1258                         spec.requirements = requirements;
1259
1260                         shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, m_contextInfo, (caseName + "_fragment").c_str(), description.c_str(), spec));
1261                 }
1262         }
1263         else if (pipelinePrograms.empty())
1264         {
1265                 ShaderCase::ShaderCaseSpecification spec;
1266
1267                 spec.expectResult       = expectResult;
1268                 spec.caseType           = ShaderCase::CASETYPE_COMPLETE;
1269                 spec.targetVersion      = version;
1270                 spec.requirements.swap(requirements);
1271                 spec.valueBlocks.swap(valueBlockList);
1272                 spec.vertexSources.swap(vertexSources);
1273                 spec.fragmentSources.swap(fragmentSources);
1274                 spec.tessCtrlSources.swap(tessellationCtrlSources);
1275                 spec.tessEvalSources.swap(tessellationEvalSources);
1276                 spec.geometrySources.swap(geometrySources);
1277
1278                 shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, m_contextInfo, caseName.c_str(), description.c_str(), spec));
1279         }
1280         else
1281         {
1282                 if (!vertexSources.empty()                              ||
1283                         !fragmentSources.empty()                        ||
1284                         !tessellationCtrlSources.empty()        ||
1285                         !tessellationEvalSources.empty()        ||
1286                         !geometrySources.empty())
1287                 {
1288                         parseError("pipeline programs cannot be mixed with complete programs");
1289                 }
1290
1291                 // Pipeline case, multiple programs
1292                 {
1293                         ShaderCase::PipelineCaseSpecification spec;
1294
1295                         spec.expectResult       = expectResult;
1296                         spec.caseType           = ShaderCase::CASETYPE_COMPLETE;
1297                         spec.targetVersion      = version;
1298                         spec.valueBlocks.swap(valueBlockList);
1299                         spec.programs.swap(pipelinePrograms);
1300
1301                         shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, m_contextInfo, caseName.c_str(), description.c_str(), spec));
1302                 }
1303         }
1304 }
1305
1306 void ShaderParser::parseShaderGroup (vector<tcu::TestNode*>& shaderNodeList)
1307 {
1308         // Parse 'case'.
1309         PARSE_DBG(("  parseShaderGroup()\n"));
1310         advanceToken(TOKEN_GROUP);
1311
1312         // Parse case name.
1313         string name = m_curTokenStr;
1314         advanceToken(); // \note [pyry] We don't want to check token type here (for instance to allow "uniform") group.
1315
1316         // Parse description.
1317         assumeToken(TOKEN_STRING);
1318         string description = parseStringLiteral(m_curTokenStr.c_str());
1319         advanceToken(TOKEN_STRING);
1320
1321         std::vector<tcu::TestNode*> children;
1322
1323         // Parse group children.
1324         for (;;)
1325         {
1326                 if (m_curToken == TOKEN_END)
1327                         break;
1328                 else if (m_curToken == TOKEN_GROUP)
1329                         parseShaderGroup(children);
1330                 else if (m_curToken == TOKEN_CASE)
1331                         parseShaderCase(children);
1332                 else if (m_curToken == TOKEN_IMPORT)
1333                         parseImport(children);
1334                 else
1335                         parseError(string("unexpected token while parsing shader group: " + m_curTokenStr));
1336         }
1337
1338         advanceToken(TOKEN_END); // group end
1339
1340         // Create group node.
1341         tcu::TestCaseGroup* groupNode = new tcu::TestCaseGroup(m_testCtx, name.c_str(), description.c_str(), children);
1342         shaderNodeList.push_back(groupNode);
1343 }
1344
1345 void ShaderParser::parseImport (vector<tcu::TestNode*>& shaderNodeList)
1346 {
1347         ShaderLibrary                   subLibrary              (m_testCtx, m_renderCtx, m_contextInfo);
1348         vector<tcu::TestNode*>  importedCases;
1349         std::string                             filename;
1350
1351         if (!m_currentDir)
1352                 parseError(string("cannot use import in inline shader source"));
1353
1354         advanceToken(TOKEN_IMPORT);
1355
1356         assumeToken(TOKEN_STRING);
1357         filename = m_currentDir + parseStringLiteral(m_curTokenStr.c_str());
1358         advanceToken(TOKEN_STRING);
1359
1360         importedCases = subLibrary.loadShaderFile(filename.c_str());
1361         shaderNodeList.insert(shaderNodeList.end(), importedCases.begin(), importedCases.end());
1362 }
1363
1364 vector<tcu::TestNode*> ShaderParser::parse (const char* input)
1365 {
1366         // Initialize parser.
1367         m_input                 = input;
1368         m_curPtr                = m_input.c_str();
1369         m_curToken              = TOKEN_INVALID;
1370         m_curTokenStr   = "";
1371         advanceToken();
1372
1373         vector<tcu::TestNode*> nodeList;
1374
1375         // Parse all cases.
1376         PARSE_DBG(("parse()\n"));
1377         for (;;)
1378         {
1379                 if (m_curToken == TOKEN_CASE)
1380                         parseShaderCase(nodeList);
1381                 else if (m_curToken == TOKEN_GROUP)
1382                         parseShaderGroup(nodeList);
1383                 else if (m_curToken == TOKEN_IMPORT)
1384                         parseImport(nodeList);
1385                 else if (m_curToken == TOKEN_EOF)
1386                         break;
1387                 else
1388                         parseError(string("invalid token encountered at main level: '") + m_curTokenStr + "'");
1389         }
1390
1391         assumeToken(TOKEN_EOF);
1392 //      printf("  parsed %d test cases.\n", caseList.size());
1393         return nodeList;
1394 }
1395
1396 } // sl
1397
1398 static std::string getFileDirectory (const std::string& filePath)
1399 {
1400         const std::string::size_type lastDelim = filePath.find_last_of('/');
1401
1402         if (lastDelim == std::string::npos)
1403                 return "";
1404         else
1405                 return filePath.substr(0, lastDelim+1);
1406 }
1407
1408 ShaderLibrary::ShaderLibrary (tcu::TestContext& testCtx, RenderContext& renderCtx, const glu::ContextInfo& contextInfo)
1409         : m_testCtx                     (testCtx)
1410         , m_renderCtx           (renderCtx)
1411         , m_contextInfo         (contextInfo)
1412 {
1413 }
1414
1415 ShaderLibrary::~ShaderLibrary (void)
1416 {
1417 }
1418
1419 vector<tcu::TestNode*> ShaderLibrary::loadShaderFile (const char* fileName)
1420 {
1421         tcu::Resource*          resource                = m_testCtx.getArchive().getResource(fileName);
1422         std::string                     fileDirectory   = getFileDirectory(fileName);
1423         std::vector<char>       buf;
1424
1425 /*      printf("  loading '%s'\n", fileName);*/
1426
1427         try
1428         {
1429                 int size = resource->getSize();
1430                 buf.resize(size + 1);
1431                 resource->read((deUint8*)&buf[0], size);
1432                 buf[size] = '\0';
1433         }
1434         catch (const std::exception&)
1435         {
1436                 delete resource;
1437                 throw;
1438         }
1439
1440         delete resource;
1441
1442         sl::ShaderParser parser(m_testCtx, m_renderCtx, m_contextInfo, fileDirectory.c_str());
1443         vector<tcu::TestNode*> nodes = parser.parse(&buf[0]);
1444
1445         return nodes;
1446 }
1447
1448 vector<tcu::TestNode*> ShaderLibrary::parseShader (const char* shaderSource)
1449 {
1450         sl::ShaderParser parser(m_testCtx, m_renderCtx, m_contextInfo);
1451         vector<tcu::TestNode*> nodes = parser.parse(shaderSource);
1452
1453         return nodes;
1454 }
1455
1456 } // gls
1457 } // deqp