Block/non-block uniforms match
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcShaderLibrary.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2016 Google Inc.
6  * Copyright (c) 2016 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */ /*!
21  * \file
22  * \brief Compiler test case.
23  */ /*-------------------------------------------------------------------*/
24
25 #include "glcShaderLibrary.hpp"
26 #include "glcShaderLibraryCase.hpp"
27 #include "gluShaderUtil.hpp"
28 #include "tcuResource.hpp"
29
30 #include "deInt32.h"
31
32 #include <fstream>
33 #include <sstream>
34 #include <string>
35 #include <vector>
36
37 #include <stdarg.h>
38 #include <stdlib.h>
39 #include <string.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 sl
56 {
57
58 static const glu::GLSLVersion DEFAULT_GLSL_VERSION = glu::GLSL_VERSION_100_ES;
59
60 DE_INLINE deBool isWhitespace(char c)
61 {
62         return (c == ' ') || (c == '\t') || (c == '\r') || (c == '\n');
63 }
64
65 DE_INLINE deBool isEOL(char c)
66 {
67         return (c == '\r') || (c == '\n');
68 }
69
70 DE_INLINE deBool isNumeric(char c)
71 {
72         return deInRange32(c, '0', '9');
73 }
74
75 DE_INLINE deBool isAlpha(char c)
76 {
77         return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z');
78 }
79
80 DE_INLINE deBool isCaseNameChar(char c)
81 {
82         return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z') || deInRange32(c, '0', '9') || (c == '_') ||
83                    (c == '-') || (c == '.');
84 }
85
86 // \todo [2011-02-11 pyry] Should not depend on Context or TestContext!
87 class ShaderParser
88 {
89 public:
90         ShaderParser(tcu::TestContext& testCtx, RenderContext& renderCtx);
91         ~ShaderParser(void);
92
93         vector<tcu::TestNode*> parse(const char* input);
94
95 private:
96         enum Token
97         {
98                 TOKEN_INVALID = 0,
99                 TOKEN_EOF,
100                 TOKEN_STRING,
101                 TOKEN_SHADER_SOURCE,
102
103                 TOKEN_INT_LITERAL,
104                 TOKEN_FLOAT_LITERAL,
105
106                 // identifiers
107                 TOKEN_IDENTIFIER,
108                 TOKEN_TRUE,
109                 TOKEN_FALSE,
110                 TOKEN_DESC,
111                 TOKEN_EXPECT,
112                 TOKEN_GROUP,
113                 TOKEN_CASE,
114                 TOKEN_END,
115                 TOKEN_VALUES,
116                 TOKEN_BOTH,
117                 TOKEN_VERTEX,
118                 TOKEN_FRAGMENT,
119                 TOKEN_UNIFORM,
120                 TOKEN_INPUT,
121                 TOKEN_OUTPUT,
122                 TOKEN_FLOAT,
123                 TOKEN_FLOAT_VEC2,
124                 TOKEN_FLOAT_VEC3,
125                 TOKEN_FLOAT_VEC4,
126                 TOKEN_FLOAT_MAT2,
127                 TOKEN_FLOAT_MAT2X3,
128                 TOKEN_FLOAT_MAT2X4,
129                 TOKEN_FLOAT_MAT3X2,
130                 TOKEN_FLOAT_MAT3,
131                 TOKEN_FLOAT_MAT3X4,
132                 TOKEN_FLOAT_MAT4X2,
133                 TOKEN_FLOAT_MAT4X3,
134                 TOKEN_FLOAT_MAT4,
135                 TOKEN_INT,
136                 TOKEN_INT_VEC2,
137                 TOKEN_INT_VEC3,
138                 TOKEN_INT_VEC4,
139                 TOKEN_UINT,
140                 TOKEN_UINT_VEC2,
141                 TOKEN_UINT_VEC3,
142                 TOKEN_UINT_VEC4,
143                 TOKEN_BOOL,
144                 TOKEN_BOOL_VEC2,
145                 TOKEN_BOOL_VEC3,
146                 TOKEN_BOOL_VEC4,
147                 TOKEN_VERSION,
148
149                 // symbols
150                 TOKEN_ASSIGN,
151                 TOKEN_PLUS,
152                 TOKEN_MINUS,
153                 TOKEN_COMMA,
154                 TOKEN_VERTICAL_BAR,
155                 TOKEN_SEMI_COLON,
156                 TOKEN_LEFT_PAREN,
157                 TOKEN_RIGHT_PAREN,
158                 TOKEN_LEFT_BRACKET,
159                 TOKEN_RIGHT_BRACKET,
160                 TOKEN_LEFT_BRACE,
161                 TOKEN_RIGHT_BRACE,
162
163                 TOKEN_LAST
164         };
165
166         void parseError(const std::string& errorStr);
167         float parseFloatLiteral(const char* str);
168         long long int parseIntLiteral(const char* str);
169         string parseStringLiteral(const char* str);
170         string parseShaderSource(const char* str);
171         void advanceToken(void);
172         void advanceToken(Token assumed);
173         void assumeToken(Token token);
174         DataType mapDataTypeToken(Token token);
175         const char* getTokenName(Token token);
176
177         void parseValueElement(DataType dataType, ShaderCase::Value& result);
178         void parseValue(ShaderCase::ValueBlock& valueBlock);
179         void parseValueBlock(ShaderCase::ValueBlock& valueBlock);
180         void parseShaderCase(vector<tcu::TestNode*>& shaderNodeList);
181         void parseShaderGroup(vector<tcu::TestNode*>& shaderNodeList);
182
183         // Member variables.
184         tcu::TestContext& m_testCtx;
185         RenderContext&  m_renderCtx;
186         std::string               m_input;
187         const char*               m_curPtr;
188         Token                     m_curToken;
189         std::string               m_curTokenStr;
190 };
191
192 ShaderParser::ShaderParser(tcu::TestContext& testCtx, RenderContext& renderCtx)
193         : m_testCtx(testCtx), m_renderCtx(renderCtx), m_curPtr(DE_NULL), m_curToken(TOKEN_LAST)
194 {
195 }
196
197 ShaderParser::~ShaderParser(void)
198 {
199         // nada
200 }
201
202 void ShaderParser::parseError(const std::string& errorStr)
203 {
204         string atStr = string(m_curPtr, 80);
205         throw tcu::InternalError((string("Parser error: ") + errorStr + " near '" + atStr + " ...'").c_str(), "", __FILE__,
206                                                          __LINE__);
207 }
208
209 float ShaderParser::parseFloatLiteral(const char* str)
210 {
211         return (float)atof(str);
212 }
213
214 long long int ShaderParser::parseIntLiteral(const char* str)
215 {
216         return strtoll(str, NULL, 0);
217 }
218
219 string ShaderParser::parseStringLiteral(const char* str)
220 {
221         const char*   p           = str;
222         char              endChar = *p++;
223         ostringstream o;
224
225         while (*p != endChar && *p)
226         {
227                 if (*p == '\\')
228                 {
229                         switch (p[1])
230                         {
231                         case 0:
232                                 DE_ASSERT(DE_FALSE);
233                                 break;
234                         case 'n':
235                                 o << '\n';
236                                 break;
237                         case 't':
238                                 o << '\t';
239                                 break;
240                         default:
241                                 o << p[1];
242                                 break;
243                         }
244
245                         p += 2;
246                 }
247                 else
248                         o << *p++;
249         }
250
251         return o.str();
252 }
253
254 static string removeExtraIndentation(const string& source)
255 {
256         // Detect indentation from first line.
257         int numIndentChars = 0;
258         for (int ndx = 0; isWhitespace(source[ndx]) && ndx < (int)source.length(); ndx++)
259                 numIndentChars += source[ndx] == '\t' ? 4 : 1;
260
261         // Process all lines and remove preceding indentation.
262         ostringstream processed;
263         {
264                 bool atLineStart                = true;
265                 int  indentCharsOmitted = 0;
266
267                 for (int pos = 0; pos < (int)source.length(); pos++)
268                 {
269                         char c = source[pos];
270
271                         if (atLineStart && indentCharsOmitted < numIndentChars && (c == ' ' || c == '\t'))
272                         {
273                                 indentCharsOmitted += c == '\t' ? 4 : 1;
274                         }
275                         else if (isEOL(c))
276                         {
277                                 if (source[pos] == '\r' && source[pos + 1] == '\n')
278                                 {
279                                         pos += 1;
280                                         processed << '\n';
281                                 }
282                                 else
283                                         processed << c;
284
285                                 atLineStart                = true;
286                                 indentCharsOmitted = 0;
287                         }
288                         else
289                         {
290                                 processed << c;
291                                 atLineStart = false;
292                         }
293                 }
294         }
295
296         return processed.str();
297 }
298
299 string ShaderParser::parseShaderSource(const char* str)
300 {
301         const char*   p = str + 2;
302         ostringstream o;
303
304         // Eat first empty line from beginning.
305         while (*p == ' ')
306                 p++;
307         while (isEOL(*p))
308                 p++;
309
310         while ((p[0] != '"') || (p[1] != '"'))
311         {
312                 if (*p == '\\')
313                 {
314                         switch (p[1])
315                         {
316                         case 0:
317                                 DE_ASSERT(DE_FALSE);
318                                 break;
319                         case 'n':
320                                 o << '\n';
321                                 break;
322                         case 't':
323                                 o << '\t';
324                                 break;
325                         default:
326                                 o << p[1];
327                                 break;
328                         }
329
330                         p += 2;
331                 }
332                 else
333                         o << *p++;
334         }
335
336         return removeExtraIndentation(o.str());
337 }
338
339 void ShaderParser::advanceToken(void)
340 {
341         // Skip old token.
342         m_curPtr += m_curTokenStr.length();
343
344         // Reset token (for safety).
345         m_curToken      = TOKEN_INVALID;
346         m_curTokenStr = "";
347
348         // Eat whitespace & comments while they last.
349         for (;;)
350         {
351                 while (isWhitespace(*m_curPtr))
352                         m_curPtr++;
353
354                 // Check for EOL comment.
355                 if (*m_curPtr == '#')
356                 {
357                         while (*m_curPtr && !isEOL(*m_curPtr))
358                                 m_curPtr++;
359                 }
360                 else
361                         break;
362         }
363
364         if (!*m_curPtr)
365         {
366                 m_curToken      = TOKEN_EOF;
367                 m_curTokenStr = "<EOF>";
368         }
369         else if (isAlpha(*m_curPtr))
370         {
371                 struct Named
372                 {
373                         const char* str;
374                         Token           token;
375                 };
376
377                 static const Named s_named[] = { { "true", TOKEN_TRUE },
378                                                                                  { "false", TOKEN_FALSE },
379                                                                                  { "desc", TOKEN_DESC },
380                                                                                  { "expect", TOKEN_EXPECT },
381                                                                                  { "group", TOKEN_GROUP },
382                                                                                  { "case", TOKEN_CASE },
383                                                                                  { "end", TOKEN_END },
384                                                                                  { "values", TOKEN_VALUES },
385                                                                                  { "both", TOKEN_BOTH },
386                                                                                  { "vertex", TOKEN_VERTEX },
387                                                                                  { "fragment", TOKEN_FRAGMENT },
388                                                                                  { "uniform", TOKEN_UNIFORM },
389                                                                                  { "input", TOKEN_INPUT },
390                                                                                  { "output", TOKEN_OUTPUT },
391                                                                                  { "float", TOKEN_FLOAT },
392                                                                                  { "vec2", TOKEN_FLOAT_VEC2 },
393                                                                                  { "vec3", TOKEN_FLOAT_VEC3 },
394                                                                                  { "vec4", TOKEN_FLOAT_VEC4 },
395                                                                                  { "mat2", TOKEN_FLOAT_MAT2 },
396                                                                                  { "mat2x3", TOKEN_FLOAT_MAT2X3 },
397                                                                                  { "mat2x4", TOKEN_FLOAT_MAT2X4 },
398                                                                                  { "mat3x2", TOKEN_FLOAT_MAT3X2 },
399                                                                                  { "mat3", TOKEN_FLOAT_MAT3 },
400                                                                                  { "mat3x4", TOKEN_FLOAT_MAT3X4 },
401                                                                                  { "mat4x2", TOKEN_FLOAT_MAT4X2 },
402                                                                                  { "mat4x3", TOKEN_FLOAT_MAT4X3 },
403                                                                                  { "mat4", TOKEN_FLOAT_MAT4 },
404                                                                                  { "int", TOKEN_INT },
405                                                                                  { "ivec2", TOKEN_INT_VEC2 },
406                                                                                  { "ivec3", TOKEN_INT_VEC3 },
407                                                                                  { "ivec4", TOKEN_INT_VEC4 },
408                                                                                  { "uint", TOKEN_UINT },
409                                                                                  { "uvec2", TOKEN_UINT_VEC2 },
410                                                                                  { "uvec3", TOKEN_UINT_VEC3 },
411                                                                                  { "uvec4", TOKEN_UINT_VEC4 },
412                                                                                  { "bool", TOKEN_BOOL },
413                                                                                  { "bvec2", TOKEN_BOOL_VEC2 },
414                                                                                  { "bvec3", TOKEN_BOOL_VEC3 },
415                                                                                  { "bvec4", TOKEN_BOOL_VEC4 },
416                                                                                  { "version", TOKEN_VERSION } };
417
418                 const char* end = m_curPtr + 1;
419                 while (isCaseNameChar(*end))
420                         end++;
421                 m_curTokenStr = string(m_curPtr, end - m_curPtr);
422
423                 m_curToken = TOKEN_IDENTIFIER;
424
425                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_named); ndx++)
426                 {
427                         if (m_curTokenStr == s_named[ndx].str)
428                         {
429                                 m_curToken = s_named[ndx].token;
430                                 break;
431                         }
432                 }
433         }
434         else if (isNumeric(*m_curPtr))
435         {
436                 /* \todo [2010-03-31 petri] Hex? */
437                 const char* p = m_curPtr;
438                 while (isNumeric(*p))
439                         p++;
440                 if (*p == '.')
441                 {
442                         p++;
443                         while (isNumeric(*p))
444                                 p++;
445
446                         if (*p == 'e' || *p == 'E')
447                         {
448                                 p++;
449                                 if (*p == '+' || *p == '-')
450                                         p++;
451                                 DE_ASSERT(isNumeric(*p));
452                                 while (isNumeric(*p))
453                                         p++;
454                         }
455
456                         m_curToken      = TOKEN_FLOAT_LITERAL;
457                         m_curTokenStr = string(m_curPtr, p - m_curPtr);
458                 }
459                 else
460                 {
461                         m_curToken      = TOKEN_INT_LITERAL;
462                         m_curTokenStr = string(m_curPtr, p - m_curPtr);
463                 }
464         }
465         else if (*m_curPtr == '"' && m_curPtr[1] == '"')
466         {
467                 const char* p = m_curPtr + 2;
468
469                 while ((p[0] != '"') || (p[1] != '"'))
470                 {
471                         DE_ASSERT(*p);
472                         if (*p == '\\')
473                         {
474                                 DE_ASSERT(p[1] != 0);
475                                 p += 2;
476                         }
477                         else
478                                 p++;
479                 }
480                 p += 2;
481
482                 m_curToken      = TOKEN_SHADER_SOURCE;
483                 m_curTokenStr = string(m_curPtr, (int)(p - m_curPtr));
484         }
485         else if (*m_curPtr == '"' || *m_curPtr == '\'')
486         {
487                 char            endChar = *m_curPtr;
488                 const char* p           = m_curPtr + 1;
489
490                 while (*p != endChar)
491                 {
492                         DE_ASSERT(*p);
493                         if (*p == '\\')
494                         {
495                                 DE_ASSERT(p[1] != 0);
496                                 p += 2;
497                         }
498                         else
499                                 p++;
500                 }
501                 p++;
502
503                 m_curToken      = TOKEN_STRING;
504                 m_curTokenStr = string(m_curPtr, (int)(p - m_curPtr));
505         }
506         else
507         {
508                 struct SimpleToken
509                 {
510                         const char* str;
511                         Token           token;
512                 };
513
514                 static const SimpleToken s_simple[] = { { "=", TOKEN_ASSIGN },           { "+", TOKEN_PLUS },
515                                                                                                 { "-", TOKEN_MINUS },            { ",", TOKEN_COMMA },
516                                                                                                 { "|", TOKEN_VERTICAL_BAR }, { ";", TOKEN_SEMI_COLON },
517                                                                                                 { "(", TOKEN_LEFT_PAREN },   { ")", TOKEN_RIGHT_PAREN },
518                                                                                                 { "[", TOKEN_LEFT_BRACKET }, { "]", TOKEN_RIGHT_BRACKET },
519                                                                                                 { "{", TOKEN_LEFT_BRACE },   { "}", TOKEN_RIGHT_BRACE } };
520
521                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_simple); ndx++)
522                 {
523                         if (strncmp(s_simple[ndx].str, m_curPtr, strlen(s_simple[ndx].str)) == 0)
524                         {
525                                 m_curToken      = s_simple[ndx].token;
526                                 m_curTokenStr = s_simple[ndx].str;
527                                 return;
528                         }
529                 }
530
531                 // Otherwise invalid token.
532                 m_curToken      = TOKEN_INVALID;
533                 m_curTokenStr = *m_curPtr;
534         }
535 }
536
537 void ShaderParser::advanceToken(Token assumed)
538 {
539         assumeToken(assumed);
540         advanceToken();
541 }
542
543 void ShaderParser::assumeToken(Token token)
544 {
545         if (m_curToken != token)
546                 parseError(
547                         (string("unexpected token '") + m_curTokenStr + "', expecting '" + getTokenName(token) + "'").c_str());
548         DE_TEST_ASSERT(m_curToken == token);
549 }
550
551 DataType ShaderParser::mapDataTypeToken(Token token)
552 {
553         switch (token)
554         {
555         case TOKEN_FLOAT:
556                 return TYPE_FLOAT;
557         case TOKEN_FLOAT_VEC2:
558                 return TYPE_FLOAT_VEC2;
559         case TOKEN_FLOAT_VEC3:
560                 return TYPE_FLOAT_VEC3;
561         case TOKEN_FLOAT_VEC4:
562                 return TYPE_FLOAT_VEC4;
563         case TOKEN_FLOAT_MAT2:
564                 return TYPE_FLOAT_MAT2;
565         case TOKEN_FLOAT_MAT2X3:
566                 return TYPE_FLOAT_MAT2X3;
567         case TOKEN_FLOAT_MAT2X4:
568                 return TYPE_FLOAT_MAT2X4;
569         case TOKEN_FLOAT_MAT3X2:
570                 return TYPE_FLOAT_MAT3X2;
571         case TOKEN_FLOAT_MAT3:
572                 return TYPE_FLOAT_MAT3;
573         case TOKEN_FLOAT_MAT3X4:
574                 return TYPE_FLOAT_MAT3X4;
575         case TOKEN_FLOAT_MAT4X2:
576                 return TYPE_FLOAT_MAT4X2;
577         case TOKEN_FLOAT_MAT4X3:
578                 return TYPE_FLOAT_MAT4X3;
579         case TOKEN_FLOAT_MAT4:
580                 return TYPE_FLOAT_MAT4;
581         case TOKEN_INT:
582                 return TYPE_INT;
583         case TOKEN_INT_VEC2:
584                 return TYPE_INT_VEC2;
585         case TOKEN_INT_VEC3:
586                 return TYPE_INT_VEC3;
587         case TOKEN_INT_VEC4:
588                 return TYPE_INT_VEC4;
589         case TOKEN_UINT:
590                 return TYPE_UINT;
591         case TOKEN_UINT_VEC2:
592                 return TYPE_UINT_VEC2;
593         case TOKEN_UINT_VEC3:
594                 return TYPE_UINT_VEC3;
595         case TOKEN_UINT_VEC4:
596                 return TYPE_UINT_VEC4;
597         case TOKEN_BOOL:
598                 return TYPE_BOOL;
599         case TOKEN_BOOL_VEC2:
600                 return TYPE_BOOL_VEC2;
601         case TOKEN_BOOL_VEC3:
602                 return TYPE_BOOL_VEC3;
603         case TOKEN_BOOL_VEC4:
604                 return TYPE_BOOL_VEC4;
605         default:
606                 return TYPE_INVALID;
607         }
608 }
609
610 const char* ShaderParser::getTokenName(Token token)
611 {
612         switch (token)
613         {
614         case TOKEN_INVALID:
615                 return "<invalid>";
616         case TOKEN_EOF:
617                 return "<eof>";
618         case TOKEN_STRING:
619                 return "<string>";
620         case TOKEN_SHADER_SOURCE:
621                 return "source";
622
623         case TOKEN_INT_LITERAL:
624                 return "<int>";
625         case TOKEN_FLOAT_LITERAL:
626                 return "<float>";
627
628         // identifiers
629         case TOKEN_IDENTIFIER:
630                 return "<identifier>";
631         case TOKEN_TRUE:
632                 return "true";
633         case TOKEN_FALSE:
634                 return "false";
635         case TOKEN_DESC:
636                 return "desc";
637         case TOKEN_EXPECT:
638                 return "expect";
639         case TOKEN_GROUP:
640                 return "group";
641         case TOKEN_CASE:
642                 return "case";
643         case TOKEN_END:
644                 return "end";
645         case TOKEN_VALUES:
646                 return "values";
647         case TOKEN_BOTH:
648                 return "both";
649         case TOKEN_VERTEX:
650                 return "vertex";
651         case TOKEN_FRAGMENT:
652                 return "fragment";
653         case TOKEN_UNIFORM:
654                 return "uniform";
655         case TOKEN_INPUT:
656                 return "input";
657         case TOKEN_OUTPUT:
658                 return "output";
659         case TOKEN_FLOAT:
660                 return "float";
661         case TOKEN_FLOAT_VEC2:
662                 return "vec2";
663         case TOKEN_FLOAT_VEC3:
664                 return "vec3";
665         case TOKEN_FLOAT_VEC4:
666                 return "vec4";
667         case TOKEN_FLOAT_MAT2:
668                 return "mat2";
669         case TOKEN_FLOAT_MAT2X3:
670                 return "mat2x3";
671         case TOKEN_FLOAT_MAT2X4:
672                 return "mat2x4";
673         case TOKEN_FLOAT_MAT3X2:
674                 return "mat3x2";
675         case TOKEN_FLOAT_MAT3:
676                 return "mat3";
677         case TOKEN_FLOAT_MAT3X4:
678                 return "mat3x4";
679         case TOKEN_FLOAT_MAT4X2:
680                 return "mat4x2";
681         case TOKEN_FLOAT_MAT4X3:
682                 return "mat4x3";
683         case TOKEN_FLOAT_MAT4:
684                 return "mat4";
685         case TOKEN_INT:
686                 return "int";
687         case TOKEN_INT_VEC2:
688                 return "ivec2";
689         case TOKEN_INT_VEC3:
690                 return "ivec3";
691         case TOKEN_INT_VEC4:
692                 return "ivec4";
693         case TOKEN_UINT:
694                 return "uint";
695         case TOKEN_UINT_VEC2:
696                 return "uvec2";
697         case TOKEN_UINT_VEC3:
698                 return "uvec3";
699         case TOKEN_UINT_VEC4:
700                 return "uvec4";
701         case TOKEN_BOOL:
702                 return "bool";
703         case TOKEN_BOOL_VEC2:
704                 return "bvec2";
705         case TOKEN_BOOL_VEC3:
706                 return "bvec3";
707         case TOKEN_BOOL_VEC4:
708                 return "bvec4";
709
710         case TOKEN_ASSIGN:
711                 return "=";
712         case TOKEN_PLUS:
713                 return "+";
714         case TOKEN_MINUS:
715                 return "-";
716         case TOKEN_COMMA:
717                 return ",";
718         case TOKEN_VERTICAL_BAR:
719                 return "|";
720         case TOKEN_SEMI_COLON:
721                 return ";";
722         case TOKEN_LEFT_PAREN:
723                 return "(";
724         case TOKEN_RIGHT_PAREN:
725                 return ")";
726         case TOKEN_LEFT_BRACKET:
727                 return "[";
728         case TOKEN_RIGHT_BRACKET:
729                 return "]";
730         case TOKEN_LEFT_BRACE:
731                 return "{";
732         case TOKEN_RIGHT_BRACE:
733                 return "}";
734
735         default:
736                 return "<unknown>";
737         }
738 }
739
740 void ShaderParser::parseValueElement(DataType expectedDataType, ShaderCase::Value& result)
741 {
742         DataType scalarType = getDataTypeScalarType(expectedDataType);
743         int              scalarSize = getDataTypeScalarSize(expectedDataType);
744
745         /* \todo [2010-04-19 petri] Support arrays. */
746         ShaderCase::Value::Element elems[16];
747
748         if (scalarSize > 1)
749         {
750                 DE_ASSERT(mapDataTypeToken(m_curToken) == expectedDataType);
751                 advanceToken(); // data type (float, vec2, etc.)
752                 advanceToken(TOKEN_LEFT_PAREN);
753         }
754
755         for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
756         {
757                 if (scalarType == TYPE_FLOAT)
758                 {
759                         float signMult = 1.0f;
760                         if (m_curToken == TOKEN_MINUS)
761                         {
762                                 signMult = -1.0f;
763                                 advanceToken();
764                         }
765
766                         assumeToken(TOKEN_FLOAT_LITERAL);
767                         elems[scalarNdx].float32 = signMult * parseFloatLiteral(m_curTokenStr.c_str());
768                         advanceToken(TOKEN_FLOAT_LITERAL);
769                 }
770                 else if (scalarType == TYPE_INT || scalarType == TYPE_UINT)
771                 {
772                         int signMult = 1;
773                         if (m_curToken == TOKEN_MINUS)
774                         {
775                                 signMult = -1;
776                                 advanceToken();
777                         }
778
779                         assumeToken(TOKEN_INT_LITERAL);
780                         elems[scalarNdx].int32 = signMult * parseIntLiteral(m_curTokenStr.c_str());
781                         advanceToken(TOKEN_INT_LITERAL);
782                 }
783                 else
784                 {
785                         DE_ASSERT(scalarType == TYPE_BOOL);
786                         elems[scalarNdx].bool32 = (m_curToken == TOKEN_TRUE);
787                         if (m_curToken != TOKEN_TRUE && m_curToken != TOKEN_FALSE)
788                                 parseError(string("unexpected token, expecting bool: " + m_curTokenStr));
789                         advanceToken(); // true/false
790                 }
791
792                 if (scalarNdx != (scalarSize - 1))
793                         advanceToken(TOKEN_COMMA);
794         }
795
796         if (scalarSize > 1)
797                 advanceToken(TOKEN_RIGHT_PAREN);
798
799         // Store results.
800         for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
801                 result.elements.push_back(elems[scalarNdx]);
802 }
803
804 void ShaderParser::parseValue(ShaderCase::ValueBlock& valueBlock)
805 {
806         PARSE_DBG(("      parseValue()\n"));
807
808         // Parsed results.
809         ShaderCase::Value result;
810
811         // Parse storage.
812         if (m_curToken == TOKEN_UNIFORM)
813                 result.storageType = ShaderCase::Value::STORAGE_UNIFORM;
814         else if (m_curToken == TOKEN_INPUT)
815                 result.storageType = ShaderCase::Value::STORAGE_INPUT;
816         else if (m_curToken == TOKEN_OUTPUT)
817                 result.storageType = ShaderCase::Value::STORAGE_OUTPUT;
818         else
819                 parseError(string("unexpected token encountered when parsing value classifier"));
820         advanceToken();
821
822         // Parse data type.
823         result.dataType = mapDataTypeToken(m_curToken);
824         if (result.dataType == TYPE_INVALID)
825                 parseError(string("unexpected token when parsing value data type: " + m_curTokenStr));
826         advanceToken();
827
828         // Parse value name.
829         if (m_curToken == TOKEN_IDENTIFIER || m_curToken == TOKEN_STRING)
830         {
831                 if (m_curToken == TOKEN_IDENTIFIER)
832                         result.valueName = m_curTokenStr;
833                 else
834                         result.valueName = parseStringLiteral(m_curTokenStr.c_str());
835         }
836         else
837                 parseError(string("unexpected token when parsing value name: " + m_curTokenStr));
838         advanceToken();
839
840         // Parse assignment operator.
841         advanceToken(TOKEN_ASSIGN);
842
843         // Parse actual value.
844         if (m_curToken == TOKEN_LEFT_BRACKET) // value list
845         {
846                 advanceToken(TOKEN_LEFT_BRACKET);
847                 result.arrayLength = 0;
848
849                 for (;;)
850                 {
851                         parseValueElement(result.dataType, result);
852                         result.arrayLength++;
853
854                         if (m_curToken == TOKEN_RIGHT_BRACKET)
855                                 break;
856                         else if (m_curToken == TOKEN_VERTICAL_BAR)
857                         {
858                                 advanceToken();
859                                 continue;
860                         }
861                         else
862                                 parseError(string("unexpected token in value element array: " + m_curTokenStr));
863                 }
864
865                 advanceToken(TOKEN_RIGHT_BRACKET);
866         }
867         else // arrays, single elements
868         {
869                 parseValueElement(result.dataType, result);
870                 result.arrayLength = 1;
871         }
872
873         advanceToken(TOKEN_SEMI_COLON); // end of declaration
874
875         valueBlock.values.push_back(result);
876 }
877
878 void ShaderParser::parseValueBlock(ShaderCase::ValueBlock& valueBlock)
879 {
880         PARSE_DBG(("    parseValueBlock()\n"));
881         advanceToken(TOKEN_VALUES);
882         advanceToken(TOKEN_LEFT_BRACE);
883
884         for (;;)
885         {
886                 if (m_curToken == TOKEN_UNIFORM || m_curToken == TOKEN_INPUT || m_curToken == TOKEN_OUTPUT)
887                         parseValue(valueBlock);
888                 else if (m_curToken == TOKEN_RIGHT_BRACE)
889                         break;
890                 else
891                         parseError(string("unexpected token when parsing a value block: " + m_curTokenStr));
892         }
893
894         advanceToken(TOKEN_RIGHT_BRACE);
895
896         // Compute combined array length of value block.
897         int arrayLength = 1;
898         for (int valueNdx = 0; valueNdx < (int)valueBlock.values.size(); valueNdx++)
899         {
900                 const ShaderCase::Value& val = valueBlock.values[valueNdx];
901                 if (val.arrayLength > 1)
902                 {
903                         DE_ASSERT(arrayLength == 1 || arrayLength == val.arrayLength);
904                         arrayLength = val.arrayLength;
905                 }
906         }
907         valueBlock.arrayLength = arrayLength;
908 }
909
910 void ShaderParser::parseShaderCase(vector<tcu::TestNode*>& shaderNodeList)
911 {
912         // Parse 'case'.
913         PARSE_DBG(("  parseShaderCase()\n"));
914         advanceToken(TOKEN_CASE);
915
916         // Parse case name.
917         string caseName = m_curTokenStr;
918         advanceToken(); // \note [pyry] All token types are allowed here.
919
920         // Setup case.
921         vector<ShaderCase::ValueBlock> valueBlockList;
922
923         GLSLVersion                              version          = DEFAULT_GLSL_VERSION;
924         ShaderCase::ExpectResult expectResult = ShaderCase::EXPECT_PASS;
925         string                                   description;
926         string                                   bothSource;
927         string                                   vertexSource;
928         string                                   fragmentSource;
929
930         for (;;)
931         {
932                 if (m_curToken == TOKEN_END)
933                         break;
934                 else if (m_curToken == TOKEN_DESC)
935                 {
936                         advanceToken();
937                         assumeToken(TOKEN_STRING);
938
939                         description = parseStringLiteral(m_curTokenStr.c_str());
940                         advanceToken();
941                 }
942                 else if (m_curToken == TOKEN_EXPECT)
943                 {
944                         advanceToken();
945                         assumeToken(TOKEN_IDENTIFIER);
946
947                         if (m_curTokenStr == "pass")
948                                 expectResult = ShaderCase::EXPECT_PASS;
949                         else if (m_curTokenStr == "compile_fail")
950                                 expectResult = ShaderCase::EXPECT_COMPILE_FAIL;
951                         else if (m_curTokenStr == "link_fail")
952                                 expectResult = ShaderCase::EXPECT_LINK_FAIL;
953                         else
954                                 parseError(string("invalid expected result value: " + m_curTokenStr));
955
956                         advanceToken();
957                 }
958                 else if (m_curToken == TOKEN_VALUES)
959                 {
960                         ShaderCase::ValueBlock block;
961                         parseValueBlock(block);
962                         valueBlockList.push_back(block);
963                 }
964                 else if (m_curToken == TOKEN_BOTH || m_curToken == TOKEN_VERTEX || m_curToken == TOKEN_FRAGMENT)
965                 {
966                         Token token = m_curToken;
967                         advanceToken();
968                         assumeToken(TOKEN_SHADER_SOURCE);
969                         string source = parseShaderSource(m_curTokenStr.c_str());
970                         advanceToken();
971                         if (token == TOKEN_BOTH)
972                                 bothSource = source;
973                         else if (token == TOKEN_VERTEX)
974                                 vertexSource = source;
975                         else if (token == TOKEN_FRAGMENT)
976                                 fragmentSource = source;
977                         else
978                                 DE_ASSERT(DE_FALSE);
979                 }
980                 else if (m_curToken == TOKEN_VERSION)
981                 {
982                         advanceToken();
983
984                         int                     versionNum = 0;
985                         std::string postfix     = "";
986
987                         assumeToken(TOKEN_INT_LITERAL);
988                         versionNum = parseIntLiteral(m_curTokenStr.c_str());
989                         advanceToken();
990
991                         if (m_curToken == TOKEN_IDENTIFIER)
992                         {
993                                 postfix = m_curTokenStr;
994                                 advanceToken();
995                         }
996
997                         if (versionNum == 100 && postfix == "es")
998                                 version = glu::GLSL_VERSION_100_ES;
999                         else if (versionNum == 300 && postfix == "es")
1000                                 version = glu::GLSL_VERSION_300_ES;
1001                         else if (versionNum == 310 && postfix == "es")
1002                                 version = glu::GLSL_VERSION_310_ES;
1003                         else if (versionNum == 130)
1004                                 version = glu::GLSL_VERSION_130;
1005                         else if (versionNum == 140)
1006                                 version = glu::GLSL_VERSION_140;
1007                         else if (versionNum == 150)
1008                                 version = glu::GLSL_VERSION_150;
1009                         else if (versionNum == 330)
1010                                 version = glu::GLSL_VERSION_330;
1011                         else if (versionNum == 400)
1012                                 version = glu::GLSL_VERSION_400;
1013                         else if (versionNum == 410)
1014                                 version = glu::GLSL_VERSION_410;
1015                         else if (versionNum == 420)
1016                                 version = glu::GLSL_VERSION_420;
1017                         else if (versionNum == 430)
1018                                 version = glu::GLSL_VERSION_430;
1019                         else if (versionNum == 440)
1020                                 version = glu::GLSL_VERSION_440;
1021                         else if (versionNum == 450)
1022                                 version = glu::GLSL_VERSION_450;
1023                         else
1024                                 parseError("Unknown GLSL version");
1025                 }
1026                 else
1027                         parseError(string("unexpected token while parsing shader case: " + m_curTokenStr));
1028         }
1029
1030         advanceToken(TOKEN_END); // case end
1031
1032         if (bothSource.length() > 0)
1033         {
1034                 DE_ASSERT(vertexSource.length() == 0);
1035                 DE_ASSERT(fragmentSource.length() == 0);
1036
1037                 string vertName = caseName + "_vertex";
1038                 string fragName = caseName + "_fragment";
1039                 shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, vertName.c_str(), description.c_str(),
1040                                                                                                 expectResult, valueBlockList, version, bothSource.c_str(), DE_NULL));
1041                 shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, fragName.c_str(), description.c_str(),
1042                                                                                                 expectResult, valueBlockList, version, DE_NULL, bothSource.c_str()));
1043         }
1044         else
1045         {
1046                 shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, caseName.c_str(), description.c_str(),
1047                                                                                                 expectResult, valueBlockList, version, vertexSource.c_str(),
1048                                                                                                 fragmentSource.c_str()));
1049         }
1050 }
1051
1052 void ShaderParser::parseShaderGroup(vector<tcu::TestNode*>& shaderNodeList)
1053 {
1054         // Parse 'case'.
1055         PARSE_DBG(("  parseShaderGroup()\n"));
1056         advanceToken(TOKEN_GROUP);
1057
1058         // Parse case name.
1059         string name = m_curTokenStr;
1060         advanceToken(); // \note [pyry] We don't want to check token type here (for instance to allow "uniform") group.
1061
1062         // Parse description.
1063         assumeToken(TOKEN_STRING);
1064         string description = parseStringLiteral(m_curTokenStr.c_str());
1065         advanceToken(TOKEN_STRING);
1066
1067         std::vector<tcu::TestNode*> children;
1068
1069         // Parse group children.
1070         for (;;)
1071         {
1072                 if (m_curToken == TOKEN_END)
1073                         break;
1074                 else if (m_curToken == TOKEN_GROUP)
1075                         parseShaderGroup(children);
1076                 else if (m_curToken == TOKEN_CASE)
1077                         parseShaderCase(children);
1078                 else
1079                         parseError(string("unexpected token while parsing shader group: " + m_curTokenStr));
1080         }
1081
1082         advanceToken(TOKEN_END); // group end
1083
1084         // Create group node.
1085         tcu::TestCaseGroup* groupNode = new tcu::TestCaseGroup(m_testCtx, name.c_str(), description.c_str(), children);
1086         shaderNodeList.push_back(groupNode);
1087 }
1088
1089 vector<tcu::TestNode*> ShaderParser::parse(const char* input)
1090 {
1091         // Initialize parser.
1092         m_input           = input;
1093         m_curPtr          = m_input.c_str();
1094         m_curToken      = TOKEN_INVALID;
1095         m_curTokenStr = "";
1096         advanceToken();
1097
1098         vector<tcu::TestNode*> nodeList;
1099
1100         // Parse all cases.
1101         PARSE_DBG(("parse()\n"));
1102         for (;;)
1103         {
1104                 if (m_curToken == TOKEN_CASE)
1105                         parseShaderCase(nodeList);
1106                 else if (m_curToken == TOKEN_GROUP)
1107                         parseShaderGroup(nodeList);
1108                 else if (m_curToken == TOKEN_EOF)
1109                         break;
1110                 else
1111                         parseError(string("invalid token encountered at main level: '") + m_curTokenStr + "'");
1112         }
1113
1114         assumeToken(TOKEN_EOF);
1115         //  printf("  parsed %d test cases.\n", caseList.size());
1116         return nodeList;
1117 }
1118
1119 } // sl
1120
1121 ShaderLibrary::ShaderLibrary(tcu::TestContext& testCtx, RenderContext& renderCtx)
1122         : m_testCtx(testCtx), m_renderCtx(renderCtx)
1123 {
1124 }
1125
1126 ShaderLibrary::~ShaderLibrary(void)
1127 {
1128 }
1129
1130 vector<tcu::TestNode*> ShaderLibrary::loadShaderFile(const char* fileName)
1131 {
1132         tcu::Resource*  resource = m_testCtx.getArchive().getResource(fileName);
1133         std::vector<char> buf;
1134
1135         /*  printf("  loading '%s'\n", fileName);*/
1136
1137         try
1138         {
1139                 int size = resource->getSize();
1140                 buf.resize(size + 1);
1141                 resource->read((deUint8*)&buf[0], size);
1142                 buf[size] = '\0';
1143         }
1144         catch (const std::exception&)
1145         {
1146                 delete resource;
1147                 throw;
1148         }
1149
1150         delete resource;
1151
1152         sl::ShaderParser           parser(m_testCtx, m_renderCtx);
1153         vector<tcu::TestNode*> nodes = parser.parse(&buf[0]);
1154
1155         return nodes;
1156 }
1157
1158 // ShaderLibraryGroup
1159
1160 ShaderLibraryGroup::ShaderLibraryGroup(Context& context, const char* name, const char* description,
1161                                                                            const char* filename)
1162         : TestCaseGroup(context, name, description), m_filename(filename)
1163 {
1164 }
1165
1166 ShaderLibraryGroup::~ShaderLibraryGroup(void)
1167 {
1168 }
1169
1170 void ShaderLibraryGroup::init(void)
1171 {
1172         deqp::ShaderLibrary                     shaderLibrary(m_testCtx, m_context.getRenderContext());
1173         std::vector<tcu::TestNode*> children = shaderLibrary.loadShaderFile(m_filename.c_str());
1174
1175         for (int i = 0; i < (int)children.size(); i++)
1176                 addChild(children[i]);
1177 }
1178
1179 } // deqp