1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL (ES) Module
3 * -----------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Compiler test case.
22 *//*--------------------------------------------------------------------*/
24 #include "glsShaderLibrary.hpp"
25 #include "glsShaderLibraryCase.hpp"
26 #include "gluShaderUtil.hpp"
27 #include "tcuResource.hpp"
28 #include "glwEnums.hpp"
43 using std::ostringstream;
48 # define PARSE_DBG(X) printf X
50 # define PARSE_DBG(X) DE_NULL_STATEMENT
60 static const glu::GLSLVersion DEFAULT_GLSL_VERSION = glu::GLSL_VERSION_100_ES;
62 DE_INLINE deBool isWhitespace (char c)
64 return (c == ' ') || (c == '\t') || (c == '\r') || (c == '\n');
67 DE_INLINE deBool isEOL (char c)
69 return (c == '\r') || (c == '\n');
72 DE_INLINE deBool isNumeric (char c)
74 return deInRange32(c, '0', '9');
77 DE_INLINE deBool isAlpha (char c)
79 return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z');
82 DE_INLINE deBool isCaseNameChar (char c)
84 return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z') || deInRange32(c, '0', '9') || (c == '_') || (c == '-') || (c == '.');
87 // \todo [2011-02-11 pyry] Should not depend on Context or TestContext!
91 ShaderParser (tcu::TestContext& testCtx, RenderContext& renderCtx, const glu::ContextInfo& contextInfo, const char* currentDir = DE_NULL);
94 vector<tcu::TestNode*> parse (const char* input);
149 TOKEN_TESSELLATION_CONTROL,
150 TOKEN_TESSELLATION_EVALUATION,
155 TOKEN_PIPELINE_PROGRAM,
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);
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);
202 tcu::TestContext& m_testCtx;
203 RenderContext& m_renderCtx;
204 const glu::ContextInfo& m_contextInfo;
206 const char* m_curPtr;
208 std::string m_curTokenStr;
209 const char* const m_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)
217 , m_curToken (TOKEN_LAST)
218 , m_currentDir (currentDir)
222 ShaderParser::~ShaderParser (void)
227 void ShaderParser::parseError (const std::string& errorStr)
229 string atStr = string(m_curPtr, 80);
230 throw tcu::InternalError((string("Parser error: ") + errorStr + " near '" + atStr + " ...'").c_str(), "", __FILE__, __LINE__);
233 float ShaderParser::parseFloatLiteral (const char* str)
235 return (float)atof(str);
238 int ShaderParser::parseIntLiteral (const char* str)
243 string ShaderParser::parseStringLiteral (const char* str)
249 while (*p != endChar && *p)
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;
270 static string removeExtraIndentation (const string& source)
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;
277 // Process all lines and remove preceding indentation.
278 ostringstream processed;
280 bool atLineStart = true;
281 int indentCharsOmitted = 0;
283 for (int pos = 0; pos < (int)source.length(); pos++)
285 char c = source[pos];
287 if (atLineStart && indentCharsOmitted < numIndentChars && (c == ' ' || c == '\t'))
289 indentCharsOmitted += c == '\t' ? 4 : 1;
293 if (source[pos] == '\r' && source[pos+1] == '\n')
302 indentCharsOmitted = 0;
312 return processed.str();
315 string ShaderParser::parseShaderSource (const char* str)
317 const char* p = str+2;
320 // Eat first empty line from beginning.
321 while (*p == ' ') p++;
325 while ((p[0] != '"') || (p[1] != '"'))
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;
343 return removeExtraIndentation(o.str());
346 void ShaderParser::advanceToken (void)
349 m_curPtr += m_curTokenStr.length();
351 // Reset token (for safety).
352 m_curToken = TOKEN_INVALID;
355 // Eat whitespace & comments while they last.
358 while (isWhitespace(*m_curPtr))
361 // Check for EOL comment.
362 if (*m_curPtr == '#')
364 while (*m_curPtr && !isEOL(*m_curPtr))
373 m_curToken = TOKEN_EOF;
374 m_curTokenStr = "<EOF>";
376 else if (isAlpha(*m_curPtr))
384 static const Named s_named[] =
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 },
431 { "import", TOKEN_IMPORT },
432 { "pipeline_program", TOKEN_PIPELINE_PROGRAM },
433 { "active_stages", TOKEN_ACTIVE_STAGES },
436 const char* end = m_curPtr + 1;
437 while (isCaseNameChar(*end))
439 m_curTokenStr = string(m_curPtr, end - m_curPtr);
441 m_curToken = TOKEN_IDENTIFIER;
443 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_named); ndx++)
445 if (m_curTokenStr == s_named[ndx].str)
447 m_curToken = s_named[ndx].token;
452 else if (isNumeric(*m_curPtr))
454 /* \todo [2010-03-31 petri] Hex? */
455 const char* p = m_curPtr;
456 while (isNumeric(*p))
461 while (isNumeric(*p))
464 if (*p == 'e' || *p == 'E')
467 if (*p == '+' || *p == '-')
469 DE_ASSERT(isNumeric(*p));
470 while (isNumeric(*p))
474 m_curToken = TOKEN_FLOAT_LITERAL;
475 m_curTokenStr = string(m_curPtr, p - m_curPtr);
479 m_curToken = TOKEN_INT_LITERAL;
480 m_curTokenStr = string(m_curPtr, p - m_curPtr);
483 else if (*m_curPtr == '"' && m_curPtr[1] == '"')
485 const char* p = m_curPtr + 2;
487 while ((p[0] != '"') || (p[1] != '"'))
492 DE_ASSERT(p[1] != 0);
500 m_curToken = TOKEN_SHADER_SOURCE;
501 m_curTokenStr = string(m_curPtr, (int)(p - m_curPtr));
503 else if (*m_curPtr == '"' || *m_curPtr == '\'')
505 char endChar = *m_curPtr;
506 const char* p = m_curPtr + 1;
508 while (*p != endChar)
513 DE_ASSERT(p[1] != 0);
521 m_curToken = TOKEN_STRING;
522 m_curTokenStr = string(m_curPtr, (int)(p - m_curPtr));
532 static const SimpleToken s_simple[] =
534 { "=", TOKEN_ASSIGN },
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 },
549 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_simple); ndx++)
551 if (strncmp(s_simple[ndx].str, m_curPtr, strlen(s_simple[ndx].str)) == 0)
553 m_curToken = s_simple[ndx].token;
554 m_curTokenStr = s_simple[ndx].str;
559 // Otherwise invalid token.
560 m_curToken = TOKEN_INVALID;
561 m_curTokenStr = *m_curPtr;
565 void ShaderParser::advanceToken (Token assumed)
567 assumeToken(assumed);
571 void ShaderParser::assumeToken (Token token)
573 if (m_curToken != token)
574 parseError((string("unexpected token '") + m_curTokenStr + "', expecting '" + getTokenName(token) + "'").c_str());
575 DE_TEST_ASSERT(m_curToken == token);
578 DataType ShaderParser::mapDataTypeToken (Token token)
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;
611 const char* ShaderParser::getTokenName (Token token)
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";
620 case TOKEN_INT_LITERAL: return "<int>";
621 case TOKEN_FLOAT_LITERAL: return "<float>";
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";
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 ">";
687 default: return "<unknown>";
691 deUint32 ShaderParser::getShaderStageLiteralFlag (void)
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);
702 parseError(std::string() + "invalid shader stage name, got " + m_curTokenStr);
707 deUint32 ShaderParser::getGLEnumFromName (const std::string& enumName)
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 },
721 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(names); ++ndx)
722 if (names[ndx].name == enumName)
723 return names[ndx].value;
725 parseError(std::string() + "unknown enum name, got " + enumName);
729 void ShaderParser::parseValueElement (DataType expectedDataType, ShaderCase::Value& result)
731 DataType scalarType = getDataTypeScalarType(expectedDataType);
732 int scalarSize = getDataTypeScalarSize(expectedDataType);
734 /* \todo [2010-04-19 petri] Support arrays. */
735 ShaderCase::Value::Element elems[16];
739 DE_ASSERT(mapDataTypeToken(m_curToken) == expectedDataType);
740 advanceToken(); // data type (float, vec2, etc.)
741 advanceToken(TOKEN_LEFT_PAREN);
744 for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
746 if (scalarType == TYPE_FLOAT)
748 float signMult = 1.0f;
749 if (m_curToken == TOKEN_MINUS)
755 assumeToken(TOKEN_FLOAT_LITERAL);
756 elems[scalarNdx].float32 = signMult * parseFloatLiteral(m_curTokenStr.c_str());
757 advanceToken(TOKEN_FLOAT_LITERAL);
759 else if (scalarType == TYPE_INT || scalarType == TYPE_UINT)
762 if (m_curToken == TOKEN_MINUS)
768 assumeToken(TOKEN_INT_LITERAL);
769 elems[scalarNdx].int32 = signMult * parseIntLiteral(m_curTokenStr.c_str());
770 advanceToken(TOKEN_INT_LITERAL);
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
781 if (scalarNdx != (scalarSize - 1))
782 advanceToken(TOKEN_COMMA);
786 advanceToken(TOKEN_RIGHT_PAREN);
789 for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
790 result.elements.push_back(elems[scalarNdx]);
793 void ShaderParser::parseValue (ShaderCase::ValueBlock& valueBlock)
795 PARSE_DBG((" parseValue()\n"));
798 ShaderCase::Value result;
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;
808 parseError(string("unexpected token encountered when parsing value classifier"));
812 result.dataType = mapDataTypeToken(m_curToken);
813 if (result.dataType == TYPE_INVALID)
814 parseError(string("unexpected token when parsing value data type: " + m_curTokenStr));
818 if (m_curToken == TOKEN_IDENTIFIER || m_curToken == TOKEN_STRING)
820 if (m_curToken == TOKEN_IDENTIFIER)
821 result.valueName = m_curTokenStr;
823 result.valueName = parseStringLiteral(m_curTokenStr.c_str());
826 parseError(string("unexpected token when parsing value name: " + m_curTokenStr));
829 // Parse assignment operator.
830 advanceToken(TOKEN_ASSIGN);
832 // Parse actual value.
833 if (m_curToken == TOKEN_LEFT_BRACKET) // value list
835 advanceToken(TOKEN_LEFT_BRACKET);
836 result.arrayLength = 0;
840 parseValueElement(result.dataType, result);
841 result.arrayLength++;
843 if (m_curToken == TOKEN_RIGHT_BRACKET)
845 else if (m_curToken == TOKEN_VERTICAL_BAR)
851 parseError(string("unexpected token in value element array: " + m_curTokenStr));
854 advanceToken(TOKEN_RIGHT_BRACKET);
856 else // arrays, single elements
858 parseValueElement(result.dataType, result);
859 result.arrayLength = 1;
862 advanceToken(TOKEN_SEMI_COLON); // end of declaration
864 valueBlock.values.push_back(result);
867 void ShaderParser::parseValueBlock (ShaderCase::ValueBlock& valueBlock)
869 PARSE_DBG((" parseValueBlock()\n"));
870 advanceToken(TOKEN_VALUES);
871 advanceToken(TOKEN_LEFT_BRACE);
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)
880 parseError(string("unexpected token when parsing a value block: " + m_curTokenStr));
883 advanceToken(TOKEN_RIGHT_BRACE);
885 // Compute combined array length of value block.
887 for (int valueNdx = 0; valueNdx < (int)valueBlock.values.size(); valueNdx++)
889 const ShaderCase::Value& val = valueBlock.values[valueNdx];
890 if (val.arrayLength > 1)
892 DE_ASSERT(arrayLength == 1 || arrayLength == val.arrayLength);
893 arrayLength = val.arrayLength;
896 valueBlock.arrayLength = arrayLength;
899 deUint32 ShaderParser::parseShaderStageList (void)
903 assumeToken(TOKEN_LEFT_BRACE);
905 // don't allow 0-sized lists
907 mask |= getShaderStageLiteralFlag();
912 if (m_curToken == TOKEN_RIGHT_BRACE)
914 else if (m_curToken == TOKEN_COMMA)
919 stageFlag = getShaderStageLiteralFlag();
920 if (stageFlag & mask)
921 parseError(string("stage already set in the shader stage set: " + m_curTokenStr));
927 parseError(string("invalid shader stage set token: " + m_curTokenStr));
929 advanceToken(TOKEN_RIGHT_BRACE);
934 void ShaderParser::parseRequirement (ShaderCase::CaseRequirement& valueBlock)
936 PARSE_DBG((" parseRequirement()\n"));
939 assumeToken(TOKEN_IDENTIFIER);
941 if (m_curTokenStr == "extension")
943 std::vector<std::string> anyExtensionStringList;
944 deUint32 affectedCasesFlags = -1; // by default all stages
947 assumeToken(TOKEN_LEFT_BRACE);
950 assumeToken(TOKEN_STRING);
952 anyExtensionStringList.push_back(parseStringLiteral(m_curTokenStr.c_str()));
957 if (m_curToken == TOKEN_RIGHT_BRACE)
959 else if (m_curToken == TOKEN_VERTICAL_BAR)
962 assumeToken(TOKEN_STRING);
964 anyExtensionStringList.push_back(parseStringLiteral(m_curTokenStr.c_str()));
968 parseError(string("invalid extension list token: " + m_curTokenStr));
970 advanceToken(TOKEN_RIGHT_BRACE);
972 if (m_curToken == TOKEN_IN)
975 affectedCasesFlags = parseShaderStageList();
978 valueBlock = ShaderCase::CaseRequirement::createAnyExtensionRequirement(anyExtensionStringList, affectedCasesFlags);
980 else if (m_curTokenStr == "limit")
987 assumeToken(TOKEN_STRING);
988 limitEnum = getGLEnumFromName(parseStringLiteral(m_curTokenStr.c_str()));
991 assumeToken(TOKEN_GREATER);
994 assumeToken(TOKEN_INT_LITERAL);
995 limitValue = parseIntLiteral(m_curTokenStr.c_str());
998 valueBlock = ShaderCase::CaseRequirement::createLimitRequirement(limitEnum, limitValue);
1000 else if (m_curTokenStr == "full_glsl_es_100_support")
1004 valueBlock = ShaderCase::CaseRequirement::createFullGLSLES100SpecificationRequirement();
1007 parseError(string("invalid requirement value: " + m_curTokenStr));
1010 void ShaderParser::parseExpectResult (ShaderCase::ExpectResult& expectResult)
1012 assumeToken(TOKEN_IDENTIFIER);
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;
1027 parseError(string("invalid expected result value: " + m_curTokenStr));
1032 void ShaderParser::parseGLSLVersion (glu::GLSLVersion& version)
1035 std::string postfix = "";
1037 assumeToken(TOKEN_INT_LITERAL);
1038 versionNum = parseIntLiteral(m_curTokenStr.c_str());
1041 if (m_curToken == TOKEN_IDENTIFIER)
1043 postfix = m_curTokenStr;
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;
1059 parseError("Unknown GLSL version");
1062 void ShaderParser::parsePipelineProgram (ShaderCase::PipelineProgram& program)
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;
1072 advanceToken(TOKEN_PIPELINE_PROGRAM);
1076 if (m_curToken == TOKEN_END)
1078 else if (m_curToken == TOKEN_ACTIVE_STAGES)
1081 activeStages = parseShaderStageList();
1083 else if (m_curToken == TOKEN_REQUIRE)
1085 ShaderCase::CaseRequirement requirement;
1086 parseRequirement(requirement);
1087 requirements.push_back(requirement);
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)
1095 const Token token = m_curToken;
1099 assumeToken(TOKEN_SHADER_SOURCE);
1100 source = parseShaderSource(m_curTokenStr.c_str());
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;
1111 parseError(DE_FALSE);
1115 parseError(string("invalid pipeline program value: " + m_curTokenStr));
1117 advanceToken(TOKEN_END);
1119 if (activeStages == 0)
1120 parseError("program pipeline object must have active stages");
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);
1132 void ShaderParser::parseShaderCase (vector<tcu::TestNode*>& shaderNodeList)
1135 PARSE_DBG((" parseShaderCase()\n"));
1136 advanceToken(TOKEN_CASE);
1139 string caseName = m_curTokenStr;
1140 advanceToken(); // \note [pyry] All token types are allowed here.
1143 GLSLVersion version = DEFAULT_GLSL_VERSION;
1144 ShaderCase::ExpectResult expectResult = ShaderCase::EXPECT_PASS;
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;
1158 if (m_curToken == TOKEN_END)
1160 else if (m_curToken == TOKEN_DESC)
1163 assumeToken(TOKEN_STRING);
1164 description = parseStringLiteral(m_curTokenStr.c_str());
1167 else if (m_curToken == TOKEN_EXPECT)
1170 parseExpectResult(expectResult);
1172 else if (m_curToken == TOKEN_VALUES)
1174 ShaderCase::ValueBlock block;
1175 parseValueBlock(block);
1176 valueBlockList.push_back(block);
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)
1185 const Token token = m_curToken;
1189 assumeToken(TOKEN_SHADER_SOURCE);
1190 source = parseShaderSource(m_curTokenStr.c_str());
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;
1202 if (!bothSource.empty())
1203 parseError("multiple 'both' blocks");
1204 bothSource = source;
1209 parseError(DE_FALSE);
1212 else if (m_curToken == TOKEN_VERSION)
1215 parseGLSLVersion(version);
1217 else if (m_curToken == TOKEN_REQUIRE)
1219 ShaderCase::CaseRequirement requirement;
1220 parseRequirement(requirement);
1221 requirements.push_back(requirement);
1223 else if (m_curToken == TOKEN_PIPELINE_PROGRAM)
1225 ShaderCase::PipelineProgram pipelineProgram;
1226 parsePipelineProgram(pipelineProgram);
1227 pipelinePrograms.push_back(pipelineProgram);
1230 parseError(string("unexpected token while parsing shader case: " + m_curTokenStr));
1233 advanceToken(TOKEN_END); // case end
1235 if (!bothSource.empty())
1237 if (!vertexSources.empty() ||
1238 !fragmentSources.empty() ||
1239 !tessellationCtrlSources.empty() ||
1240 !tessellationEvalSources.empty() ||
1241 !geometrySources.empty() ||
1242 !pipelinePrograms.empty())
1244 parseError("'both' cannot be mixed with other shader stages");
1249 ShaderCase::ShaderCaseSpecification spec = ShaderCase::ShaderCaseSpecification::generateSharedSourceVertexCase(expectResult, version, valueBlockList, bothSource);
1250 spec.requirements = requirements;
1252 shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, m_contextInfo, (caseName + "_vertex").c_str(), description.c_str(), spec));
1257 ShaderCase::ShaderCaseSpecification spec = ShaderCase::ShaderCaseSpecification::generateSharedSourceFragmentCase(expectResult, version, valueBlockList, bothSource);
1258 spec.requirements = requirements;
1260 shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, m_contextInfo, (caseName + "_fragment").c_str(), description.c_str(), spec));
1263 else if (pipelinePrograms.empty())
1265 ShaderCase::ShaderCaseSpecification spec;
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);
1278 shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, m_contextInfo, caseName.c_str(), description.c_str(), spec));
1282 if (!vertexSources.empty() ||
1283 !fragmentSources.empty() ||
1284 !tessellationCtrlSources.empty() ||
1285 !tessellationEvalSources.empty() ||
1286 !geometrySources.empty())
1288 parseError("pipeline programs cannot be mixed with complete programs");
1291 // Pipeline case, multiple programs
1293 ShaderCase::PipelineCaseSpecification spec;
1295 spec.expectResult = expectResult;
1296 spec.caseType = ShaderCase::CASETYPE_COMPLETE;
1297 spec.targetVersion = version;
1298 spec.valueBlocks.swap(valueBlockList);
1299 spec.programs.swap(pipelinePrograms);
1301 shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, m_contextInfo, caseName.c_str(), description.c_str(), spec));
1306 void ShaderParser::parseShaderGroup (vector<tcu::TestNode*>& shaderNodeList)
1309 PARSE_DBG((" parseShaderGroup()\n"));
1310 advanceToken(TOKEN_GROUP);
1313 string name = m_curTokenStr;
1314 advanceToken(); // \note [pyry] We don't want to check token type here (for instance to allow "uniform") group.
1316 // Parse description.
1317 assumeToken(TOKEN_STRING);
1318 string description = parseStringLiteral(m_curTokenStr.c_str());
1319 advanceToken(TOKEN_STRING);
1321 std::vector<tcu::TestNode*> children;
1323 // Parse group children.
1326 if (m_curToken == TOKEN_END)
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);
1335 parseError(string("unexpected token while parsing shader group: " + m_curTokenStr));
1338 advanceToken(TOKEN_END); // group end
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);
1345 void ShaderParser::parseImport (vector<tcu::TestNode*>& shaderNodeList)
1347 ShaderLibrary subLibrary (m_testCtx, m_renderCtx, m_contextInfo);
1348 vector<tcu::TestNode*> importedCases;
1349 std::string filename;
1352 parseError(string("cannot use import in inline shader source"));
1354 advanceToken(TOKEN_IMPORT);
1356 assumeToken(TOKEN_STRING);
1357 filename = m_currentDir + parseStringLiteral(m_curTokenStr.c_str());
1358 advanceToken(TOKEN_STRING);
1360 importedCases = subLibrary.loadShaderFile(filename.c_str());
1361 shaderNodeList.insert(shaderNodeList.end(), importedCases.begin(), importedCases.end());
1364 vector<tcu::TestNode*> ShaderParser::parse (const char* input)
1366 // Initialize parser.
1368 m_curPtr = m_input.c_str();
1369 m_curToken = TOKEN_INVALID;
1373 vector<tcu::TestNode*> nodeList;
1376 PARSE_DBG(("parse()\n"));
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)
1388 parseError(string("invalid token encountered at main level: '") + m_curTokenStr + "'");
1391 assumeToken(TOKEN_EOF);
1392 // printf(" parsed %d test cases.\n", caseList.size());
1398 static std::string getFileDirectory (const std::string& filePath)
1400 const std::string::size_type lastDelim = filePath.find_last_of('/');
1402 if (lastDelim == std::string::npos)
1405 return filePath.substr(0, lastDelim+1);
1408 ShaderLibrary::ShaderLibrary (tcu::TestContext& testCtx, RenderContext& renderCtx, const glu::ContextInfo& contextInfo)
1409 : m_testCtx (testCtx)
1410 , m_renderCtx (renderCtx)
1411 , m_contextInfo (contextInfo)
1415 ShaderLibrary::~ShaderLibrary (void)
1419 vector<tcu::TestNode*> ShaderLibrary::loadShaderFile (const char* fileName)
1421 tcu::Resource* resource = m_testCtx.getArchive().getResource(fileName);
1422 std::string fileDirectory = getFileDirectory(fileName);
1423 std::vector<char> buf;
1425 /* printf(" loading '%s'\n", fileName);*/
1429 int size = resource->getSize();
1430 buf.resize(size + 1);
1431 resource->read((deUint8*)&buf[0], size);
1434 catch (const std::exception&)
1442 sl::ShaderParser parser(m_testCtx, m_renderCtx, m_contextInfo, fileDirectory.c_str());
1443 vector<tcu::TestNode*> nodes = parser.parse(&buf[0]);
1448 vector<tcu::TestNode*> ShaderLibrary::parseShader (const char* shaderSource)
1450 sl::ShaderParser parser(m_testCtx, m_renderCtx, m_contextInfo);
1451 vector<tcu::TestNode*> nodes = parser.parse(shaderSource);