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