• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
isWhitespace(char c)62 DE_INLINE deBool isWhitespace (char c)
63 {
64 	return (c == ' ') || (c == '\t') || (c == '\r') || (c == '\n');
65 }
66 
isEOL(char c)67 DE_INLINE deBool isEOL (char c)
68 {
69 	return (c == '\r') || (c == '\n');
70 }
71 
isNumeric(char c)72 DE_INLINE deBool isNumeric (char c)
73 {
74 	return deInRange32(c, '0', '9');
75 }
76 
isAlpha(char c)77 DE_INLINE deBool isAlpha (char c)
78 {
79 	return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z');
80 }
81 
isCaseNameChar(char c)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 
ShaderParser(tcu::TestContext & testCtx,RenderContext & renderCtx,const glu::ContextInfo & contextInfo,const char * currentDir)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 
~ShaderParser(void)222 ShaderParser::~ShaderParser (void)
223 {
224 	// nada
225 }
226 
parseError(const std::string & errorStr)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 
parseFloatLiteral(const char * str)233 float ShaderParser::parseFloatLiteral (const char* str)
234 {
235 	return (float)atof(str);
236 }
237 
parseIntLiteral(const char * str)238 int ShaderParser::parseIntLiteral (const char* str)
239 {
240 	return atoi(str);
241 }
242 
parseStringLiteral(const char * str)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 
removeExtraIndentation(const string & source)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 
parseShaderSource(const char * str)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 
advanceToken(void)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 
advanceToken(Token assumed)565 void ShaderParser::advanceToken (Token assumed)
566 {
567 	assumeToken(assumed);
568 	advanceToken();
569 }
570 
assumeToken(Token token)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 
mapDataTypeToken(Token token)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 
getTokenName(Token token)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 
getShaderStageLiteralFlag(void)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 
getGLEnumFromName(const std::string & enumName)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 
parseValueElement(DataType expectedDataType,ShaderCase::Value & result)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 
parseValue(ShaderCase::ValueBlock & valueBlock)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 
parseValueBlock(ShaderCase::ValueBlock & valueBlock)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 
parseShaderStageList(void)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 
parseRequirement(ShaderCase::CaseRequirement & valueBlock)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 
parseExpectResult(ShaderCase::ExpectResult & expectResult)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 
parseGLSLVersion(glu::GLSLVersion & version)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 
parsePipelineProgram(ShaderCase::PipelineProgram & program)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 
parseShaderCase(vector<tcu::TestNode * > & shaderNodeList)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 
parseShaderGroup(vector<tcu::TestNode * > & shaderNodeList)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 
parseImport(vector<tcu::TestNode * > & shaderNodeList)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 
parse(const char * input)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 
getFileDirectory(const std::string & filePath)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 
ShaderLibrary(tcu::TestContext & testCtx,RenderContext & renderCtx,const glu::ContextInfo & contextInfo)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 
~ShaderLibrary(void)1415 ShaderLibrary::~ShaderLibrary (void)
1416 {
1417 }
1418 
loadShaderFile(const char * fileName)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 
parseShader(const char * shaderSource)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
1458