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