1#include "ANGLETest.h" 2 3class GLSLTest : public ANGLETest 4{ 5protected: 6 GLSLTest() 7 { 8 setWindowWidth(128); 9 setWindowHeight(128); 10 setConfigRedBits(8); 11 setConfigGreenBits(8); 12 setConfigBlueBits(8); 13 setConfigAlphaBits(8); 14 } 15 16 virtual void SetUp() 17 { 18 ANGLETest::SetUp(); 19 20 mSimpleVSSource = SHADER_SOURCE 21 ( 22 attribute vec4 inputAttribute; 23 void main() 24 { 25 gl_Position = inputAttribute; 26 } 27 ); 28 } 29 30 std::string GenerateVaryingType(GLint vectorSize) 31 { 32 char varyingType[10]; 33 34 if (vectorSize == 1) 35 { 36 sprintf(varyingType, "float"); 37 } 38 else 39 { 40 sprintf(varyingType, "vec%d", vectorSize); 41 } 42 43 return std::string(varyingType); 44 } 45 46 std::string GenerateVectorVaryingDeclaration(GLint vectorSize, GLint arraySize, GLint id) 47 { 48 char buff[100]; 49 50 if (arraySize == 1) 51 { 52 sprintf(buff, "varying %s v%d;\n", GenerateVaryingType(vectorSize).c_str(), id); 53 } 54 else 55 { 56 sprintf(buff, "varying %s v%d[%d];\n", GenerateVaryingType(vectorSize).c_str(), id, arraySize); 57 } 58 59 return std::string(buff); 60 } 61 62 std::string GenerateVectorVaryingSettingCode(GLint vectorSize, GLint arraySize, GLint id) 63 { 64 std::string returnString; 65 char buff[100]; 66 67 if (arraySize == 1) 68 { 69 sprintf(buff, "\t v%d = %s(1.0);\n", id, GenerateVaryingType(vectorSize).c_str()); 70 returnString += buff; 71 } 72 else 73 { 74 for (int i = 0; i < arraySize; i++) 75 { 76 sprintf(buff, "\t v%d[%d] = %s(1.0);\n", id, i, GenerateVaryingType(vectorSize).c_str()); 77 returnString += buff; 78 } 79 } 80 81 return returnString; 82 } 83 84 std::string GenerateVectorVaryingUseCode(GLint arraySize, GLint id) 85 { 86 if (arraySize == 1) 87 { 88 char buff[100]; 89 sprintf(buff, "v%d + ", id); 90 return std::string(buff); 91 } 92 else 93 { 94 std::string returnString; 95 for (int i = 0; i < arraySize; i++) 96 { 97 char buff[100]; 98 sprintf(buff, "v%d[%d] + ", id, i); 99 returnString += buff; 100 } 101 return returnString; 102 } 103 } 104 105 void GenerateGLSLWithVaryings(GLint floatCount, GLint floatArrayCount, GLint vec2Count, GLint vec2ArrayCount, GLint vec3Count, GLint vec3ArrayCount, std::string* fragmentShader, std::string* vertexShader) 106 { 107 // Generate a string declaring the varyings, to share between the fragment shader and the vertex shader. 108 std::string varyingDeclaration; 109 110 unsigned int varyingCount = 0; 111 112 for (GLint i = 0; i < floatCount; i++) 113 { 114 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 1, varyingCount); 115 varyingCount += 1; 116 } 117 118 for (GLint i = 0; i < floatArrayCount; i++) 119 { 120 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 2, varyingCount); 121 varyingCount += 1; 122 } 123 124 for (GLint i = 0; i < vec2Count; i++) 125 { 126 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 1, varyingCount); 127 varyingCount += 1; 128 } 129 130 for (GLint i = 0; i < vec2ArrayCount; i++) 131 { 132 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 2, varyingCount); 133 varyingCount += 1; 134 } 135 136 for (GLint i = 0; i < vec3Count; i++) 137 { 138 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 1, varyingCount); 139 varyingCount += 1; 140 } 141 142 for (GLint i = 0; i < vec3ArrayCount; i++) 143 { 144 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 2, varyingCount); 145 varyingCount += 1; 146 } 147 148 // Generate the vertex shader 149 vertexShader->clear(); 150 vertexShader->append(varyingDeclaration); 151 vertexShader->append("\nvoid main()\n{\n"); 152 153 unsigned int currentVSVarying = 0; 154 155 for (GLint i = 0; i < floatCount; i++) 156 { 157 vertexShader->append(GenerateVectorVaryingSettingCode(1, 1, currentVSVarying)); 158 currentVSVarying += 1; 159 } 160 161 for (GLint i = 0; i < floatArrayCount; i++) 162 { 163 vertexShader->append(GenerateVectorVaryingSettingCode(1, 2, currentVSVarying)); 164 currentVSVarying += 1; 165 } 166 167 for (GLint i = 0; i < vec2Count; i++) 168 { 169 vertexShader->append(GenerateVectorVaryingSettingCode(2, 1, currentVSVarying)); 170 currentVSVarying += 1; 171 } 172 173 for (GLint i = 0; i < vec2ArrayCount; i++) 174 { 175 vertexShader->append(GenerateVectorVaryingSettingCode(2, 2, currentVSVarying)); 176 currentVSVarying += 1; 177 } 178 179 for (GLint i = 0; i < vec3Count; i++) 180 { 181 vertexShader->append(GenerateVectorVaryingSettingCode(3, 1, currentVSVarying)); 182 currentVSVarying += 1; 183 } 184 185 for (GLint i = 0; i < vec3ArrayCount; i++) 186 { 187 vertexShader->append(GenerateVectorVaryingSettingCode(3, 2, currentVSVarying)); 188 currentVSVarying += 1; 189 } 190 191 vertexShader->append("}\n"); 192 193 // Generate the fragment shader 194 fragmentShader->clear(); 195 fragmentShader->append("precision highp float;\n"); 196 fragmentShader->append(varyingDeclaration); 197 fragmentShader->append("\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n"); 198 199 unsigned int currentFSVarying = 0; 200 201 // Make use of the float varyings 202 fragmentShader->append("\tretColor += vec4("); 203 204 for (GLint i = 0; i < floatCount; i++) 205 { 206 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying)); 207 currentFSVarying += 1; 208 } 209 210 for (GLint i = 0; i < floatArrayCount; i++) 211 { 212 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying)); 213 currentFSVarying += 1; 214 } 215 216 fragmentShader->append("0.0, 0.0, 0.0, 0.0);\n"); 217 218 // Make use of the vec2 varyings 219 fragmentShader->append("\tretColor += vec4("); 220 221 for (GLint i = 0; i < vec2Count; i++) 222 { 223 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying)); 224 currentFSVarying += 1; 225 } 226 227 for (GLint i = 0; i < vec2ArrayCount; i++) 228 { 229 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying)); 230 currentFSVarying += 1; 231 } 232 233 fragmentShader->append("vec2(0.0, 0.0), 0.0, 0.0);\n"); 234 235 // Make use of the vec3 varyings 236 fragmentShader->append("\tretColor += vec4("); 237 238 for (GLint i = 0; i < vec3Count; i++) 239 { 240 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying)); 241 currentFSVarying += 1; 242 } 243 244 for (GLint i = 0; i < vec3ArrayCount; i++) 245 { 246 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying)); 247 currentFSVarying += 1; 248 } 249 250 fragmentShader->append("vec3(0.0, 0.0, 0.0), 0.0);\n"); 251 fragmentShader->append("\tgl_FragColor = retColor;\n}"); 252 } 253 254 std::string mSimpleVSSource; 255}; 256 257TEST_F(GLSLTest, NamelessScopedStructs) 258{ 259 const std::string fragmentShaderSource = SHADER_SOURCE 260 ( 261 precision mediump float; 262 263 void main() 264 { 265 struct 266 { 267 float q; 268 } b; 269 270 gl_FragColor = vec4(1, 0, 0, 1); 271 gl_FragColor.a += b.q; 272 } 273 ); 274 275 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource); 276 EXPECT_NE(0u, program); 277} 278TEST_F(GLSLTest, ScopedStructsOrderBug) 279{ 280 const std::string fragmentShaderSource = SHADER_SOURCE 281 ( 282 precision mediump float; 283 284 struct T 285 { 286 float f; 287 }; 288 289 void main() 290 { 291 T a; 292 293 struct T 294 { 295 float q; 296 }; 297 298 T b; 299 300 gl_FragColor = vec4(1, 0, 0, 1); 301 gl_FragColor.a += a.f; 302 gl_FragColor.a += b.q; 303 } 304 ); 305 306 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource); 307 EXPECT_NE(0u, program); 308} 309 310TEST_F(GLSLTest, ScopedStructsBug) 311{ 312 const std::string fragmentShaderSource = SHADER_SOURCE 313 ( 314 precision mediump float; 315 316 struct T_0 317 { 318 float f; 319 }; 320 321 void main() 322 { 323 gl_FragColor = vec4(1, 0, 0, 1); 324 325 struct T 326 { 327 vec2 v; 328 }; 329 330 T_0 a; 331 T b; 332 333 gl_FragColor.a += a.f; 334 gl_FragColor.a += b.v.x; 335 } 336 ); 337 338 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource); 339 EXPECT_NE(0u, program); 340} 341 342TEST_F(GLSLTest, DxPositionBug) 343{ 344 const std::string &vertexShaderSource = SHADER_SOURCE 345 ( 346 attribute vec4 inputAttribute; 347 varying float dx_Position; 348 void main() 349 { 350 gl_Position = vec4(inputAttribute); 351 dx_Position = 0.0; 352 } 353 ); 354 355 const std::string &fragmentShaderSource = SHADER_SOURCE 356 ( 357 precision mediump float; 358 359 varying float dx_Position; 360 361 void main() 362 { 363 gl_FragColor = vec4(dx_Position, 0, 0, 1); 364 } 365 ); 366 367 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 368 EXPECT_NE(0u, program); 369} 370 371TEST_F(GLSLTest, ElseIfRewriting) 372{ 373 const std::string &vertexShaderSource = 374 "attribute vec4 a_position;\n" 375 "varying float v;\n" 376 "void main() {\n" 377 " gl_Position = a_position;\n" 378 " v = 1.0;\n" 379 " if (a_position.x <= 0.5) {\n" 380 " v = 0.0;\n" 381 " } else if (a_position.x >= 0.5) {\n" 382 " v = 2.0;\n" 383 " }\n" 384 "}\n"; 385 386 const std::string &fragmentShaderSource = 387 "precision highp float;\n" 388 "varying float v;\n" 389 "void main() {\n" 390 " vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n" 391 " if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n" 392 " if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n" 393 " gl_FragColor = color;\n" 394 "}\n"; 395 396 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 397 ASSERT_NE(0u, program); 398 399 drawQuad(program, "a_position", 0.5f); 400 swapBuffers(); 401 402 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255); 403 EXPECT_PIXEL_EQ(getWindowWidth()-1, 0, 0, 255, 0, 255); 404} 405 406TEST_F(GLSLTest, TwoElseIfRewriting) 407{ 408 const std::string &vertexShaderSource = 409 "attribute vec4 a_position;\n" 410 "varying float v;\n" 411 "void main() {\n" 412 " gl_Position = a_position;\n" 413 " if (a_position.x == 0.0) {\n" 414 " v = 1.0;\n" 415 " } else if (a_position.x > 0.5) {\n" 416 " v = 0.0;\n" 417 " } else if (a_position.x > 0.75) {\n" 418 " v = 0.5;\n" 419 " }\n" 420 "}\n"; 421 422 const std::string &fragmentShaderSource = 423 "precision highp float;\n" 424 "varying float v;\n" 425 "void main() {\n" 426 " gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n" 427 "}\n"; 428 429 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 430 EXPECT_NE(0u, program); 431} 432 433TEST_F(GLSLTest, InvariantVaryingOut) 434{ 435 const std::string fragmentShaderSource = SHADER_SOURCE 436 ( 437 precision mediump float; 438 varying float v_varying; 439 void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); } 440 ); 441 442 const std::string vertexShaderSource = SHADER_SOURCE 443 ( 444 attribute vec4 a_position; 445 invariant varying float v_varying; 446 void main() { v_varying = a_position.x; gl_Position = a_position; } 447 ); 448 449 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 450 EXPECT_NE(0u, program); 451} 452 453TEST_F(GLSLTest, FrontFacingAndVarying) 454{ 455 const std::string vertexShaderSource = SHADER_SOURCE 456 ( 457 attribute vec4 a_position; 458 varying float v_varying; 459 void main() 460 { 461 v_varying = a_position.x; 462 gl_Position = a_position; 463 } 464 ); 465 466 const std::string fragmentShaderSource = SHADER_SOURCE 467 ( 468 precision mediump float; 469 varying float v_varying; 470 void main() 471 { 472 vec4 c; 473 474 if (gl_FrontFacing) 475 { 476 c = vec4(v_varying, 0, 0, 1.0); 477 } 478 else 479 { 480 c = vec4(0, v_varying, 0, 1.0); 481 } 482 gl_FragColor = c; 483 } 484 ); 485 486 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 487 EXPECT_NE(0u, program); 488} 489 490TEST_F(GLSLTest, InvariantVaryingIn) 491{ 492 const std::string fragmentShaderSource = SHADER_SOURCE 493 ( 494 precision mediump float; 495 invariant varying float v_varying; 496 void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); } 497 ); 498 499 const std::string vertexShaderSource = SHADER_SOURCE 500 ( 501 attribute vec4 a_position; 502 varying float v_varying; 503 void main() { v_varying = a_position.x; gl_Position = a_position; } 504 ); 505 506 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 507 EXPECT_NE(0u, program); 508} 509 510TEST_F(GLSLTest, InvariantVaryingBoth) 511{ 512 const std::string fragmentShaderSource = SHADER_SOURCE 513 ( 514 precision mediump float; 515 invariant varying float v_varying; 516 void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); } 517 ); 518 519 const std::string vertexShaderSource = SHADER_SOURCE 520 ( 521 attribute vec4 a_position; 522 invariant varying float v_varying; 523 void main() { v_varying = a_position.x; gl_Position = a_position; } 524 ); 525 526 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 527 EXPECT_NE(0u, program); 528} 529 530TEST_F(GLSLTest, InvariantGLPosition) 531{ 532 const std::string fragmentShaderSource = SHADER_SOURCE 533 ( 534 precision mediump float; 535 varying float v_varying; 536 void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); } 537 ); 538 539 const std::string vertexShaderSource = SHADER_SOURCE 540 ( 541 attribute vec4 a_position; 542 invariant gl_Position; 543 varying float v_varying; 544 void main() { v_varying = a_position.x; gl_Position = a_position; } 545 ); 546 547 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 548 EXPECT_NE(0u, program); 549} 550 551TEST_F(GLSLTest, InvariantAll) 552{ 553 const std::string fragmentShaderSource = SHADER_SOURCE 554 ( 555 precision mediump float; 556 varying float v_varying; 557 void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); } 558 ); 559 560 const std::string vertexShaderSource = 561 "#pragma STDGL invariant(all)\n" 562 "attribute vec4 a_position;\n" 563 "varying float v_varying;\n" 564 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n"; 565 566 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 567 EXPECT_NE(0u, program); 568} 569 570TEST_F(GLSLTest, MaxVaryingVec3) 571{ 572 GLint maxVaryings = 0; 573 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); 574 575 std::string fragmentShaderSource; 576 std::string vertexShaderSource; 577 578 GenerateGLSLWithVaryings(0, 0, 0, 0, maxVaryings, 0, &fragmentShaderSource, &vertexShaderSource); 579 580 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 581 EXPECT_NE(0u, program); 582} 583 584TEST_F(GLSLTest, MaxVaryingVec3Array) 585{ 586 GLint maxVaryings = 0; 587 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); 588 589 std::string fragmentShaderSource; 590 std::string vertexShaderSource; 591 592 GenerateGLSLWithVaryings(0, 0, 0, 0, 0, maxVaryings / 2, &fragmentShaderSource, &vertexShaderSource); 593 594 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 595 EXPECT_NE(0u, program); 596} 597 598TEST_F(GLSLTest, MaxVaryingVec3AndOneFloat) 599{ 600 GLint maxVaryings = 0; 601 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); 602 603 std::string fragmentShaderSource; 604 std::string vertexShaderSource; 605 606 GenerateGLSLWithVaryings(1, 0, 0, 0, maxVaryings, 0, &fragmentShaderSource, &vertexShaderSource); 607 608 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 609 EXPECT_NE(0u, program); 610} 611 612TEST_F(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray) 613{ 614 GLint maxVaryings = 0; 615 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); 616 617 std::string fragmentShaderSource; 618 std::string vertexShaderSource; 619 620 GenerateGLSLWithVaryings(0, 1, 0, 0, 0, maxVaryings / 2, &fragmentShaderSource, &vertexShaderSource); 621 622 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 623 EXPECT_NE(0u, program); 624} 625 626TEST_F(GLSLTest, TwiceMaxVaryingVec2) 627{ 628 GLint maxVaryings = 0; 629 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); 630 631 std::string fragmentShaderSource; 632 std::string vertexShaderSource; 633 634 GenerateGLSLWithVaryings(0, 0, 2 * maxVaryings, 0, 0, 0, &fragmentShaderSource, &vertexShaderSource); 635 636 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 637 EXPECT_NE(0u, program); 638} 639 640TEST_F(GLSLTest, MaxVaryingVec2Arrays) 641{ 642 GLint maxVaryings = 0; 643 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); 644 645 std::string fragmentShaderSource; 646 std::string vertexShaderSource; 647 648 GenerateGLSLWithVaryings(0, 0, 0, maxVaryings, 0, 0, &fragmentShaderSource, &vertexShaderSource); 649 650 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 651 EXPECT_NE(0u, program); 652} 653 654TEST_F(GLSLTest, MaxPlusOneVaryingVec3) 655{ 656 GLint maxVaryings = 0; 657 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); 658 659 std::string fragmentShaderSource; 660 std::string vertexShaderSource; 661 662 GenerateGLSLWithVaryings(0, 0, 0, 0, maxVaryings + 1, 0, &fragmentShaderSource, &vertexShaderSource); 663 664 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 665 EXPECT_EQ(0u, program); 666} 667 668TEST_F(GLSLTest, MaxPlusOneVaryingVec3Array) 669{ 670 GLint maxVaryings = 0; 671 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); 672 673 std::string fragmentShaderSource; 674 std::string vertexShaderSource; 675 676 GenerateGLSLWithVaryings(0, 0, 0, 0, 0, maxVaryings / 2 + 1, &fragmentShaderSource, &vertexShaderSource); 677 678 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 679 EXPECT_EQ(0u, program); 680} 681 682TEST_F(GLSLTest, MaxVaryingVec3AndOneVec2) 683{ 684 GLint maxVaryings = 0; 685 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); 686 687 std::string fragmentShaderSource; 688 std::string vertexShaderSource; 689 690 GenerateGLSLWithVaryings(0, 0, 1, 0, maxVaryings, 0, &fragmentShaderSource, &vertexShaderSource); 691 692 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 693 EXPECT_EQ(0u, program); 694} 695 696TEST_F(GLSLTest, MaxPlusOneVaryingVec2) 697{ 698 GLint maxVaryings = 0; 699 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); 700 701 std::string fragmentShaderSource; 702 std::string vertexShaderSource; 703 704 GenerateGLSLWithVaryings(0, 0, 2 * maxVaryings + 1, 0, 0, 0, &fragmentShaderSource, &vertexShaderSource); 705 706 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 707 EXPECT_EQ(0u, program); 708} 709 710TEST_F(GLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray) 711{ 712 GLint maxVaryings = 0; 713 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); 714 715 std::string fragmentShaderSource; 716 std::string vertexShaderSource; 717 718 GenerateGLSLWithVaryings(0, maxVaryings / 2 + 1, 0, 0, 0, maxVaryings / 2, &fragmentShaderSource, &vertexShaderSource); 719 720 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); 721 EXPECT_EQ(0u, program); 722} 723