1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.0 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 Shader compilation performance tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es3pShaderCompilationCases.hpp" 25 #include "tcuTestLog.hpp" 26 #include "tcuVector.hpp" 27 #include "tcuMatrix.hpp" 28 #include "tcuTextureUtil.hpp" 29 #include "tcuPlatform.hpp" 30 #include "tcuCommandLine.hpp" 31 #include "tcuRenderTarget.hpp" 32 #include "tcuCPUWarmup.hpp" 33 #include "tcuStringTemplate.hpp" 34 #include "gluTexture.hpp" 35 #include "gluPixelTransfer.hpp" 36 #include "gluRenderContext.hpp" 37 #include "deStringUtil.hpp" 38 #include "deRandom.hpp" 39 #include "deClock.h" 40 #include "deMath.h" 41 42 #include "glwEnums.hpp" 43 #include "glwFunctions.hpp" 44 45 #include <map> 46 #include <algorithm> 47 #include <limits> 48 #include <iomanip> 49 50 using tcu::TestLog; 51 using tcu::Vec3; 52 using tcu::Vec4; 53 using tcu::Mat3; 54 using tcu::Mat4; 55 using std::string; 56 using std::vector; 57 using namespace glw; // GL types 58 59 namespace deqp 60 { 61 62 namespace gles3 63 { 64 65 namespace Performance 66 { 67 68 static const bool WARMUP_CPU_AT_BEGINNING_OF_CASE = false; 69 static const bool WARMUP_CPU_BEFORE_EACH_MEASUREMENT = true; 70 71 static const int MAX_VIEWPORT_WIDTH = 64; 72 static const int MAX_VIEWPORT_HEIGHT = 64; 73 74 static const int DEFAULT_MINIMUM_MEASUREMENT_COUNT = 15; 75 static const float RELATIVE_MEDIAN_ABSOLUTE_DEVIATION_THRESHOLD = 0.05f; 76 77 // Texture size for the light shader and texture lookup shader cases. 78 static const int TEXTURE_WIDTH = 64; 79 static const int TEXTURE_HEIGHT = 64; 80 81 template <typename T> 82 inline string toStringWithPadding (T value, int minLength) 83 { 84 std::ostringstream s; 85 s << std::setfill('0') << std::setw(minLength) << value; 86 return s.str(); 87 } 88 89 // Add some whitespace and comments to str. They should depend on uniqueNumber. 90 static string strWithWhiteSpaceAndComments (const string& str, deUint32 uniqueNumber) 91 { 92 string res(""); 93 94 // Find the first newline. 95 int firstLineEndNdx = 0; 96 while (firstLineEndNdx < (int)str.size() && str[firstLineEndNdx] != '\n') 97 { 98 res += str[firstLineEndNdx]; 99 firstLineEndNdx++; 100 } 101 res += '\n'; 102 DE_ASSERT(firstLineEndNdx < (int)str.size()); 103 104 // Add the whitespaces and comments just after the first line. 105 106 de::Random rnd (uniqueNumber); 107 int numWS = rnd.getInt(10, 20); 108 109 for (int i = 0; i < numWS; i++) 110 res += " \t\n"[rnd.getInt(0, 2)]; 111 112 res += "/* unique comment " + de::toString(uniqueNumber) + " */\n"; 113 res += "// unique comment " + de::toString(uniqueNumber) + "\n"; 114 115 for (int i = 0; i < numWS; i++) 116 res += " \t\n"[rnd.getInt(0, 2)]; 117 118 // Add the rest of the string. 119 res.append(&str.c_str()[firstLineEndNdx + 1]); 120 121 return res; 122 } 123 124 //! Helper for computing relative magnitudes while avoiding division by zero. 125 static float hackySafeRelativeResult (float x, float y) 126 { 127 // \note A possible case is that x is standard deviation, and y is average 128 // (or similarly for median or some such). So, if y is 0, that 129 // probably means that x is also 0(ish) (because in practice we're 130 // dealing with non-negative values, in which case an average of 0 131 // implies that the samples are all 0 - note that the same isn't 132 // strictly true for things like median) so a relative result of 0 133 // wouldn't be that far from the truth. 134 return y == 0.0f ? 0.0f : x/y; 135 } 136 137 template <typename T> 138 static float vectorFloatAverage (const vector<T>& v) 139 { 140 DE_ASSERT(!v.empty()); 141 float result = 0.0f; 142 for (int i = 0; i < (int)v.size(); i++) 143 result += (float)v[i]; 144 return result / (float)v.size(); 145 } 146 147 template <typename T> 148 static float vectorFloatMedian (const vector<T>& v) 149 { 150 DE_ASSERT(!v.empty()); 151 vector<T> temp = v; 152 std::sort(temp.begin(), temp.end()); 153 return temp.size() % 2 == 0 154 ? 0.5f * ((float)temp[temp.size()/2-1] + (float)temp[temp.size()/2]) 155 : (float)temp[temp.size()/2]; 156 } 157 158 template <typename T> 159 static float vectorFloatMinimum (const vector<T>& v) 160 { 161 DE_ASSERT(!v.empty()); 162 return (float)*std::min_element(v.begin(), v.end()); 163 } 164 165 template <typename T> 166 static float vectorFloatMaximum (const vector<T>& v) 167 { 168 DE_ASSERT(!v.empty()); 169 return (float)*std::max_element(v.begin(), v.end()); 170 } 171 172 template <typename T> 173 static float vectorFloatStandardDeviation (const vector<T>& v) 174 { 175 float average = vectorFloatAverage(v); 176 float result = 0.0f; 177 for (int i = 0; i < (int)v.size(); i++) 178 { 179 float d = (float)v[i] - average; 180 result += d*d; 181 } 182 return deFloatSqrt(result/(float)v.size()); 183 } 184 185 template <typename T> 186 static float vectorFloatRelativeStandardDeviation (const vector<T>& v) 187 { 188 return hackySafeRelativeResult(vectorFloatStandardDeviation(v), vectorFloatAverage(v)); 189 } 190 191 template <typename T> 192 static float vectorFloatMedianAbsoluteDeviation (const vector<T>& v) 193 { 194 float median = vectorFloatMedian(v); 195 vector<float> absoluteDeviations (v.size()); 196 197 for (int i = 0; i < (int)v.size(); i++) 198 absoluteDeviations[i] = deFloatAbs((float)v[i] - median); 199 200 return vectorFloatMedian(absoluteDeviations); 201 } 202 203 template <typename T> 204 static float vectorFloatRelativeMedianAbsoluteDeviation (const vector<T>& v) 205 { 206 return hackySafeRelativeResult(vectorFloatMedianAbsoluteDeviation(v), vectorFloatMedian(v)); 207 } 208 209 template <typename T> 210 static float vectorFloatMaximumMinusMinimum (const vector<T>& v) 211 { 212 return vectorFloatMaximum(v) - vectorFloatMinimum(v); 213 } 214 215 template <typename T> 216 static float vectorFloatRelativeMaximumMinusMinimum (const vector<T>& v) 217 { 218 return hackySafeRelativeResult(vectorFloatMaximumMinusMinimum(v), vectorFloatMaximum(v)); 219 } 220 221 template <typename T> 222 static vector<T> vectorLowestPercentage (const vector<T>& v, float factor) 223 { 224 DE_ASSERT(0.0f < factor && factor <= 1.0f); 225 226 int targetSize = (int)(deFloatCeil(factor*(float)v.size())); 227 vector<T> temp = v; 228 std::sort(temp.begin(), temp.end()); 229 230 while ((int)temp.size() > targetSize) 231 temp.pop_back(); 232 233 return temp; 234 } 235 236 template <typename T> 237 static float vectorFloatFirstQuartile (const vector<T>& v) 238 { 239 return vectorFloatMedian(vectorLowestPercentage(v, 0.5f)); 240 } 241 242 // Helper function for combining 4 tcu::Vec4's into one tcu::Vector<float, 16>. 243 static tcu::Vector<float, 16> combineVec4ToVec16 (const Vec4& a0, const Vec4& a1, const Vec4& a2, const Vec4& a3) 244 { 245 tcu::Vector<float, 16> result; 246 247 for (int vecNdx = 0; vecNdx < 4; vecNdx++) 248 { 249 const Vec4& srcVec = vecNdx == 0 ? a0 : vecNdx == 1 ? a1 : vecNdx == 2 ? a2 : a3; 250 for (int i = 0; i < 4; i++) 251 result[vecNdx*4 + i] = srcVec[i]; 252 } 253 254 return result; 255 } 256 257 // Helper function for extending an n-sized (n <= 16) vector to a 16-sized vector (padded with zeros). 258 template <int Size> 259 static tcu::Vector<float, 16> vecTo16 (const tcu::Vector<float, Size>& vec) 260 { 261 DE_STATIC_ASSERT(Size <= 16); 262 263 tcu::Vector<float, 16> res(0.0f); 264 265 for (int i = 0; i < Size; i++) 266 res[i] = vec[i]; 267 268 return res; 269 } 270 271 // Helper function for extending an n-sized (n <= 16) array to a 16-sized vector (padded with zeros). 272 template <int Size> 273 static tcu::Vector<float, 16> arrTo16 (const tcu::Array<float, Size>& arr) 274 { 275 DE_STATIC_ASSERT(Size <= 16); 276 277 tcu::Vector<float, 16> res(0.0f); 278 279 for(int i = 0; i < Size; i++) 280 res[i] = arr[i]; 281 282 return res; 283 } 284 285 static string getShaderInfoLog (const glw::Functions& gl, deUint32 shader) 286 { 287 string result; 288 int infoLogLen = 0; 289 vector<char> infoLogBuf; 290 291 gl.getShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLen); 292 infoLogBuf.resize(infoLogLen + 1); 293 gl.getShaderInfoLog(shader, infoLogLen + 1, DE_NULL, &infoLogBuf[0]); 294 result = &infoLogBuf[0]; 295 296 return result; 297 } 298 299 static string getProgramInfoLog (const glw::Functions& gl, deUint32 program) 300 { 301 string result; 302 int infoLogLen = 0; 303 vector<char> infoLogBuf; 304 305 gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLen); 306 infoLogBuf.resize(infoLogLen + 1); 307 gl.getProgramInfoLog(program, infoLogLen + 1, DE_NULL, &infoLogBuf[0]); 308 result = &infoLogBuf[0]; 309 310 return result; 311 } 312 313 enum LightType 314 { 315 LIGHT_DIRECTIONAL = 0, 316 LIGHT_POINT, 317 318 LIGHT_LAST, 319 }; 320 321 enum LoopType 322 { 323 LOOP_TYPE_STATIC = 0, 324 LOOP_TYPE_UNIFORM, 325 LOOP_TYPE_DYNAMIC, 326 327 LOOP_LAST 328 }; 329 330 // For texture lookup cases: which texture lookups are inside a conditional statement. 331 enum ConditionalUsage 332 { 333 CONDITIONAL_USAGE_NONE = 0, // No conditional statements. 334 CONDITIONAL_USAGE_FIRST_HALF, // First numLookUps/2 lookups are inside a conditional statement. 335 CONDITIONAL_USAGE_EVERY_OTHER, // First, third etc. lookups are inside conditional statements. 336 337 CONDITIONAL_USAGE_LAST 338 }; 339 340 enum ConditionalType 341 { 342 CONDITIONAL_TYPE_STATIC = 0, 343 CONDITIONAL_TYPE_UNIFORM, 344 CONDITIONAL_TYPE_DYNAMIC, 345 346 CONDITIONAL_TYPE_LAST 347 }; 348 349 // For the invalid shader compilation tests; what kind of invalidity a shader shall contain. 350 enum ShaderValidity 351 { 352 SHADER_VALIDITY_VALID = 0, 353 SHADER_VALIDITY_INVALID_CHAR, 354 SHADER_VALIDITY_SEMANTIC_ERROR, 355 356 SHADER_VALIDITY_LAST 357 }; 358 359 class ShaderCompilerCase : public TestCase 360 { 361 public: 362 struct AttribSpec 363 { 364 string name; 365 tcu::Vector<float, 16> value; 366 367 AttribSpec (const string& n, const tcu::Vector<float, 16>& v) : name(n), value(v) {} 368 }; 369 370 struct UniformSpec 371 { 372 enum Type 373 { 374 TYPE_FLOAT = 0, 375 TYPE_VEC2, 376 TYPE_VEC3, 377 TYPE_VEC4, 378 379 TYPE_MAT3, 380 TYPE_MAT4, 381 382 TYPE_TEXTURE_UNIT, 383 384 TYPE_LAST 385 }; 386 387 string name; 388 Type type; 389 tcu::Vector<float, 16> value; 390 391 UniformSpec (const string& n, Type t, float v) : name(n), type(t), value(v) {} 392 UniformSpec (const string& n, Type t, const tcu::Vector<float, 16>& v) : name(n), type(t), value(v) {} 393 }; 394 395 ShaderCompilerCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments); 396 ~ShaderCompilerCase (void); 397 398 void init (void); 399 400 IterateResult iterate (void); 401 402 protected: 403 struct ProgramContext 404 { 405 string vertShaderSource; 406 string fragShaderSource; 407 vector<AttribSpec> vertexAttributes; 408 vector<UniformSpec> uniforms; 409 }; 410 411 deUint32 getSpecializationID (int measurementNdx) const; // Return an ID that depends on the case ID, current measurement index and time; used to specialize attribute names etc. (avoid shader caching). 412 virtual ProgramContext generateShaderData (int measurementNdx) const = 0; // Generate shader sources and inputs. Attribute etc. names depend on above name specialization. 413 414 private: 415 struct Measurement 416 { 417 // \note All times in microseconds. 32-bit integers would probably suffice (would need over an hour of test case runtime to overflow), but better safe than sorry. 418 deInt64 sourceSetTime; 419 deInt64 vertexCompileTime; 420 deInt64 fragmentCompileTime; 421 deInt64 programLinkTime; 422 deInt64 firstInputSetTime; 423 deInt64 firstDrawTime; 424 425 deInt64 secondInputSetTime; 426 deInt64 secondDrawTime; 427 428 deInt64 firstPhase (void) const { return sourceSetTime + vertexCompileTime + fragmentCompileTime + programLinkTime + firstInputSetTime + firstDrawTime; } 429 deInt64 secondPhase (void) const { return secondInputSetTime + secondDrawTime; } 430 431 deInt64 totalTimeWithoutDraw (void) const { return firstPhase() - de::min(secondPhase(), firstInputSetTime + firstDrawTime); } 432 433 Measurement (deInt64 sourceSetTime_, 434 deInt64 vertexCompileTime_, 435 deInt64 fragmentCompileTime_, 436 deInt64 programLinkTime_, 437 deInt64 firstInputSetTime_, 438 deInt64 firstDrawTime_, 439 deInt64 secondInputSetTime_, 440 deInt64 secondDrawTime_) 441 : sourceSetTime (sourceSetTime_) 442 , vertexCompileTime (vertexCompileTime_) 443 , fragmentCompileTime (fragmentCompileTime_) 444 , programLinkTime (programLinkTime_) 445 , firstInputSetTime (firstInputSetTime_) 446 , firstDrawTime (firstDrawTime_) 447 , secondInputSetTime (secondInputSetTime_) 448 , secondDrawTime (secondDrawTime_) 449 { 450 } 451 }; 452 453 struct ShadersAndProgram 454 { 455 deUint32 vertShader; 456 deUint32 fragShader; 457 deUint32 program; 458 }; 459 460 struct Logs 461 { 462 string vert; 463 string frag; 464 string link; 465 }; 466 467 struct BuildInfo 468 { 469 bool vertCompileSuccess; 470 bool fragCompileSuccess; 471 bool linkSuccess; 472 473 Logs logs; 474 }; 475 476 ShadersAndProgram createShadersAndProgram (void) const; 477 void setShaderSources (deUint32 vertShader, deUint32 fragShader, const ProgramContext&) const; 478 bool compileShader (deUint32 shader) const; 479 bool linkAndUseProgram (deUint32 program) const; 480 void setShaderInputs (deUint32 program, const ProgramContext&) const; // Set attribute pointers and uniforms. 481 void draw (void) const; // Clear, draw and finish. 482 void cleanup (const ShadersAndProgram&, const ProgramContext&, bool linkSuccess) const; // Do GL deinitializations. 483 484 Logs getLogs (const ShadersAndProgram&) const; 485 void logProgramData (const BuildInfo&, const ProgramContext&) const; 486 bool goodEnoughMeasurements (const vector<Measurement>& measurements) const; 487 488 int m_viewportWidth; 489 int m_viewportHeight; 490 491 bool m_avoidCache; // If true, avoid caching between measurements as well (and not only between test cases). 492 bool m_addWhitespaceAndComments; // If true, add random whitespace and comments to the source (good caching should ignore those). 493 deUint32 m_startHash; // A hash from case id and time, at the time of construction. 494 495 int m_minimumMeasurementCount; 496 int m_maximumMeasurementCount; 497 }; 498 499 class ShaderCompilerLightCase : public ShaderCompilerCase 500 { 501 public: 502 ShaderCompilerLightCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments, bool isVertexCase, int numLights, LightType lightType); 503 ~ShaderCompilerLightCase (void); 504 505 void init (void); 506 void deinit (void); 507 508 protected: 509 ProgramContext generateShaderData (int measurementNdx) const; 510 511 private: 512 int m_numLights; 513 bool m_isVertexCase; 514 LightType m_lightType; 515 glu::Texture2D* m_texture; 516 }; 517 518 class ShaderCompilerTextureCase : public ShaderCompilerCase 519 { 520 public: 521 ShaderCompilerTextureCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments, int numLookups, ConditionalUsage conditionalUsage, ConditionalType conditionalType); 522 ~ShaderCompilerTextureCase (void); 523 524 void init (void); 525 void deinit (void); 526 527 protected: 528 ProgramContext generateShaderData (int measurementNdx) const; 529 530 private: 531 int m_numLookups; 532 vector<glu::Texture2D*> m_textures; 533 ConditionalUsage m_conditionalUsage; 534 ConditionalType m_conditionalType; 535 }; 536 537 class ShaderCompilerLoopCase : public ShaderCompilerCase 538 { 539 public: 540 ShaderCompilerLoopCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments, bool isVertexCase, LoopType type, int numLoopIterations, int nestingDepth); 541 ~ShaderCompilerLoopCase (void); 542 543 protected: 544 ProgramContext generateShaderData (int measurementNdx) const; 545 546 private: 547 int m_numLoopIterations; 548 int m_nestingDepth; 549 bool m_isVertexCase; 550 LoopType m_type; 551 }; 552 553 class ShaderCompilerOperCase : public ShaderCompilerCase 554 { 555 public: 556 ShaderCompilerOperCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments, bool isVertexCase, const char* oper, int numOperations); 557 ~ShaderCompilerOperCase (void); 558 559 protected: 560 ProgramContext generateShaderData (int measurementNdx) const; 561 562 private: 563 string m_oper; 564 int m_numOperations; 565 bool m_isVertexCase; 566 }; 567 568 class ShaderCompilerMandelbrotCase : public ShaderCompilerCase 569 { 570 public: 571 ShaderCompilerMandelbrotCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments, int numFractalIterations); 572 ~ShaderCompilerMandelbrotCase (void); 573 574 protected: 575 ProgramContext generateShaderData (int measurementNdx) const; 576 577 private: 578 int m_numFractalIterations; 579 }; 580 581 class InvalidShaderCompilerCase : public TestCase 582 { 583 public: 584 // \note Similar to the ShaderValidity enum, but doesn't have a VALID type. 585 enum InvalidityType 586 { 587 INVALIDITY_INVALID_CHAR = 0, 588 INVALIDITY_SEMANTIC_ERROR, 589 590 INVALIDITY_LAST 591 }; 592 593 InvalidShaderCompilerCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType); 594 ~InvalidShaderCompilerCase (void); 595 596 IterateResult iterate (void); 597 598 protected: 599 struct ProgramContext 600 { 601 string vertShaderSource; 602 string fragShaderSource; 603 }; 604 605 deUint32 getSpecializationID (int measurementNdx) const; // Return an ID that depends on the case ID, current measurement index and time; used to specialize attribute names etc. (avoid shader caching). 606 virtual ProgramContext generateShaderSources (int measurementNdx) const = 0; // Generate shader sources. Attribute etc. names depend on above name specialization. 607 608 InvalidityType m_invalidityType; 609 610 private: 611 struct Measurement 612 { 613 // \note All times in microseconds. 32-bit integers would probably suffice (would need over an hour of test case runtime to overflow), but better safe than sorry. 614 deInt64 sourceSetTime; 615 deInt64 vertexCompileTime; 616 deInt64 fragmentCompileTime; 617 618 deInt64 totalTime (void) const { return sourceSetTime + vertexCompileTime + fragmentCompileTime; } 619 620 Measurement (deInt64 sourceSetTime_, 621 deInt64 vertexCompileTime_, 622 deInt64 fragmentCompileTime_) 623 : sourceSetTime (sourceSetTime_) 624 , vertexCompileTime (vertexCompileTime_) 625 , fragmentCompileTime (fragmentCompileTime_) 626 { 627 } 628 }; 629 630 struct Shaders 631 { 632 deUint32 vertShader; 633 deUint32 fragShader; 634 }; 635 636 struct Logs 637 { 638 string vert; 639 string frag; 640 }; 641 642 struct BuildInfo 643 { 644 bool vertCompileSuccess; 645 bool fragCompileSuccess; 646 647 Logs logs; 648 }; 649 650 Shaders createShaders (void) const; 651 void setShaderSources (const Shaders&, const ProgramContext&) const; 652 bool compileShader (deUint32 shader) const; 653 void cleanup (const Shaders&) const; 654 655 Logs getLogs (const Shaders&) const; 656 void logProgramData (const BuildInfo&, const ProgramContext&) const; 657 bool goodEnoughMeasurements (const vector<Measurement>& measurements) const; 658 659 deUint32 m_startHash; // A hash from case id and time, at the time of construction. 660 661 int m_minimumMeasurementCount; 662 int m_maximumMeasurementCount; 663 }; 664 665 class InvalidShaderCompilerLightCase : public InvalidShaderCompilerCase 666 { 667 public: 668 InvalidShaderCompilerLightCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, bool isVertexCase, int numLights, LightType lightType); 669 ~InvalidShaderCompilerLightCase (void); 670 671 protected: 672 ProgramContext generateShaderSources (int measurementNdx) const; 673 674 private: 675 bool m_isVertexCase; 676 int m_numLights; 677 LightType m_lightType; 678 }; 679 680 class InvalidShaderCompilerTextureCase : public InvalidShaderCompilerCase 681 { 682 public: 683 InvalidShaderCompilerTextureCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, int numLookups, ConditionalUsage conditionalUsage, ConditionalType conditionalType); 684 ~InvalidShaderCompilerTextureCase (void); 685 686 protected: 687 ProgramContext generateShaderSources (int measurementNdx) const; 688 689 private: 690 int m_numLookups; 691 ConditionalUsage m_conditionalUsage; 692 ConditionalType m_conditionalType; 693 }; 694 695 class InvalidShaderCompilerLoopCase : public InvalidShaderCompilerCase 696 { 697 public: 698 InvalidShaderCompilerLoopCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, bool , LoopType type, int numLoopIterations, int nestingDepth); 699 ~InvalidShaderCompilerLoopCase (void); 700 701 protected: 702 ProgramContext generateShaderSources (int measurementNdx) const; 703 704 private: 705 bool m_isVertexCase; 706 int m_numLoopIterations; 707 int m_nestingDepth; 708 LoopType m_type; 709 }; 710 711 class InvalidShaderCompilerOperCase : public InvalidShaderCompilerCase 712 { 713 public: 714 InvalidShaderCompilerOperCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, bool isVertexCase, const char* oper, int numOperations); 715 ~InvalidShaderCompilerOperCase (void); 716 717 protected: 718 ProgramContext generateShaderSources (int measurementNdx) const; 719 720 private: 721 bool m_isVertexCase; 722 string m_oper; 723 int m_numOperations; 724 }; 725 726 class InvalidShaderCompilerMandelbrotCase : public InvalidShaderCompilerCase 727 { 728 public: 729 InvalidShaderCompilerMandelbrotCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, int numFractalIterations); 730 ~InvalidShaderCompilerMandelbrotCase (void); 731 732 protected: 733 ProgramContext generateShaderSources (int measurementNdx) const; 734 735 private: 736 int m_numFractalIterations; 737 }; 738 739 static string getNameSpecialization (deUint32 id) 740 { 741 return "_" + toStringWithPadding(id, 10); 742 } 743 744 // Substitute StringTemplate parameters for attribute/uniform/varying name and constant expression specialization as well as possible shader compilation error causes. 745 static string specializeShaderSource (const string& shaderSourceTemplate, deUint32 cacheAvoidanceID, ShaderValidity validity) 746 { 747 std::map<string, string> params; 748 params["NAME_SPEC"] = getNameSpecialization(cacheAvoidanceID); 749 params["FLOAT01"] = de::floatToString((float)cacheAvoidanceID / (float)(std::numeric_limits<deUint32>::max()), 6); 750 params["SEMANTIC_ERROR"] = validity != SHADER_VALIDITY_SEMANTIC_ERROR ? "" : "\tfloat invalid = sin(1.0, 2.0);\n"; 751 params["INVALID_CHAR"] = validity != SHADER_VALIDITY_INVALID_CHAR ? "" : "@\n"; // \note Some implementations crash when the invalid character is the last character in the source, so use newline. 752 753 return tcu::StringTemplate(shaderSourceTemplate).specialize(params); 754 } 755 756 // Function for generating the vertex shader of a (directional or point) light case. 757 static string lightVertexTemplate (int numLights, bool isVertexCase, LightType lightType) 758 { 759 string resultTemplate; 760 761 resultTemplate += 762 "#version 300 es\n" 763 "in highp vec4 a_position${NAME_SPEC};\n" 764 "in mediump vec3 a_normal${NAME_SPEC};\n" 765 "in mediump vec4 a_texCoord0${NAME_SPEC};\n" 766 "uniform mediump vec3 u_material_ambientColor${NAME_SPEC};\n" 767 "uniform mediump vec4 u_material_diffuseColor${NAME_SPEC};\n" 768 "uniform mediump vec3 u_material_emissiveColor${NAME_SPEC};\n" 769 "uniform mediump vec3 u_material_specularColor${NAME_SPEC};\n" 770 "uniform mediump float u_material_shininess${NAME_SPEC};\n"; 771 772 for (int lightNdx = 0; lightNdx < numLights; lightNdx++) 773 { 774 string ndxStr = de::toString(lightNdx); 775 776 resultTemplate += 777 "uniform mediump vec3 u_light" + ndxStr + "_color${NAME_SPEC};\n" 778 "uniform mediump vec3 u_light" + ndxStr + "_direction${NAME_SPEC};\n"; 779 780 if (lightType == LIGHT_POINT) 781 resultTemplate += 782 "uniform mediump vec4 u_light" + ndxStr + "_position${NAME_SPEC};\n" 783 "uniform mediump float u_light" + ndxStr + "_constantAttenuation${NAME_SPEC};\n" 784 "uniform mediump float u_light" + ndxStr + "_linearAttenuation${NAME_SPEC};\n" 785 "uniform mediump float u_light" + ndxStr + "_quadraticAttenuation${NAME_SPEC};\n"; 786 } 787 788 resultTemplate += 789 "uniform highp mat4 u_mvpMatrix${NAME_SPEC};\n" 790 "uniform highp mat4 u_modelViewMatrix${NAME_SPEC};\n" 791 "uniform mediump mat3 u_normalMatrix${NAME_SPEC};\n" 792 "uniform mediump mat4 u_texCoordMatrix0${NAME_SPEC};\n" 793 "out mediump vec4 v_color${NAME_SPEC};\n" 794 "out mediump vec2 v_texCoord0${NAME_SPEC};\n"; 795 796 if (!isVertexCase) 797 { 798 resultTemplate += "out mediump vec3 v_eyeNormal${NAME_SPEC};\n"; 799 800 if (lightType == LIGHT_POINT) 801 resultTemplate += 802 "out mediump vec3 v_directionToLight${NAME_SPEC}[" + de::toString(numLights) + "];\n" 803 "out mediump float v_distanceToLight${NAME_SPEC}[" + de::toString(numLights) + "];\n"; 804 } 805 806 resultTemplate += 807 "mediump vec3 direction (mediump vec4 from, mediump vec4 to)\n" 808 "{\n" 809 " return vec3(to.xyz * from.w - from.xyz * to.w);\n" 810 "}\n" 811 "\n" 812 "mediump vec3 computeLighting (\n" 813 " mediump vec3 directionToLight,\n" 814 " mediump vec3 halfVector,\n" 815 " mediump vec3 normal,\n" 816 " mediump vec3 lightColor,\n" 817 " mediump vec3 diffuseColor,\n" 818 " mediump vec3 specularColor,\n" 819 " mediump float shininess)\n" 820 "{\n" 821 " mediump float normalDotDirection = max(dot(normal, directionToLight), 0.0);\n" 822 " mediump vec3 color = normalDotDirection * diffuseColor * lightColor;\n" 823 "\n" 824 " if (normalDotDirection != 0.0)\n" 825 " color += pow(max(dot(normal, halfVector), 0.0), shininess) * specularColor * lightColor;\n" 826 "\n" 827 " return color;\n" 828 "}\n" 829 "\n"; 830 831 if (lightType == LIGHT_POINT) 832 resultTemplate += 833 "mediump float computeDistanceAttenuation (mediump float distToLight, mediump float constAtt, mediump float linearAtt, mediump float quadraticAtt)\n" 834 "{\n" 835 " return 1.0 / (constAtt + linearAtt * distToLight + quadraticAtt * distToLight * distToLight);\n" 836 "}\n" 837 "\n"; 838 839 resultTemplate += 840 "void main (void)\n" 841 "{\n" 842 " highp vec4 position = a_position${NAME_SPEC};\n" 843 " highp vec3 normal = a_normal${NAME_SPEC};\n" 844 " gl_Position = u_mvpMatrix${NAME_SPEC} * position * (0.95 + 0.05*${FLOAT01});\n" 845 " v_texCoord0${NAME_SPEC} = (u_texCoordMatrix0${NAME_SPEC} * a_texCoord0${NAME_SPEC}).xy;\n" 846 " mediump vec4 color = vec4(u_material_emissiveColor${NAME_SPEC}, u_material_diffuseColor${NAME_SPEC}.a);\n" 847 "\n" 848 " highp vec4 eyePosition = u_modelViewMatrix${NAME_SPEC} * position;\n" 849 " mediump vec3 eyeNormal = normalize(u_normalMatrix${NAME_SPEC} * normal);\n"; 850 851 if (!isVertexCase) 852 resultTemplate += "\tv_eyeNormal${NAME_SPEC} = eyeNormal;\n"; 853 854 resultTemplate += "\n"; 855 856 for (int lightNdx = 0; lightNdx < numLights; lightNdx++) 857 { 858 string ndxStr = de::toString(lightNdx); 859 860 resultTemplate += 861 " /* Light " + ndxStr + " */\n"; 862 863 if (lightType == LIGHT_POINT) 864 { 865 resultTemplate += 866 " mediump float distanceToLight" + ndxStr + " = distance(eyePosition, u_light" + ndxStr + "_position${NAME_SPEC});\n" 867 " mediump vec3 directionToLight" + ndxStr + " = normalize(direction(eyePosition, u_light" + ndxStr + "_position${NAME_SPEC}));\n"; 868 869 if (isVertexCase) 870 resultTemplate += 871 " mediump vec3 halfVector" + ndxStr + " = normalize(directionToLight" + ndxStr + " + vec3(0.0, 0.0, 1.0));\n" 872 " color.rgb += computeLighting(directionToLight" + ndxStr + ", halfVector" + ndxStr + ", eyeNormal, u_light" + ndxStr + "_color${NAME_SPEC}, u_material_diffuseColor${NAME_SPEC}.rgb, " 873 "u_material_specularColor${NAME_SPEC}, u_material_shininess${NAME_SPEC}) * computeDistanceAttenuation(distanceToLight" + ndxStr + ", u_light" + ndxStr + "_constantAttenuation${NAME_SPEC}, " 874 "u_light" + ndxStr + "_linearAttenuation${NAME_SPEC}, u_light" + ndxStr + "_quadraticAttenuation${NAME_SPEC});\n"; 875 else 876 resultTemplate += 877 " v_directionToLight${NAME_SPEC}[" + ndxStr + "] = directionToLight" + ndxStr + ";\n" 878 " v_distanceToLight${NAME_SPEC}[" + ndxStr + "] = distanceToLight" + ndxStr + ";\n"; 879 } 880 else if (lightType == LIGHT_DIRECTIONAL) 881 { 882 if (isVertexCase) 883 resultTemplate += 884 " mediump vec3 directionToLight" + ndxStr + " = -u_light" + ndxStr + "_direction${NAME_SPEC};\n" 885 " mediump vec3 halfVector" + ndxStr + " = normalize(directionToLight" + ndxStr + " + vec3(0.0, 0.0, 1.0));\n" 886 " color.rgb += computeLighting(directionToLight" + ndxStr + ", halfVector" + ndxStr + ", eyeNormal, u_light" + ndxStr + "_color${NAME_SPEC}, u_material_diffuseColor${NAME_SPEC}.rgb, u_material_specularColor${NAME_SPEC}, u_material_shininess${NAME_SPEC});\n"; 887 } 888 else 889 DE_ASSERT(DE_FALSE); 890 891 resultTemplate += "\n"; 892 } 893 894 resultTemplate += 895 " v_color${NAME_SPEC} = color;\n" 896 "${SEMANTIC_ERROR}" 897 "}\n" 898 "${INVALID_CHAR}"; 899 900 return resultTemplate; 901 } 902 903 // Function for generating the fragment shader of a (directional or point) light case. 904 static string lightFragmentTemplate (int numLights, bool isVertexCase, LightType lightType) 905 { 906 string resultTemplate; 907 908 resultTemplate += 909 "#version 300 es\n" 910 "layout(location = 0) out mediump vec4 o_color;\n"; 911 912 if (!isVertexCase) 913 { 914 resultTemplate += 915 "uniform mediump vec3 u_material_ambientColor${NAME_SPEC};\n" 916 "uniform mediump vec4 u_material_diffuseColor${NAME_SPEC};\n" 917 "uniform mediump vec3 u_material_emissiveColor${NAME_SPEC};\n" 918 "uniform mediump vec3 u_material_specularColor${NAME_SPEC};\n" 919 "uniform mediump float u_material_shininess${NAME_SPEC};\n"; 920 921 for (int lightNdx = 0; lightNdx < numLights; lightNdx++) 922 { 923 string ndxStr = de::toString(lightNdx); 924 925 resultTemplate += 926 "uniform mediump vec3 u_light" + ndxStr + "_color${NAME_SPEC};\n" 927 "uniform mediump vec3 u_light" + ndxStr + "_direction${NAME_SPEC};\n"; 928 929 if (lightType == LIGHT_POINT) 930 resultTemplate += 931 "uniform mediump vec4 u_light" + ndxStr + "_position${NAME_SPEC};\n" 932 "uniform mediump float u_light" + ndxStr + "_constantAttenuation${NAME_SPEC};\n" 933 "uniform mediump float u_light" + ndxStr + "_linearAttenuation${NAME_SPEC};\n" 934 "uniform mediump float u_light" + ndxStr + "_quadraticAttenuation${NAME_SPEC};\n"; 935 } 936 } 937 938 resultTemplate += 939 "uniform sampler2D u_sampler0${NAME_SPEC};\n" 940 "in mediump vec4 v_color${NAME_SPEC};\n" 941 "in mediump vec2 v_texCoord0${NAME_SPEC};\n"; 942 943 if (!isVertexCase) 944 { 945 resultTemplate += 946 "in mediump vec3 v_eyeNormal${NAME_SPEC};\n"; 947 948 if (lightType == LIGHT_POINT) 949 resultTemplate += 950 "in mediump vec3 v_directionToLight${NAME_SPEC}[" + de::toString(numLights) + "];\n" 951 "in mediump float v_distanceToLight${NAME_SPEC}[" + de::toString(numLights) + "];\n"; 952 953 resultTemplate += 954 "mediump vec3 direction (mediump vec4 from, mediump vec4 to)\n" 955 "{\n" 956 " return vec3(to.xyz * from.w - from.xyz * to.w);\n" 957 "}\n" 958 "\n"; 959 960 resultTemplate += 961 "mediump vec3 computeLighting (\n" 962 " mediump vec3 directionToLight,\n" 963 " mediump vec3 halfVector,\n" 964 " mediump vec3 normal,\n" 965 " mediump vec3 lightColor,\n" 966 " mediump vec3 diffuseColor,\n" 967 " mediump vec3 specularColor,\n" 968 " mediump float shininess)\n" 969 "{\n" 970 " mediump float normalDotDirection = max(dot(normal, directionToLight), 0.0);\n" 971 " mediump vec3 color = normalDotDirection * diffuseColor * lightColor;\n" 972 "\n" 973 " if (normalDotDirection != 0.0)\n" 974 " color += pow(max(dot(normal, halfVector), 0.0), shininess) * specularColor * lightColor;\n" 975 "\n" 976 " return color;\n" 977 "}\n" 978 "\n"; 979 980 if (lightType == LIGHT_POINT) 981 resultTemplate += 982 "mediump float computeDistanceAttenuation (mediump float distToLight, mediump float constAtt, mediump float linearAtt, mediump float quadraticAtt)\n" 983 "{\n" 984 " return 1.0 / (constAtt + linearAtt * distToLight + quadraticAtt * distToLight * distToLight);\n" 985 "}\n" 986 "\n"; 987 } 988 989 resultTemplate += 990 "void main (void)\n" 991 "{\n" 992 " mediump vec2 texCoord0 = v_texCoord0${NAME_SPEC}.xy;\n" 993 " mediump vec4 color = v_color${NAME_SPEC};\n"; 994 995 if (!isVertexCase) 996 { 997 resultTemplate += 998 " mediump vec3 eyeNormal = normalize(v_eyeNormal${NAME_SPEC});\n" 999 "\n"; 1000 1001 for (int lightNdx = 0; lightNdx < numLights; lightNdx++) 1002 { 1003 string ndxStr = de::toString(lightNdx); 1004 1005 resultTemplate += 1006 " /* Light " + ndxStr + " */\n"; 1007 1008 if (lightType == LIGHT_POINT) 1009 resultTemplate += 1010 " mediump vec3 directionToLight" + ndxStr + " = normalize(v_directionToLight${NAME_SPEC}[" + ndxStr + "]);\n" 1011 " mediump float distanceToLight" + ndxStr + " = v_distanceToLight${NAME_SPEC}[" + ndxStr + "];\n" 1012 " mediump vec3 halfVector" + ndxStr + " = normalize(directionToLight" + ndxStr + " + vec3(0.0, 0.0, 1.0));\n" 1013 " color.rgb += computeLighting(directionToLight" + ndxStr + ", halfVector" + ndxStr + ", eyeNormal, u_light" + ndxStr + "_color${NAME_SPEC}, u_material_diffuseColor${NAME_SPEC}.rgb, " 1014 "u_material_specularColor${NAME_SPEC}, u_material_shininess${NAME_SPEC}) * computeDistanceAttenuation(distanceToLight" + ndxStr + ", u_light" + ndxStr + "_constantAttenuation${NAME_SPEC}, " 1015 "u_light" + ndxStr + "_linearAttenuation${NAME_SPEC}, u_light" + ndxStr + "_quadraticAttenuation${NAME_SPEC});\n" 1016 "\n"; 1017 else if (lightType == LIGHT_DIRECTIONAL) 1018 resultTemplate += 1019 " mediump vec3 directionToLight" + ndxStr + " = -u_light" + ndxStr + "_direction${NAME_SPEC};\n" 1020 " mediump vec3 halfVector" + ndxStr + " = normalize(directionToLight" + ndxStr + " + vec3(0.0, 0.0, 1.0));\n" 1021 " color.rgb += computeLighting(directionToLight" + ndxStr + ", halfVector" + ndxStr + ", eyeNormal, u_light" + ndxStr + "_color${NAME_SPEC}, u_material_diffuseColor${NAME_SPEC}.rgb, u_material_specularColor${NAME_SPEC}, u_material_shininess${NAME_SPEC});\n" 1022 "\n"; 1023 else 1024 DE_ASSERT(DE_FALSE); 1025 } 1026 } 1027 1028 resultTemplate += 1029 " color *= texture(u_sampler0${NAME_SPEC}, texCoord0);\n" 1030 " o_color = color + ${FLOAT01};\n" 1031 "${SEMANTIC_ERROR}" 1032 "}\n" 1033 "${INVALID_CHAR}"; 1034 1035 return resultTemplate; 1036 } 1037 1038 // Function for generating the shader attributes of a (directional or point) light case. 1039 static vector<ShaderCompilerCase::AttribSpec> lightShaderAttributes (const string& nameSpecialization) 1040 { 1041 vector<ShaderCompilerCase::AttribSpec> result; 1042 1043 result.push_back(ShaderCompilerCase::AttribSpec("a_position" + nameSpecialization, 1044 combineVec4ToVec16(Vec4(-1.0f, -1.0f, 0.0f, 1.0f), 1045 Vec4(-1.0f, 1.0f, 0.0f, 1.0f), 1046 Vec4( 1.0f, -1.0f, 0.0f, 1.0f), 1047 Vec4( 1.0f, 1.0f, 0.0f, 1.0f)))); 1048 1049 result.push_back(ShaderCompilerCase::AttribSpec("a_normal" + nameSpecialization, 1050 combineVec4ToVec16(Vec4(0.0f, 0.0f, -1.0f, 0.0f), 1051 Vec4(0.0f, 0.0f, -1.0f, 0.0f), 1052 Vec4(0.0f, 0.0f, -1.0f, 0.0f), 1053 Vec4(0.0f, 0.0f, -1.0f, 0.0f)))); 1054 1055 result.push_back(ShaderCompilerCase::AttribSpec("a_texCoord0" + nameSpecialization, 1056 combineVec4ToVec16(Vec4(0.0f, 0.0f, 0.0f, 0.0f), 1057 Vec4(1.0f, 0.0f, 0.0f, 0.0f), 1058 Vec4(0.0f, 1.0f, 0.0f, 0.0f), 1059 Vec4(1.0f, 1.0f, 0.0f, 0.0f)))); 1060 1061 return result; 1062 } 1063 1064 // Function for generating the shader uniforms of a (directional or point) light case. 1065 static vector<ShaderCompilerCase::UniformSpec> lightShaderUniforms (const string& nameSpecialization, int numLights, LightType lightType) 1066 { 1067 vector<ShaderCompilerCase::UniformSpec> result; 1068 1069 result.push_back(ShaderCompilerCase::UniformSpec("u_material_ambientColor" + nameSpecialization, 1070 ShaderCompilerCase::UniformSpec::TYPE_VEC3, 1071 vecTo16(Vec3(0.5f, 0.7f, 0.9f)))); 1072 1073 result.push_back(ShaderCompilerCase::UniformSpec("u_material_diffuseColor" + nameSpecialization, 1074 ShaderCompilerCase:: UniformSpec::TYPE_VEC4, 1075 vecTo16(Vec4(0.3f, 0.4f, 0.5f, 1.0f)))); 1076 1077 result.push_back(ShaderCompilerCase::UniformSpec("u_material_emissiveColor" + nameSpecialization, 1078 ShaderCompilerCase::UniformSpec::TYPE_VEC3, 1079 vecTo16(Vec3(0.7f, 0.2f, 0.2f)))); 1080 1081 result.push_back(ShaderCompilerCase::UniformSpec("u_material_specularColor" + nameSpecialization, 1082 ShaderCompilerCase::UniformSpec::TYPE_VEC3, 1083 vecTo16(Vec3(0.2f, 0.6f, 1.0f)))); 1084 1085 result.push_back(ShaderCompilerCase::UniformSpec("u_material_shininess" + nameSpecialization, 1086 ShaderCompilerCase::UniformSpec::TYPE_FLOAT, 1087 0.8f)); 1088 1089 for (int lightNdx = 0; lightNdx < numLights; lightNdx++) 1090 { 1091 string ndxStr = de::toString(lightNdx); 1092 1093 result.push_back(ShaderCompilerCase::UniformSpec("u_light" + ndxStr + "_color" + nameSpecialization, 1094 ShaderCompilerCase::UniformSpec::TYPE_VEC3, 1095 vecTo16(Vec3(0.8f, 0.6f, 0.3f)))); 1096 1097 result.push_back(ShaderCompilerCase::UniformSpec("u_light" + ndxStr + "_direction" + nameSpecialization, 1098 ShaderCompilerCase::UniformSpec::TYPE_VEC3, 1099 vecTo16(Vec3(0.2f, 0.3f, 0.4f)))); 1100 1101 if (lightType == LIGHT_POINT) 1102 { 1103 result.push_back(ShaderCompilerCase::UniformSpec("u_light" + ndxStr + "_position" + nameSpecialization, 1104 ShaderCompilerCase::UniformSpec::TYPE_VEC4, 1105 vecTo16(Vec4(1.0f, 0.6f, 0.3f, 0.2f)))); 1106 1107 result.push_back(ShaderCompilerCase::UniformSpec("u_light" + ndxStr + "_constantAttenuation" + nameSpecialization, 1108 ShaderCompilerCase::UniformSpec::TYPE_FLOAT, 1109 0.6f)); 1110 1111 result.push_back(ShaderCompilerCase::UniformSpec("u_light" + ndxStr + "_linearAttenuation" + nameSpecialization, 1112 ShaderCompilerCase::UniformSpec::TYPE_FLOAT, 1113 0.5f)); 1114 1115 result.push_back(ShaderCompilerCase::UniformSpec("u_light" + ndxStr + "_quadraticAttenuation" + nameSpecialization, 1116 ShaderCompilerCase::UniformSpec::TYPE_FLOAT, 1117 0.4f)); 1118 } 1119 } 1120 1121 result.push_back(ShaderCompilerCase::UniformSpec("u_mvpMatrix" + nameSpecialization, 1122 ShaderCompilerCase::UniformSpec::TYPE_MAT4, 1123 arrTo16(Mat4(1.0f).getColumnMajorData()))); 1124 1125 result.push_back(ShaderCompilerCase::UniformSpec("u_modelViewMatrix" + nameSpecialization, 1126 ShaderCompilerCase::UniformSpec::TYPE_MAT4, 1127 arrTo16(Mat4(1.0f).getColumnMajorData()))); 1128 1129 result.push_back(ShaderCompilerCase::UniformSpec("u_normalMatrix" + nameSpecialization, 1130 ShaderCompilerCase::UniformSpec::TYPE_MAT3, 1131 arrTo16(Mat3(1.0f).getColumnMajorData()))); 1132 1133 result.push_back(ShaderCompilerCase::UniformSpec("u_texCoordMatrix0" + nameSpecialization, 1134 ShaderCompilerCase::UniformSpec::TYPE_MAT4, 1135 arrTo16(Mat4(1.0f).getColumnMajorData()))); 1136 1137 result.push_back(ShaderCompilerCase::UniformSpec("u_sampler0" + nameSpecialization, 1138 ShaderCompilerCase::UniformSpec::TYPE_TEXTURE_UNIT, 1139 0.0f)); 1140 1141 return result; 1142 } 1143 1144 // Function for generating a vertex shader with a for loop. 1145 static string loopVertexTemplate (LoopType type, bool isVertexCase, int numLoopIterations, int nestingDepth) 1146 { 1147 string resultTemplate; 1148 string loopBound = type == LOOP_TYPE_STATIC ? de::toString(numLoopIterations) 1149 : type == LOOP_TYPE_UNIFORM ? "int(u_loopBound${NAME_SPEC})" 1150 : type == LOOP_TYPE_DYNAMIC ? "int(a_loopBound${NAME_SPEC})" 1151 : ""; 1152 1153 DE_ASSERT(!loopBound.empty()); 1154 1155 resultTemplate += 1156 "#version 300 es\n" 1157 "in highp vec4 a_position${NAME_SPEC};\n"; 1158 1159 if (type == LOOP_TYPE_DYNAMIC) 1160 resultTemplate += 1161 "in mediump float a_loopBound${NAME_SPEC};\n"; 1162 1163 resultTemplate += 1164 "in mediump vec4 a_value${NAME_SPEC};\n" 1165 "out mediump vec4 v_value${NAME_SPEC};\n"; 1166 1167 if (isVertexCase) 1168 { 1169 if (type == LOOP_TYPE_UNIFORM) 1170 resultTemplate += "uniform mediump float u_loopBound${NAME_SPEC};\n"; 1171 1172 resultTemplate += 1173 "\n" 1174 "void main()\n" 1175 "{\n" 1176 " gl_Position = a_position${NAME_SPEC} * (0.95 + 0.05*${FLOAT01});\n" 1177 " mediump vec4 value = a_value${NAME_SPEC};\n"; 1178 1179 for (int i = 0; i < nestingDepth; i++) 1180 { 1181 string iterName = "i" + de::toString(i); 1182 resultTemplate += string(i + 1, '\t') + "for (int " + iterName + " = 0; " + iterName + " < " + loopBound + "; " + iterName + "++)\n"; 1183 } 1184 1185 resultTemplate += string(nestingDepth + 1, '\t') + "value *= a_value${NAME_SPEC};\n"; 1186 1187 resultTemplate += 1188 " v_value${NAME_SPEC} = value;\n"; 1189 } 1190 else 1191 { 1192 if (type == LOOP_TYPE_DYNAMIC) 1193 resultTemplate += 1194 "out mediump float v_loopBound${NAME_SPEC};\n"; 1195 1196 resultTemplate += 1197 "\n" 1198 "void main()\n" 1199 "{\n" 1200 " gl_Position = a_position${NAME_SPEC} * (0.95 + 0.05*${FLOAT01});\n" 1201 " v_value${NAME_SPEC} = a_value${NAME_SPEC};\n"; 1202 1203 if (type == LOOP_TYPE_DYNAMIC) 1204 resultTemplate += 1205 " v_loopBound${NAME_SPEC} = a_loopBound${NAME_SPEC};\n"; 1206 } 1207 1208 resultTemplate += 1209 "${SEMANTIC_ERROR}" 1210 "}\n" 1211 "${INVALID_CHAR}"; 1212 1213 return resultTemplate; 1214 } 1215 1216 // Function for generating a fragment shader with a for loop. 1217 static string loopFragmentTemplate (LoopType type, bool isVertexCase, int numLoopIterations, int nestingDepth) 1218 { 1219 string resultTemplate; 1220 string loopBound = type == LOOP_TYPE_STATIC ? de::toString(numLoopIterations) 1221 : type == LOOP_TYPE_UNIFORM ? "int(u_loopBound${NAME_SPEC})" 1222 : type == LOOP_TYPE_DYNAMIC ? "int(v_loopBound${NAME_SPEC})" 1223 : ""; 1224 1225 DE_ASSERT(!loopBound.empty()); 1226 1227 resultTemplate += 1228 "#version 300 es\n" 1229 "layout(location = 0) out mediump vec4 o_color;\n" 1230 "in mediump vec4 v_value${NAME_SPEC};\n"; 1231 1232 if (!isVertexCase) 1233 { 1234 if (type == LOOP_TYPE_DYNAMIC) 1235 resultTemplate += 1236 "in mediump float v_loopBound${NAME_SPEC};\n"; 1237 else if (type == LOOP_TYPE_UNIFORM) 1238 resultTemplate += 1239 "uniform mediump float u_loopBound${NAME_SPEC};\n"; 1240 1241 resultTemplate += 1242 "\n" 1243 "void main()\n" 1244 "{\n" 1245 " mediump vec4 value = v_value${NAME_SPEC};\n"; 1246 1247 for (int i = 0; i < nestingDepth; i++) 1248 { 1249 string iterName = "i" + de::toString(i); 1250 resultTemplate += string(i + 1, '\t') + "for (int " + iterName + " = 0; " + iterName + " < " + loopBound + "; " + iterName + "++)\n"; 1251 } 1252 1253 resultTemplate += string(nestingDepth + 1, '\t') + "value *= v_value${NAME_SPEC};\n"; 1254 1255 resultTemplate += 1256 " o_color = value + ${FLOAT01};\n"; 1257 } 1258 else 1259 resultTemplate += 1260 "\n" 1261 "void main()\n" 1262 "{\n" 1263 " o_color = v_value${NAME_SPEC} + ${FLOAT01};\n"; 1264 1265 resultTemplate += 1266 "${SEMANTIC_ERROR}" 1267 "}\n" 1268 "${INVALID_CHAR}"; 1269 1270 return resultTemplate; 1271 } 1272 1273 // Function for generating the shader attributes for a loop case. 1274 static vector<ShaderCompilerCase::AttribSpec> loopShaderAttributes (const string& nameSpecialization, LoopType type, int numLoopIterations) 1275 { 1276 vector<ShaderCompilerCase::AttribSpec> result; 1277 1278 result.push_back(ShaderCompilerCase::AttribSpec("a_position" + nameSpecialization, 1279 combineVec4ToVec16(Vec4(-1.0f, -1.0f, 0.0f, 1.0f), 1280 Vec4(-1.0f, 1.0f, 0.0f, 1.0f), 1281 Vec4( 1.0f, -1.0f, 0.0f, 1.0f), 1282 Vec4( 1.0f, 1.0f, 0.0f, 1.0f)))); 1283 1284 result.push_back(ShaderCompilerCase::AttribSpec("a_value" + nameSpecialization, 1285 combineVec4ToVec16(Vec4( 1.0f, 1.0f, 1.0f, 1.0f), 1286 Vec4( 1.0f, 1.0f, 1.0f, 1.0f), 1287 Vec4( 1.0f, 1.0f, 1.0f, 1.0f), 1288 Vec4( 1.0f, 1.0f, 1.0f, 1.0f)))); 1289 1290 if (type == LOOP_TYPE_DYNAMIC) 1291 result.push_back(ShaderCompilerCase::AttribSpec("a_loopBound" + nameSpecialization, 1292 combineVec4ToVec16(Vec4((float)numLoopIterations, 0.0f, 0.0f, 0.0f), 1293 Vec4((float)numLoopIterations, 0.0f, 0.0f, 0.0f), 1294 Vec4((float)numLoopIterations, 0.0f, 0.0f, 0.0f), 1295 Vec4((float)numLoopIterations, 0.0f, 0.0f, 0.0f)))); 1296 1297 return result; 1298 } 1299 1300 static vector<ShaderCompilerCase::UniformSpec> loopShaderUniforms (const string& nameSpecialization, LoopType type, int numLoopIterations) 1301 { 1302 vector<ShaderCompilerCase::UniformSpec> result; 1303 1304 if (type == LOOP_TYPE_UNIFORM) 1305 result.push_back(ShaderCompilerCase::UniformSpec("u_loopBound" + nameSpecialization, 1306 ShaderCompilerCase::UniformSpec::TYPE_FLOAT, 1307 (float)numLoopIterations)); 1308 1309 return result; 1310 } 1311 1312 // Function for generating the shader attributes for a case with only one attribute value in addition to the position attribute. 1313 static vector<ShaderCompilerCase::AttribSpec> singleValueShaderAttributes (const string& nameSpecialization) 1314 { 1315 vector<ShaderCompilerCase::AttribSpec> result; 1316 1317 result.push_back(ShaderCompilerCase::AttribSpec("a_position" + nameSpecialization, 1318 combineVec4ToVec16(Vec4(-1.0f, -1.0f, 0.0f, 1.0f), 1319 Vec4(-1.0f, 1.0f, 0.0f, 1.0f), 1320 Vec4( 1.0f, -1.0f, 0.0f, 1.0f), 1321 Vec4( 1.0f, 1.0f, 0.0f, 1.0f)))); 1322 1323 result.push_back(ShaderCompilerCase::AttribSpec("a_value" + nameSpecialization, 1324 combineVec4ToVec16(Vec4( 1.0f, 1.0f, 1.0f, 1.0f), 1325 Vec4( 1.0f, 1.0f, 1.0f, 1.0f), 1326 Vec4( 1.0f, 1.0f, 1.0f, 1.0f), 1327 Vec4( 1.0f, 1.0f, 1.0f, 1.0f)))); 1328 1329 return result; 1330 } 1331 1332 // Function for generating a vertex shader with a binary operation chain. 1333 static string binaryOpVertexTemplate (int numOperations, const char* op) 1334 { 1335 string resultTemplate; 1336 1337 resultTemplate += 1338 "#version 300 es\n" 1339 "in highp vec4 a_position${NAME_SPEC};\n" 1340 "in mediump vec4 a_value${NAME_SPEC};\n" 1341 "out mediump vec4 v_value${NAME_SPEC};\n" 1342 "\n" 1343 "void main()\n" 1344 "{\n" 1345 " gl_Position = a_position${NAME_SPEC} * (0.95 + 0.05*${FLOAT01});\n" 1346 " mediump vec4 value = "; 1347 1348 for (int i = 0; i < numOperations; i++) 1349 resultTemplate += string(i > 0 ? op : "") + "a_value${NAME_SPEC}"; 1350 1351 resultTemplate += 1352 ";\n" 1353 " v_value${NAME_SPEC} = value;\n" 1354 "${SEMANTIC_ERROR}" 1355 "}\n" 1356 "${INVALID_CHAR}"; 1357 1358 return resultTemplate; 1359 } 1360 1361 // Function for generating a fragment shader with a binary operation chain. 1362 static string binaryOpFragmentTemplate (int numOperations, const char* op) 1363 { 1364 string resultTemplate; 1365 1366 resultTemplate += 1367 "#version 300 es\n" 1368 "layout(location = 0) out mediump vec4 o_color;\n" 1369 "in mediump vec4 v_value${NAME_SPEC};\n" 1370 "\n" 1371 "void main()\n" 1372 "{\n" 1373 " mediump vec4 value = "; 1374 1375 for (int i = 0; i < numOperations; i++) 1376 resultTemplate += string(i > 0 ? op : "") + "v_value${NAME_SPEC}"; 1377 1378 resultTemplate += 1379 ";\n" 1380 " o_color = value + ${FLOAT01};\n" 1381 "${SEMANTIC_ERROR}" 1382 "}\n" 1383 "${INVALID_CHAR}"; 1384 1385 return resultTemplate; 1386 } 1387 1388 // Function for generating a vertex that takes one attribute in addition to position and just passes it to the fragment shader as a varying. 1389 static string singleVaryingVertexTemplate (void) 1390 { 1391 const char* resultTemplate = 1392 "#version 300 es\n" 1393 "in highp vec4 a_position${NAME_SPEC};\n" 1394 "in mediump vec4 a_value${NAME_SPEC};\n" 1395 "out mediump vec4 v_value${NAME_SPEC};\n" 1396 "\n" 1397 "void main()\n" 1398 "{\n" 1399 " gl_Position = a_position${NAME_SPEC} * (0.95 + 0.05*${FLOAT01});\n" 1400 " v_value${NAME_SPEC} = a_value${NAME_SPEC};\n" 1401 "${SEMANTIC_ERROR}" 1402 "}\n" 1403 "${INVALID_CHAR}"; 1404 1405 return resultTemplate; 1406 } 1407 1408 // Function for generating a fragment shader that takes a single varying and uses it as the color. 1409 static string singleVaryingFragmentTemplate (void) 1410 { 1411 const char* resultTemplate = 1412 "#version 300 es\n" 1413 "layout(location = 0) out mediump vec4 o_color;\n" 1414 "in mediump vec4 v_value${NAME_SPEC};\n" 1415 "\n" 1416 "void main()\n" 1417 "{\n" 1418 " o_color = v_value${NAME_SPEC} + ${FLOAT01};\n" 1419 "${SEMANTIC_ERROR}" 1420 "}\n" 1421 "${INVALID_CHAR}"; 1422 1423 return resultTemplate; 1424 } 1425 1426 // Function for generating the vertex shader of a texture lookup case. 1427 static string textureLookupVertexTemplate (ConditionalUsage conditionalUsage, ConditionalType conditionalType) 1428 { 1429 string resultTemplate; 1430 bool conditionVaryingNeeded = conditionalUsage != CONDITIONAL_USAGE_NONE && conditionalType == CONDITIONAL_TYPE_DYNAMIC; 1431 1432 resultTemplate += 1433 "#version 300 es\n" 1434 "in highp vec4 a_position${NAME_SPEC};\n" 1435 "in mediump vec2 a_coords${NAME_SPEC};\n" 1436 "out mediump vec2 v_coords${NAME_SPEC};\n"; 1437 1438 if (conditionVaryingNeeded) 1439 resultTemplate += 1440 "in mediump float a_condition${NAME_SPEC};\n" 1441 "out mediump float v_condition${NAME_SPEC};\n"; 1442 1443 resultTemplate += 1444 "\n" 1445 "void main()\n" 1446 "{\n" 1447 " gl_Position = a_position${NAME_SPEC} * (0.95 + 0.05*${FLOAT01});\n" 1448 " v_coords${NAME_SPEC} = a_coords${NAME_SPEC};\n"; 1449 1450 if (conditionVaryingNeeded) 1451 resultTemplate += 1452 " v_condition${NAME_SPEC} = a_condition${NAME_SPEC};\n"; 1453 1454 resultTemplate += 1455 "${SEMANTIC_ERROR}" 1456 "}\n" 1457 "${INVALID_CHAR}"; 1458 1459 return resultTemplate; 1460 } 1461 1462 // Function for generating the fragment shader of a texture lookup case. 1463 static string textureLookupFragmentTemplate (int numLookups, ConditionalUsage conditionalUsage, ConditionalType conditionalType) 1464 { 1465 string resultTemplate; 1466 1467 resultTemplate += 1468 "#version 300 es\n" 1469 "layout(location = 0) out mediump vec4 o_color;\n" 1470 "in mediump vec2 v_coords${NAME_SPEC};\n"; 1471 1472 if (conditionalUsage != CONDITIONAL_USAGE_NONE && conditionalType == CONDITIONAL_TYPE_DYNAMIC) 1473 resultTemplate += 1474 "in mediump float v_condition${NAME_SPEC};\n"; 1475 1476 for (int i = 0; i < numLookups; i++) 1477 resultTemplate += 1478 "uniform sampler2D u_sampler" + de::toString(i) + "${NAME_SPEC};\n"; 1479 1480 if (conditionalUsage != CONDITIONAL_USAGE_NONE && conditionalType == CONDITIONAL_TYPE_UNIFORM) 1481 resultTemplate += 1482 "uniform mediump float u_condition${NAME_SPEC};\n"; 1483 1484 resultTemplate += 1485 "\n" 1486 "void main()\n" 1487 "{\n" 1488 " mediump vec4 color = vec4(0.0);\n"; 1489 1490 const char* conditionalTerm = conditionalType == CONDITIONAL_TYPE_STATIC ? "1.0 > 0.0" 1491 : conditionalType == CONDITIONAL_TYPE_UNIFORM ? "u_condition${NAME_SPEC} > 0.0" 1492 : conditionalType == CONDITIONAL_TYPE_DYNAMIC ? "v_condition${NAME_SPEC} > 0.0" 1493 : DE_NULL; 1494 1495 DE_ASSERT(conditionalTerm != DE_NULL); 1496 1497 if (conditionalUsage == CONDITIONAL_USAGE_FIRST_HALF) 1498 resultTemplate += string("") + 1499 " if (" + conditionalTerm + ")\n" 1500 " {\n"; 1501 1502 for (int i = 0; i < numLookups; i++) 1503 { 1504 if (conditionalUsage == CONDITIONAL_USAGE_FIRST_HALF) 1505 { 1506 if (i < (numLookups + 1) / 2) 1507 resultTemplate += "\t"; 1508 } 1509 else if (conditionalUsage == CONDITIONAL_USAGE_EVERY_OTHER) 1510 { 1511 if (i % 2 == 0) 1512 resultTemplate += string("") + 1513 " if (" + conditionalTerm + ")\n" 1514 "\t"; 1515 } 1516 1517 resultTemplate += 1518 " color += texture(u_sampler" + de::toString(i) + "${NAME_SPEC}, v_coords${NAME_SPEC});\n"; 1519 1520 if (conditionalUsage == CONDITIONAL_USAGE_FIRST_HALF && i == (numLookups - 1) / 2) 1521 resultTemplate += "\t}\n"; 1522 } 1523 1524 resultTemplate += 1525 " o_color = color/" + de::toString(numLookups) + ".0 + ${FLOAT01};\n" + 1526 "${SEMANTIC_ERROR}" 1527 "}\n" 1528 "${INVALID_CHAR}"; 1529 1530 return resultTemplate; 1531 } 1532 1533 // Function for generating the shader attributes of a texture lookup case. 1534 static vector<ShaderCompilerCase::AttribSpec> textureLookupShaderAttributes (const string& nameSpecialization, ConditionalUsage conditionalUsage, ConditionalType conditionalType) 1535 { 1536 vector<ShaderCompilerCase::AttribSpec> result; 1537 1538 result.push_back(ShaderCompilerCase::AttribSpec("a_position" + nameSpecialization, 1539 combineVec4ToVec16(Vec4(-1.0f, -1.0f, 0.0f, 1.0f), 1540 Vec4(-1.0f, 1.0f, 0.0f, 1.0f), 1541 Vec4( 1.0f, -1.0f, 0.0f, 1.0f), 1542 Vec4( 1.0f, 1.0f, 0.0f, 1.0f)))); 1543 1544 result.push_back(ShaderCompilerCase::AttribSpec("a_coords" + nameSpecialization, 1545 combineVec4ToVec16(Vec4(0.0f, 0.0f, 0.0f, 0.0f), 1546 Vec4(0.0f, 1.0f, 0.0f, 0.0f), 1547 Vec4(1.0f, 0.0f, 0.0f, 0.0f), 1548 Vec4(1.0f, 1.0f, 0.0f, 0.0f)))); 1549 1550 if (conditionalUsage != CONDITIONAL_USAGE_NONE && conditionalType == CONDITIONAL_TYPE_DYNAMIC) 1551 result.push_back(ShaderCompilerCase::AttribSpec("a_condition" + nameSpecialization, 1552 combineVec4ToVec16(Vec4(1.0f), Vec4(1.0f), Vec4(1.0f), Vec4(1.0f)))); 1553 1554 return result; 1555 } 1556 1557 // Function for generating the shader uniforms of a texture lookup case. 1558 static vector<ShaderCompilerCase::UniformSpec> textureLookupShaderUniforms (const string& nameSpecialization, int numLookups, ConditionalUsage conditionalUsage, ConditionalType conditionalType) 1559 { 1560 vector<ShaderCompilerCase::UniformSpec> result; 1561 1562 for (int i = 0; i < numLookups; i++) 1563 result.push_back(ShaderCompilerCase::UniformSpec("u_sampler" + de::toString(i) + nameSpecialization, 1564 ShaderCompilerCase::UniformSpec::TYPE_TEXTURE_UNIT, 1565 (float)i)); 1566 1567 if (conditionalUsage != CONDITIONAL_USAGE_NONE && conditionalType == CONDITIONAL_TYPE_UNIFORM) 1568 result.push_back(ShaderCompilerCase::UniformSpec("u_condition" + nameSpecialization, 1569 ShaderCompilerCase::UniformSpec::TYPE_FLOAT, 1570 1.0f)); 1571 1572 return result; 1573 } 1574 1575 static string mandelbrotVertexTemplate (void) 1576 { 1577 const char* resultTemplate = 1578 "#version 300 es\n" 1579 "uniform highp mat4 u_mvp${NAME_SPEC};\n" 1580 "\n" 1581 "in highp vec4 a_vertex${NAME_SPEC};\n" 1582 "in highp vec4 a_coord${NAME_SPEC};\n" 1583 "\n" 1584 "out mediump vec2 v_coord${NAME_SPEC};\n" 1585 "\n" 1586 "void main(void)\n" 1587 "{\n" 1588 " gl_Position = u_mvp${NAME_SPEC} * a_vertex${NAME_SPEC} * (0.95 + 0.05*${FLOAT01});\n" 1589 "\n" 1590 " float xMin = -2.0;\n" 1591 " float xMax = +0.5;\n" 1592 " float yMin = -1.5;\n" 1593 " float yMax = +1.5;\n" 1594 "\n" 1595 " v_coord${NAME_SPEC}.x = a_coord${NAME_SPEC}.x * (xMax - xMin) + xMin;\n" 1596 " v_coord${NAME_SPEC}.y = a_coord${NAME_SPEC}.y * (yMax - yMin) + yMin;\n" 1597 "${SEMANTIC_ERROR}" 1598 "}\n" 1599 "${INVALID_CHAR}"; 1600 1601 return resultTemplate; 1602 } 1603 1604 static string mandelbrotFragmentTemplate (int numFractalIterations) 1605 { 1606 string resultTemplate = 1607 "#version 300 es\n" 1608 "layout(location = 0) out mediump vec4 o_color;\n" 1609 "in mediump vec2 v_coord${NAME_SPEC};\n" 1610 "\n" 1611 "precision mediump float;\n" 1612 "\n" 1613 "#define NUM_ITERS " + de::toString(numFractalIterations) + "\n" 1614 "\n" 1615 "void main (void)\n" 1616 "{\n" 1617 " vec2 coords = v_coord${NAME_SPEC};\n" 1618 " float u_limit = 2.0 * 2.0;\n" 1619 " vec2 tmp = vec2(0, 0);\n" 1620 " int iter;\n" 1621 "\n" 1622 " for (iter = 0; iter < NUM_ITERS; iter++)\n" 1623 " {\n" 1624 " tmp = vec2((tmp.x + tmp.y) * (tmp.x - tmp.y), 2.0 * (tmp.x * tmp.y)) + coords;\n" 1625 "\n" 1626 " if (dot(tmp, tmp) > u_limit)\n" 1627 " break;\n" 1628 " }\n" 1629 "\n" 1630 " vec3 color = vec3(float(iter) * (1.0 / float(NUM_ITERS)));\n" 1631 "\n" 1632 " o_color = vec4(color, 1.0) + ${FLOAT01};\n" 1633 "${SEMANTIC_ERROR}" 1634 "}\n" 1635 "${INVALID_CHAR}"; 1636 1637 return resultTemplate; 1638 } 1639 1640 static vector<ShaderCompilerCase::AttribSpec> mandelbrotShaderAttributes (const string& nameSpecialization) 1641 { 1642 vector<ShaderCompilerCase::AttribSpec> result; 1643 1644 result.push_back(ShaderCompilerCase::AttribSpec("a_vertex" + nameSpecialization, 1645 combineVec4ToVec16(Vec4(-1.0f, -1.0f, 0.0f, 1.0f), 1646 Vec4(-1.0f, 1.0f, 0.0f, 1.0f), 1647 Vec4( 1.0f, -1.0f, 0.0f, 1.0f), 1648 Vec4( 1.0f, 1.0f, 0.0f, 1.0f)))); 1649 1650 result.push_back(ShaderCompilerCase::AttribSpec("a_coord" + nameSpecialization, 1651 combineVec4ToVec16(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 1652 Vec4(0.0f, 1.0f, 0.0f, 1.0f), 1653 Vec4(1.0f, 0.0f, 0.0f, 1.0f), 1654 Vec4(1.0f, 1.0f, 0.0f, 1.0f)))); 1655 1656 return result; 1657 } 1658 1659 static vector<ShaderCompilerCase::UniformSpec> mandelbrotShaderUniforms (const string& nameSpecialization) 1660 { 1661 vector<ShaderCompilerCase::UniformSpec> result; 1662 1663 result.push_back(ShaderCompilerCase::UniformSpec("u_mvp" + nameSpecialization, 1664 ShaderCompilerCase::UniformSpec::TYPE_MAT4, 1665 arrTo16(Mat4(1.0f).getColumnMajorData()))); 1666 1667 return result; 1668 } 1669 1670 ShaderCompilerCase::ShaderCompilerCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments) 1671 : TestCase (context, tcu::NODETYPE_PERFORMANCE, name, description) 1672 , m_viewportWidth (0) 1673 , m_viewportHeight (0) 1674 , m_avoidCache (avoidCache) 1675 , m_addWhitespaceAndComments (addWhitespaceAndComments) 1676 , m_startHash ((deUint32)(deUint64Hash(deGetTime()) ^ deUint64Hash(deGetMicroseconds()) ^ deInt32Hash(caseID))) 1677 { 1678 int cmdLineIterCount = context.getTestContext().getCommandLine().getTestIterationCount(); 1679 m_minimumMeasurementCount = cmdLineIterCount > 0 ? cmdLineIterCount : DEFAULT_MINIMUM_MEASUREMENT_COUNT; 1680 m_maximumMeasurementCount = m_minimumMeasurementCount*3; 1681 } 1682 1683 ShaderCompilerCase::~ShaderCompilerCase (void) 1684 { 1685 } 1686 1687 deUint32 ShaderCompilerCase::getSpecializationID (int measurementNdx) const 1688 { 1689 if (m_avoidCache) 1690 return m_startHash ^ (deUint32)deInt32Hash((deInt32)measurementNdx); 1691 else 1692 return m_startHash; 1693 } 1694 1695 void ShaderCompilerCase::init (void) 1696 { 1697 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1698 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 1699 1700 m_viewportWidth = deMin32(MAX_VIEWPORT_WIDTH, renderTarget.getWidth()); 1701 m_viewportHeight = deMin32(MAX_VIEWPORT_HEIGHT, renderTarget.getHeight()); 1702 1703 gl.viewport(0, 0, m_viewportWidth, m_viewportHeight); 1704 } 1705 1706 ShaderCompilerCase::ShadersAndProgram ShaderCompilerCase::createShadersAndProgram (void) const 1707 { 1708 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1709 ShadersAndProgram result; 1710 1711 result.vertShader = gl.createShader(GL_VERTEX_SHADER); 1712 result.fragShader = gl.createShader(GL_FRAGMENT_SHADER); 1713 result.program = gl.createProgram(); 1714 1715 gl.attachShader(result.program, result.vertShader); 1716 gl.attachShader(result.program, result.fragShader); 1717 1718 return result; 1719 } 1720 1721 void ShaderCompilerCase::setShaderSources (deUint32 vertShader, deUint32 fragShader, const ProgramContext& progCtx) const 1722 { 1723 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1724 const char* vertShaderSourceCStr = progCtx.vertShaderSource.c_str(); 1725 const char* fragShaderSourceCStr = progCtx.fragShaderSource.c_str(); 1726 gl.shaderSource(vertShader, 1, &vertShaderSourceCStr, DE_NULL); 1727 gl.shaderSource(fragShader, 1, &fragShaderSourceCStr, DE_NULL); 1728 } 1729 1730 bool ShaderCompilerCase::compileShader (deUint32 shader) const 1731 { 1732 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1733 GLint status = 0; 1734 gl.compileShader(shader); 1735 gl.getShaderiv(shader, GL_COMPILE_STATUS, &status); 1736 return status != 0; 1737 } 1738 1739 bool ShaderCompilerCase::linkAndUseProgram (deUint32 program) const 1740 { 1741 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1742 GLint linkStatus = 0; 1743 1744 gl.linkProgram(program); 1745 gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus); 1746 1747 if (linkStatus != 0) 1748 gl.useProgram(program); 1749 1750 return linkStatus != 0; 1751 } 1752 1753 void ShaderCompilerCase::setShaderInputs (deUint32 program, const ProgramContext& progCtx) const 1754 { 1755 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1756 1757 // Setup attributes. 1758 1759 for (int attribNdx = 0; attribNdx < (int)progCtx.vertexAttributes.size(); attribNdx++) 1760 { 1761 int location = gl.getAttribLocation(program, progCtx.vertexAttributes[attribNdx].name.c_str()); 1762 if (location >= 0) 1763 { 1764 gl.enableVertexAttribArray(location); 1765 gl.vertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, 0, progCtx.vertexAttributes[attribNdx].value.getPtr()); 1766 } 1767 } 1768 1769 // Setup uniforms. 1770 1771 for (int uniformNdx = 0; uniformNdx < (int)progCtx.uniforms.size(); uniformNdx++) 1772 { 1773 int location = gl.getUniformLocation(program, progCtx.uniforms[uniformNdx].name.c_str()); 1774 if (location >= 0) 1775 { 1776 const float* floatPtr = progCtx.uniforms[uniformNdx].value.getPtr(); 1777 1778 switch (progCtx.uniforms[uniformNdx].type) 1779 { 1780 case UniformSpec::TYPE_FLOAT: gl.uniform1fv(location, 1, floatPtr); break; 1781 case UniformSpec::TYPE_VEC2: gl.uniform2fv(location, 1, floatPtr); break; 1782 case UniformSpec::TYPE_VEC3: gl.uniform3fv(location, 1, floatPtr); break; 1783 case UniformSpec::TYPE_VEC4: gl.uniform4fv(location, 1, floatPtr); break; 1784 case UniformSpec::TYPE_MAT3: gl.uniformMatrix3fv(location, 1, GL_FALSE, floatPtr); break; 1785 case UniformSpec::TYPE_MAT4: gl.uniformMatrix4fv(location, 1, GL_FALSE, floatPtr); break; 1786 case UniformSpec::TYPE_TEXTURE_UNIT: gl.uniform1i(location, (GLint)deRoundFloatToInt32(*floatPtr)); break; 1787 default: 1788 DE_ASSERT(DE_FALSE); 1789 } 1790 } 1791 } 1792 } 1793 1794 void ShaderCompilerCase::draw (void) const 1795 { 1796 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1797 1798 static const deUint8 indices[] = 1799 { 1800 0, 1, 2, 1801 2, 1, 3 1802 }; 1803 1804 gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 1805 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_BYTE, indices); 1806 1807 // \note Read one pixel to force compilation. 1808 deUint32 pixel; 1809 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel); 1810 } 1811 1812 void ShaderCompilerCase::cleanup (const ShadersAndProgram& shadersAndProgram, const ProgramContext& progCtx, bool linkSuccess) const 1813 { 1814 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1815 1816 if (linkSuccess) 1817 { 1818 for (int attribNdx = 0; attribNdx < (int)progCtx.vertexAttributes.size(); attribNdx++) 1819 { 1820 int location = gl.getAttribLocation(shadersAndProgram.program, progCtx.vertexAttributes[attribNdx].name.c_str()); 1821 if (location >= 0) 1822 gl.disableVertexAttribArray(location); 1823 } 1824 } 1825 1826 gl.useProgram(0); 1827 gl.detachShader(shadersAndProgram.program, shadersAndProgram.vertShader); 1828 gl.detachShader(shadersAndProgram.program, shadersAndProgram.fragShader); 1829 gl.deleteShader(shadersAndProgram.vertShader); 1830 gl.deleteShader(shadersAndProgram.fragShader); 1831 gl.deleteProgram(shadersAndProgram.program); 1832 } 1833 1834 void ShaderCompilerCase::logProgramData (const BuildInfo& buildInfo, const ProgramContext& progCtx) const 1835 { 1836 m_testCtx.getLog() << TestLog::ShaderProgram(buildInfo.linkSuccess, buildInfo.logs.link) 1837 << TestLog::Shader(QP_SHADER_TYPE_VERTEX, progCtx.vertShaderSource, buildInfo.vertCompileSuccess, buildInfo.logs.vert) 1838 << TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, progCtx.fragShaderSource, buildInfo.fragCompileSuccess, buildInfo.logs.frag) 1839 << TestLog::EndShaderProgram; 1840 } 1841 1842 ShaderCompilerCase::Logs ShaderCompilerCase::getLogs (const ShadersAndProgram& shadersAndProgram) const 1843 { 1844 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1845 Logs result; 1846 1847 result.vert = getShaderInfoLog(gl, shadersAndProgram.vertShader); 1848 result.frag = getShaderInfoLog(gl, shadersAndProgram.fragShader); 1849 result.link = getProgramInfoLog(gl, shadersAndProgram.program); 1850 1851 return result; 1852 } 1853 1854 bool ShaderCompilerCase::goodEnoughMeasurements (const vector<Measurement>& measurements) const 1855 { 1856 if ((int)measurements.size() < m_minimumMeasurementCount) 1857 return false; 1858 else 1859 { 1860 if ((int)measurements.size() >= m_maximumMeasurementCount) 1861 return true; 1862 else 1863 { 1864 vector<deInt64> totalTimesWithoutDraw; 1865 for (int i = 0; i < (int)measurements.size(); i++) 1866 totalTimesWithoutDraw.push_back(measurements[i].totalTimeWithoutDraw()); 1867 return vectorFloatRelativeMedianAbsoluteDeviation(vectorLowestPercentage(totalTimesWithoutDraw, 0.5f)) < RELATIVE_MEDIAN_ABSOLUTE_DEVIATION_THRESHOLD; 1868 } 1869 } 1870 } 1871 1872 ShaderCompilerCase::IterateResult ShaderCompilerCase::iterate (void) 1873 { 1874 // Before actual measurements, compile and draw with a dummy shader to avoid possible initial slowdowns in the actual test. 1875 { 1876 deUint32 specID = getSpecializationID(0); 1877 ProgramContext progCtx; 1878 progCtx.vertShaderSource = specializeShaderSource(singleVaryingVertexTemplate(), specID, SHADER_VALIDITY_VALID); 1879 progCtx.fragShaderSource = specializeShaderSource(singleVaryingFragmentTemplate(), specID, SHADER_VALIDITY_VALID); 1880 progCtx.vertexAttributes = singleValueShaderAttributes(getNameSpecialization(specID)); 1881 1882 ShadersAndProgram shadersAndProgram = createShadersAndProgram(); 1883 setShaderSources(shadersAndProgram.vertShader, shadersAndProgram.fragShader, progCtx); 1884 1885 BuildInfo buildInfo; 1886 buildInfo.vertCompileSuccess = compileShader(shadersAndProgram.vertShader); 1887 buildInfo.fragCompileSuccess = compileShader(shadersAndProgram.fragShader); 1888 buildInfo.linkSuccess = linkAndUseProgram(shadersAndProgram.program); 1889 if (!(buildInfo.vertCompileSuccess && buildInfo.fragCompileSuccess && buildInfo.linkSuccess)) 1890 { 1891 buildInfo.logs = getLogs(shadersAndProgram); 1892 logProgramData(buildInfo, progCtx); 1893 cleanup(shadersAndProgram, progCtx, buildInfo.linkSuccess); 1894 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compilation failed"); 1895 return STOP; 1896 } 1897 setShaderInputs(shadersAndProgram.program, progCtx); 1898 draw(); 1899 cleanup(shadersAndProgram, progCtx, buildInfo.linkSuccess); 1900 } 1901 1902 vector<Measurement> measurements; 1903 // \note These are logged after measurements are done. 1904 ProgramContext latestProgramContext; 1905 BuildInfo latestBuildInfo; 1906 1907 if (WARMUP_CPU_AT_BEGINNING_OF_CASE) 1908 tcu::warmupCPU(); 1909 1910 // Actual test measurements. 1911 while (!goodEnoughMeasurements(measurements)) 1912 { 1913 // Create shaders, compile & link, set shader inputs and draw. Time measurement is done at relevant points. 1914 // \note Setting inputs and drawing are done twice in order to find out the time for actual compiling. 1915 1916 // \note Shader data (sources and inputs) are generated and GL shader and program objects are created before any time measurements. 1917 ProgramContext progCtx = generateShaderData((int)measurements.size()); 1918 ShadersAndProgram shadersAndProgram = createShadersAndProgram(); 1919 BuildInfo buildInfo; 1920 1921 if (m_addWhitespaceAndComments) 1922 { 1923 const deUint32 hash = m_startHash ^ (deUint32)deInt32Hash((deInt32)measurements.size()); 1924 progCtx.vertShaderSource = strWithWhiteSpaceAndComments(progCtx.vertShaderSource, hash); 1925 progCtx.fragShaderSource = strWithWhiteSpaceAndComments(progCtx.fragShaderSource, hash); 1926 } 1927 1928 if (WARMUP_CPU_BEFORE_EACH_MEASUREMENT) 1929 tcu::warmupCPU(); 1930 1931 // \note Do NOT do anything too hefty between the first and last deGetMicroseconds() here (other than the gl calls); it would disturb the measurement. 1932 1933 deUint64 startTime = deGetMicroseconds(); 1934 1935 setShaderSources(shadersAndProgram.vertShader, shadersAndProgram.fragShader, progCtx); 1936 deUint64 shaderSourceSetEndTime = deGetMicroseconds(); 1937 1938 buildInfo.vertCompileSuccess = compileShader(shadersAndProgram.vertShader); 1939 deUint64 vertexShaderCompileEndTime = deGetMicroseconds(); 1940 1941 buildInfo.fragCompileSuccess = compileShader(shadersAndProgram.fragShader); 1942 deUint64 fragmentShaderCompileEndTime = deGetMicroseconds(); 1943 1944 buildInfo.linkSuccess = linkAndUseProgram(shadersAndProgram.program); 1945 deUint64 programLinkEndTime = deGetMicroseconds(); 1946 1947 // Check compilation and linking status here, after all compilation and linking gl calls are made. 1948 if (!(buildInfo.vertCompileSuccess && buildInfo.fragCompileSuccess && buildInfo.linkSuccess)) 1949 { 1950 buildInfo.logs = getLogs(shadersAndProgram); 1951 logProgramData(buildInfo, progCtx); 1952 cleanup(shadersAndProgram, progCtx, buildInfo.linkSuccess); 1953 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compilation failed"); 1954 return STOP; 1955 } 1956 1957 setShaderInputs(shadersAndProgram.program, progCtx); 1958 deUint64 firstShaderInputSetEndTime = deGetMicroseconds(); 1959 1960 // Draw for the first time. 1961 draw(); 1962 deUint64 firstDrawEndTime = deGetMicroseconds(); 1963 1964 // Set inputs and draw again. 1965 1966 setShaderInputs(shadersAndProgram.program, progCtx); 1967 deUint64 secondShaderInputSetEndTime = deGetMicroseconds(); 1968 1969 draw(); 1970 deUint64 secondDrawEndTime = deGetMicroseconds(); 1971 1972 // De-initializations (detach shaders etc.). 1973 1974 buildInfo.logs = getLogs(shadersAndProgram); 1975 cleanup(shadersAndProgram, progCtx, buildInfo.linkSuccess); 1976 1977 // Output measurement log later (after last measurement). 1978 1979 measurements.push_back(Measurement((deInt64)(shaderSourceSetEndTime - startTime), 1980 (deInt64)(vertexShaderCompileEndTime - shaderSourceSetEndTime), 1981 (deInt64)(fragmentShaderCompileEndTime - vertexShaderCompileEndTime), 1982 (deInt64)(programLinkEndTime - fragmentShaderCompileEndTime), 1983 (deInt64)(firstShaderInputSetEndTime - programLinkEndTime), 1984 (deInt64)(firstDrawEndTime - firstShaderInputSetEndTime), 1985 (deInt64)(secondShaderInputSetEndTime - firstDrawEndTime), 1986 (deInt64)(secondDrawEndTime - secondShaderInputSetEndTime))); 1987 1988 latestBuildInfo = buildInfo; 1989 latestProgramContext = progCtx; 1990 1991 m_testCtx.touchWatchdog(); // \note Measurements may take a while in a bad case. 1992 } 1993 1994 // End of test case, log information about measurements. 1995 { 1996 TestLog& log = m_testCtx.getLog(); 1997 1998 vector<deInt64> sourceSetTimes; 1999 vector<deInt64> vertexCompileTimes; 2000 vector<deInt64> fragmentCompileTimes; 2001 vector<deInt64> programLinkTimes; 2002 vector<deInt64> firstInputSetTimes; 2003 vector<deInt64> firstDrawTimes; 2004 vector<deInt64> secondInputTimes; 2005 vector<deInt64> secondDrawTimes; 2006 vector<deInt64> firstPhaseTimes; 2007 vector<deInt64> secondPhaseTimes; 2008 vector<deInt64> totalTimesWithoutDraw; 2009 vector<deInt64> specializationTimes; 2010 2011 if (!m_avoidCache) 2012 log << TestLog::Message << "Note: Testing cache hits, so the medians and averages exclude the first iteration." << TestLog::EndMessage; 2013 2014 log << TestLog::Message << "Note: \"Specialization time\" means first draw time minus second draw time." << TestLog::EndMessage 2015 << TestLog::Message << "Note: \"Compilation time\" means the time up to (and including) linking, plus specialization time." << TestLog::EndMessage; 2016 2017 log << TestLog::Section("IterationMeasurements", "Iteration measurements of compilation and linking times"); 2018 2019 DE_ASSERT((int)measurements.size() > (m_avoidCache ? 0 : 1)); 2020 2021 for (int ndx = 0; ndx < (int)measurements.size(); ndx++) 2022 { 2023 const Measurement& curMeas = measurements[ndx]; 2024 2025 // Subtract time of second phase (second input setup and draw) from first (from start to end of first draw). 2026 // \note Cap if second phase seems unreasonably high (higher than first input set and draw). 2027 deInt64 timeWithoutDraw = curMeas.totalTimeWithoutDraw(); 2028 2029 // Specialization time = first draw - second draw time. Again, cap at 0 if second draw was longer than first draw. 2030 deInt64 specializationTime = de::max<deInt64>(0, curMeas.firstDrawTime - curMeas.secondDrawTime); 2031 2032 if (ndx > 0 || m_avoidCache) // \note When allowing cache hits, don't account for the first measurement when calculating median or average. 2033 { 2034 sourceSetTimes.push_back (curMeas.sourceSetTime); 2035 vertexCompileTimes.push_back (curMeas.vertexCompileTime); 2036 fragmentCompileTimes.push_back (curMeas.fragmentCompileTime); 2037 programLinkTimes.push_back (curMeas.programLinkTime); 2038 firstInputSetTimes.push_back (curMeas.firstInputSetTime); 2039 firstDrawTimes.push_back (curMeas.firstDrawTime); 2040 firstPhaseTimes.push_back (curMeas.firstPhase()); 2041 secondDrawTimes.push_back (curMeas.secondDrawTime); 2042 secondInputTimes.push_back (curMeas.secondInputSetTime); 2043 secondPhaseTimes.push_back (curMeas.secondPhase()); 2044 totalTimesWithoutDraw.push_back (timeWithoutDraw); 2045 specializationTimes.push_back (specializationTime); 2046 } 2047 2048 // Log this measurement. 2049 log << TestLog::Float("Measurement" + de::toString(ndx) + "CompilationTime", 2050 "Measurement " + de::toString(ndx) + " compilation time", 2051 "ms", QP_KEY_TAG_TIME, (float)timeWithoutDraw / 1000.0f) 2052 << TestLog::Float("Measurement" + de::toString(ndx) + "SpecializationTime", 2053 "Measurement " + de::toString(ndx) + " specialization time", 2054 "ms", QP_KEY_TAG_TIME, (float)specializationTime / 1000.0f); 2055 } 2056 2057 // Log some statistics. 2058 2059 for (int entireRangeOrLowestHalf = 0; entireRangeOrLowestHalf < 2; entireRangeOrLowestHalf++) 2060 { 2061 bool isEntireRange = entireRangeOrLowestHalf == 0; 2062 string statNamePrefix = isEntireRange ? "" : "LowestHalf"; 2063 vector<deInt64> rangeTotalTimes = isEntireRange ? totalTimesWithoutDraw : vectorLowestPercentage(totalTimesWithoutDraw, 0.5f); 2064 vector<deInt64> rangeSpecializationTimes = isEntireRange ? specializationTimes : vectorLowestPercentage(specializationTimes, 0.5f); 2065 2066 #define LOG_COMPILE_SPECIALIZE_TIME_STAT(NAME, DESC, FUNC) \ 2067 log << TestLog::Float(statNamePrefix + "CompilationTime" + (NAME), (DESC) + string(" of compilation time"), "ms", QP_KEY_TAG_TIME, (FUNC)(rangeTotalTimes)/1000.0f) \ 2068 << TestLog::Float(statNamePrefix + "SpecializationTime" + (NAME), (DESC) + string(" of specialization time"), "ms", QP_KEY_TAG_TIME, (FUNC)(rangeSpecializationTimes)/1000.0f) 2069 2070 #define LOG_COMPILE_SPECIALIZE_RELATIVE_STAT(NAME, DESC, FUNC) \ 2071 log << TestLog::Float(statNamePrefix + "CompilationTime" + (NAME), (DESC) + string(" of compilation time"), "", QP_KEY_TAG_NONE, (FUNC)(rangeTotalTimes)) \ 2072 << TestLog::Float(statNamePrefix + "SpecializationTime" + (NAME), (DESC) + string(" of specialization time"), "", QP_KEY_TAG_NONE, (FUNC)(rangeSpecializationTimes)) 2073 2074 log << TestLog::Message << "\nStatistics computed from " 2075 << (isEntireRange ? "all" : "only the lowest 50%") 2076 << " of the above measurements:" 2077 << TestLog::EndMessage; 2078 2079 LOG_COMPILE_SPECIALIZE_TIME_STAT ("Median", "Median", vectorFloatMedian); 2080 LOG_COMPILE_SPECIALIZE_TIME_STAT ("Average", "Average", vectorFloatAverage); 2081 LOG_COMPILE_SPECIALIZE_TIME_STAT ("Minimum", "Minimum", vectorFloatMinimum); 2082 LOG_COMPILE_SPECIALIZE_TIME_STAT ("Maximum", "Maximum", vectorFloatMaximum); 2083 LOG_COMPILE_SPECIALIZE_TIME_STAT ("MedianAbsoluteDeviation", "Median absolute deviation", vectorFloatMedianAbsoluteDeviation); 2084 LOG_COMPILE_SPECIALIZE_RELATIVE_STAT ("RelativeMedianAbsoluteDeviation", "Relative median absolute deviation", vectorFloatRelativeMedianAbsoluteDeviation); 2085 LOG_COMPILE_SPECIALIZE_TIME_STAT ("StandardDeviation", "Standard deviation", vectorFloatStandardDeviation); 2086 LOG_COMPILE_SPECIALIZE_RELATIVE_STAT ("RelativeStandardDeviation", "Relative standard deviation", vectorFloatRelativeStandardDeviation); 2087 LOG_COMPILE_SPECIALIZE_TIME_STAT ("MaxMinusMin", "Max-min", vectorFloatMaximumMinusMinimum); 2088 LOG_COMPILE_SPECIALIZE_RELATIVE_STAT ("RelativeMaxMinusMin", "Relative max-min", vectorFloatRelativeMaximumMinusMinimum); 2089 2090 #undef LOG_COMPILE_SPECIALIZE_RELATIVE_STAT 2091 #undef LOG_COMPILE_SPECIALIZE_TIME_STAT 2092 2093 if (!isEntireRange && vectorFloatRelativeMedianAbsoluteDeviation(rangeTotalTimes) > RELATIVE_MEDIAN_ABSOLUTE_DEVIATION_THRESHOLD) 2094 log << TestLog::Message << "\nWARNING: couldn't achieve relative median absolute deviation under threshold value " 2095 << RELATIVE_MEDIAN_ABSOLUTE_DEVIATION_THRESHOLD 2096 << " for compilation time of the lowest 50% of measurements" << TestLog::EndMessage; 2097 } 2098 2099 log << TestLog::EndSection; // End section IterationMeasurements 2100 2101 for (int medianOrAverage = 0; medianOrAverage < 2; medianOrAverage++) 2102 { 2103 typedef float (*VecFunc)(const vector<deInt64>&); 2104 2105 bool isMedian = medianOrAverage == 0; 2106 string singular = isMedian ? "Median" : "Average"; 2107 string plural = singular + "s"; 2108 VecFunc func = isMedian ? (VecFunc) vectorFloatMedian<deInt64> : (VecFunc) vectorFloatAverage<deInt64>; 2109 2110 log << TestLog::Section(plural + "PerPhase", plural + " per phase"); 2111 2112 for (int entireRangeOrLowestHalf = 0; entireRangeOrLowestHalf < 2; entireRangeOrLowestHalf++) 2113 { 2114 bool isEntireRange = entireRangeOrLowestHalf == 0; 2115 string statNamePrefix = isEntireRange ? "" : "LowestHalf"; 2116 float rangeSizeRatio = isEntireRange ? 1.0f : 0.5f; 2117 2118 #define LOG_TIME(NAME, DESC, DATA) log << TestLog::Float(statNamePrefix + (NAME) + singular, singular + " of " + (DESC), "ms", QP_KEY_TAG_TIME, func(vectorLowestPercentage((DATA), rangeSizeRatio))/1000.0f); 2119 2120 log << TestLog::Message << (isEntireRange ? "For all measurements:" : "\nFor only the lowest 50% of the measurements:") << TestLog::EndMessage; 2121 LOG_TIME("ShaderSourceSetTime", "shader source set time", sourceSetTimes); 2122 LOG_TIME("VertexShaderCompileTime", "vertex shader compile time", vertexCompileTimes); 2123 LOG_TIME("FragmentShaderCompileTime", "fragment shader compile time", fragmentCompileTimes); 2124 LOG_TIME("ProgramLinkTime", "program link time", programLinkTimes); 2125 LOG_TIME("FirstShaderInputSetTime", "first shader input set time", firstInputSetTimes); 2126 LOG_TIME("FirstDrawTime", "first draw time", firstDrawTimes); 2127 LOG_TIME("SecondShaderInputSetTime", "second shader input set time", secondInputTimes); 2128 LOG_TIME("SecondDrawTime", "second draw time", secondDrawTimes); 2129 2130 #undef LOG_TIME 2131 } 2132 2133 log << TestLog::EndSection; 2134 } 2135 2136 // Set result. 2137 2138 { 2139 log << TestLog::Message << "Note: test result is the first quartile (i.e. median of the lowest half of measurements) of compilation times" << TestLog::EndMessage; 2140 float result = vectorFloatFirstQuartile(totalTimesWithoutDraw) / 1000.0f; 2141 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString(result, 2).c_str()); 2142 } 2143 2144 // Log shaders. 2145 2146 if (m_avoidCache || m_addWhitespaceAndComments) 2147 { 2148 string msg = "Note: the following shaders are the ones from the last iteration; "; 2149 2150 if (m_avoidCache) 2151 msg += "variables' names and some constant expressions"; 2152 if (m_addWhitespaceAndComments) 2153 msg += string(m_avoidCache ? " as well as " : "") + "whitespace and comments"; 2154 2155 msg += " differ between iterations."; 2156 2157 log << TestLog::Message << msg.c_str() << TestLog::EndMessage; 2158 } 2159 2160 logProgramData(latestBuildInfo, latestProgramContext); 2161 2162 return STOP; 2163 } 2164 } 2165 2166 ShaderCompilerLightCase::ShaderCompilerLightCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments, bool isVertexCase, int numLights, LightType lightType) 2167 : ShaderCompilerCase (context, name, description, caseID, avoidCache, addWhitespaceAndComments) 2168 , m_numLights (numLights) 2169 , m_isVertexCase (isVertexCase) 2170 , m_lightType (lightType) 2171 , m_texture (DE_NULL) 2172 { 2173 } 2174 2175 ShaderCompilerLightCase::~ShaderCompilerLightCase (void) 2176 { 2177 ShaderCompilerLightCase::deinit(); 2178 } 2179 2180 void ShaderCompilerLightCase::deinit (void) 2181 { 2182 delete m_texture; 2183 m_texture = DE_NULL; 2184 } 2185 2186 void ShaderCompilerLightCase::init (void) 2187 { 2188 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2189 2190 // Setup texture. 2191 2192 DE_ASSERT(m_texture == DE_NULL); 2193 2194 m_texture = new glu::Texture2D(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, TEXTURE_WIDTH, TEXTURE_HEIGHT); 2195 2196 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(m_texture->getRefTexture().getFormat()); 2197 2198 m_texture->getRefTexture().allocLevel(0); 2199 tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(0), fmtInfo.valueMin, fmtInfo.valueMax); 2200 2201 gl.activeTexture(GL_TEXTURE0); 2202 gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture()); 2203 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2204 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2205 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 2206 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 2207 m_texture->upload(); 2208 2209 ShaderCompilerCase::init(); 2210 } 2211 2212 ShaderCompilerCase::ProgramContext ShaderCompilerLightCase::generateShaderData (int measurementNdx) const 2213 { 2214 deUint32 specID = getSpecializationID(measurementNdx); 2215 string nameSpec = getNameSpecialization(specID); 2216 ProgramContext result; 2217 2218 result.vertShaderSource = specializeShaderSource(lightVertexTemplate(m_numLights, m_isVertexCase, m_lightType), specID, SHADER_VALIDITY_VALID); 2219 result.fragShaderSource = specializeShaderSource(lightFragmentTemplate(m_numLights, m_isVertexCase, m_lightType), specID, SHADER_VALIDITY_VALID); 2220 result.vertexAttributes = lightShaderAttributes(nameSpec); 2221 result.uniforms = lightShaderUniforms(nameSpec, m_numLights, m_lightType); 2222 2223 return result; 2224 } 2225 2226 ShaderCompilerTextureCase::ShaderCompilerTextureCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments, int numLookups, ConditionalUsage conditionalUsage, ConditionalType conditionalType) 2227 : ShaderCompilerCase (context, name, description, caseID, avoidCache, addWhitespaceAndComments) 2228 , m_numLookups (numLookups) 2229 , m_conditionalUsage (conditionalUsage) 2230 , m_conditionalType (conditionalType) 2231 { 2232 } 2233 2234 ShaderCompilerTextureCase::~ShaderCompilerTextureCase (void) 2235 { 2236 ShaderCompilerTextureCase::deinit(); 2237 } 2238 2239 void ShaderCompilerTextureCase::deinit (void) 2240 { 2241 for (vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++) 2242 delete *i; 2243 m_textures.clear(); 2244 } 2245 2246 void ShaderCompilerTextureCase::init (void) 2247 { 2248 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2249 2250 // Setup texture. 2251 2252 DE_ASSERT(m_textures.empty()); 2253 2254 m_textures.reserve(m_numLookups); 2255 2256 for (int i = 0; i < m_numLookups; i++) 2257 { 2258 glu::Texture2D* tex = new glu::Texture2D(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, TEXTURE_WIDTH, TEXTURE_HEIGHT); 2259 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(tex->getRefTexture().getFormat()); 2260 2261 tex->getRefTexture().allocLevel(0); 2262 tcu::fillWithComponentGradients(tex->getRefTexture().getLevel(0), fmtInfo.valueMin, fmtInfo.valueMax); 2263 2264 gl.activeTexture(GL_TEXTURE0 + i); 2265 gl.bindTexture(GL_TEXTURE_2D, tex->getGLTexture()); 2266 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2267 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2268 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 2269 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 2270 tex->upload(); 2271 2272 m_textures.push_back(tex); 2273 } 2274 2275 ShaderCompilerCase::init(); 2276 } 2277 2278 ShaderCompilerCase::ProgramContext ShaderCompilerTextureCase::generateShaderData (int measurementNdx) const 2279 { 2280 deUint32 specID = getSpecializationID(measurementNdx); 2281 string nameSpec = getNameSpecialization(specID); 2282 ProgramContext result; 2283 2284 result.vertShaderSource = specializeShaderSource(textureLookupVertexTemplate(m_conditionalUsage, m_conditionalType), specID, SHADER_VALIDITY_VALID); 2285 result.fragShaderSource = specializeShaderSource(textureLookupFragmentTemplate(m_numLookups, m_conditionalUsage, m_conditionalType), specID, SHADER_VALIDITY_VALID); 2286 result.vertexAttributes = textureLookupShaderAttributes(nameSpec, m_conditionalUsage, m_conditionalType); 2287 result.uniforms = textureLookupShaderUniforms(nameSpec, m_numLookups, m_conditionalUsage, m_conditionalType); 2288 2289 return result; 2290 } 2291 2292 ShaderCompilerLoopCase::ShaderCompilerLoopCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments, bool isVertexCase, LoopType type, int numLoopIterations, int nestingDepth) 2293 : ShaderCompilerCase (context, name, description, caseID, avoidCache, addWhitespaceAndComments) 2294 , m_numLoopIterations (numLoopIterations) 2295 , m_nestingDepth (nestingDepth) 2296 , m_isVertexCase (isVertexCase) 2297 , m_type (type) 2298 { 2299 } 2300 2301 ShaderCompilerLoopCase::~ShaderCompilerLoopCase (void) 2302 { 2303 } 2304 2305 ShaderCompilerCase::ProgramContext ShaderCompilerLoopCase::generateShaderData (int measurementNdx) const 2306 { 2307 deUint32 specID = getSpecializationID(measurementNdx); 2308 string nameSpec = getNameSpecialization(specID); 2309 ProgramContext result; 2310 2311 result.vertShaderSource = specializeShaderSource(loopVertexTemplate(m_type, m_isVertexCase, m_numLoopIterations, m_nestingDepth), specID, SHADER_VALIDITY_VALID); 2312 result.fragShaderSource = specializeShaderSource(loopFragmentTemplate(m_type, m_isVertexCase, m_numLoopIterations, m_nestingDepth), specID, SHADER_VALIDITY_VALID); 2313 2314 result.vertexAttributes = loopShaderAttributes(nameSpec, m_type, m_numLoopIterations); 2315 result.uniforms = loopShaderUniforms(nameSpec, m_type, m_numLoopIterations); 2316 2317 return result; 2318 } 2319 2320 ShaderCompilerOperCase::ShaderCompilerOperCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments, bool isVertexCase, const char* oper, int numOperations) 2321 : ShaderCompilerCase (context, name, description, caseID, avoidCache, addWhitespaceAndComments) 2322 , m_oper (oper) 2323 , m_numOperations (numOperations) 2324 , m_isVertexCase (isVertexCase) 2325 { 2326 } 2327 2328 ShaderCompilerOperCase::~ShaderCompilerOperCase (void) 2329 { 2330 } 2331 2332 ShaderCompilerCase::ProgramContext ShaderCompilerOperCase::generateShaderData (int measurementNdx) const 2333 { 2334 deUint32 specID = getSpecializationID(measurementNdx); 2335 string nameSpec = getNameSpecialization(specID); 2336 ProgramContext result; 2337 2338 if (m_isVertexCase) 2339 { 2340 result.vertShaderSource = specializeShaderSource(binaryOpVertexTemplate(m_numOperations, m_oper.c_str()), specID, SHADER_VALIDITY_VALID); 2341 result.fragShaderSource = specializeShaderSource(singleVaryingFragmentTemplate(), specID, SHADER_VALIDITY_VALID); 2342 } 2343 else 2344 { 2345 result.vertShaderSource = specializeShaderSource(singleVaryingVertexTemplate(), specID, SHADER_VALIDITY_VALID); 2346 result.fragShaderSource = specializeShaderSource(binaryOpFragmentTemplate(m_numOperations, m_oper.c_str()), specID, SHADER_VALIDITY_VALID); 2347 } 2348 2349 result.vertexAttributes = singleValueShaderAttributes(nameSpec); 2350 2351 result.uniforms.clear(); // No uniforms used. 2352 2353 return result; 2354 } 2355 2356 ShaderCompilerMandelbrotCase::ShaderCompilerMandelbrotCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments, int numFractalIterations) 2357 : ShaderCompilerCase (context, name, description, caseID, avoidCache, addWhitespaceAndComments) 2358 , m_numFractalIterations (numFractalIterations) 2359 { 2360 } 2361 2362 ShaderCompilerMandelbrotCase::~ShaderCompilerMandelbrotCase (void) 2363 { 2364 } 2365 2366 ShaderCompilerCase::ProgramContext ShaderCompilerMandelbrotCase::generateShaderData (int measurementNdx) const 2367 { 2368 deUint32 specID = getSpecializationID(measurementNdx); 2369 string nameSpec = getNameSpecialization(specID); 2370 ProgramContext result; 2371 2372 result.vertShaderSource = specializeShaderSource(mandelbrotVertexTemplate(), specID, SHADER_VALIDITY_VALID); 2373 result.fragShaderSource = specializeShaderSource(mandelbrotFragmentTemplate(m_numFractalIterations), specID, SHADER_VALIDITY_VALID); 2374 2375 result.vertexAttributes = mandelbrotShaderAttributes(nameSpec); 2376 result.uniforms = mandelbrotShaderUniforms(nameSpec); 2377 2378 return result; 2379 } 2380 2381 InvalidShaderCompilerCase::InvalidShaderCompilerCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType) 2382 : TestCase (context, tcu::NODETYPE_PERFORMANCE, name, description) 2383 , m_invalidityType (invalidityType) 2384 , m_startHash ((deUint32)(deUint64Hash(deGetTime()) ^ deUint64Hash(deGetMicroseconds()) ^ deInt32Hash(caseID))) 2385 { 2386 int cmdLineIterCount = context.getTestContext().getCommandLine().getTestIterationCount(); 2387 m_minimumMeasurementCount = cmdLineIterCount > 0 ? cmdLineIterCount : DEFAULT_MINIMUM_MEASUREMENT_COUNT; 2388 m_maximumMeasurementCount = 3*m_minimumMeasurementCount; 2389 } 2390 2391 InvalidShaderCompilerCase::~InvalidShaderCompilerCase (void) 2392 { 2393 } 2394 2395 deUint32 InvalidShaderCompilerCase::getSpecializationID (int measurementNdx) const 2396 { 2397 return m_startHash ^ (deUint32)deInt32Hash((deInt32)measurementNdx); 2398 } 2399 2400 InvalidShaderCompilerCase::Shaders InvalidShaderCompilerCase::createShaders (void) const 2401 { 2402 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2403 Shaders result; 2404 2405 result.vertShader = gl.createShader(GL_VERTEX_SHADER); 2406 result.fragShader = gl.createShader(GL_FRAGMENT_SHADER); 2407 2408 return result; 2409 } 2410 2411 void InvalidShaderCompilerCase::setShaderSources (const Shaders& shaders, const ProgramContext& progCtx) const 2412 { 2413 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2414 const char* vertShaderSourceCStr = progCtx.vertShaderSource.c_str(); 2415 const char* fragShaderSourceCStr = progCtx.fragShaderSource.c_str(); 2416 gl.shaderSource(shaders.vertShader, 1, &vertShaderSourceCStr, DE_NULL); 2417 gl.shaderSource(shaders.fragShader, 1, &fragShaderSourceCStr, DE_NULL); 2418 } 2419 2420 bool InvalidShaderCompilerCase::compileShader (deUint32 shader) const 2421 { 2422 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2423 GLint status; 2424 gl.compileShader(shader); 2425 gl.getShaderiv(shader, GL_COMPILE_STATUS, &status); 2426 return status != 0; 2427 } 2428 2429 void InvalidShaderCompilerCase::logProgramData (const BuildInfo& buildInfo, const ProgramContext& progCtx) const 2430 { 2431 m_testCtx.getLog() << TestLog::ShaderProgram(false, "(No linking done)") 2432 << TestLog::Shader(QP_SHADER_TYPE_VERTEX, progCtx.vertShaderSource, buildInfo.vertCompileSuccess, buildInfo.logs.vert) 2433 << TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, progCtx.fragShaderSource, buildInfo.fragCompileSuccess, buildInfo.logs.frag) 2434 << TestLog::EndShaderProgram; 2435 } 2436 2437 InvalidShaderCompilerCase::Logs InvalidShaderCompilerCase::getLogs (const Shaders& shaders) const 2438 { 2439 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2440 Logs result; 2441 2442 result.vert = getShaderInfoLog(gl, shaders.vertShader); 2443 result.frag = getShaderInfoLog(gl, shaders.fragShader); 2444 2445 return result; 2446 } 2447 2448 void InvalidShaderCompilerCase::cleanup (const Shaders& shaders) const 2449 { 2450 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2451 2452 gl.deleteShader(shaders.vertShader); 2453 gl.deleteShader(shaders.fragShader); 2454 } 2455 2456 bool InvalidShaderCompilerCase::goodEnoughMeasurements (const vector<Measurement>& measurements) const 2457 { 2458 if ((int)measurements.size() < m_minimumMeasurementCount) 2459 return false; 2460 else 2461 { 2462 if ((int)measurements.size() >= m_maximumMeasurementCount) 2463 return true; 2464 else 2465 { 2466 vector<deInt64> totalTimes; 2467 for (int i = 0; i < (int)measurements.size(); i++) 2468 totalTimes.push_back(measurements[i].totalTime()); 2469 return vectorFloatRelativeMedianAbsoluteDeviation(vectorLowestPercentage(totalTimes, 0.5f)) < RELATIVE_MEDIAN_ABSOLUTE_DEVIATION_THRESHOLD; 2470 } 2471 } 2472 } 2473 2474 InvalidShaderCompilerCase::IterateResult InvalidShaderCompilerCase::iterate (void) 2475 { 2476 ShaderValidity shaderValidity = m_invalidityType == INVALIDITY_INVALID_CHAR ? SHADER_VALIDITY_INVALID_CHAR 2477 : m_invalidityType == INVALIDITY_SEMANTIC_ERROR ? SHADER_VALIDITY_SEMANTIC_ERROR 2478 : SHADER_VALIDITY_LAST; 2479 2480 DE_ASSERT(shaderValidity != SHADER_VALIDITY_LAST); 2481 2482 // Before actual measurements, compile a dummy shader to avoid possible initial slowdowns in the actual test. 2483 { 2484 deUint32 specID = getSpecializationID(0); 2485 ProgramContext progCtx; 2486 progCtx.vertShaderSource = specializeShaderSource(singleVaryingVertexTemplate(), specID, shaderValidity); 2487 progCtx.fragShaderSource = specializeShaderSource(singleVaryingFragmentTemplate(), specID, shaderValidity); 2488 2489 Shaders shaders = createShaders(); 2490 setShaderSources(shaders, progCtx); 2491 2492 BuildInfo buildInfo; 2493 buildInfo.vertCompileSuccess = compileShader(shaders.vertShader); 2494 buildInfo.fragCompileSuccess = compileShader(shaders.fragShader); 2495 if (buildInfo.vertCompileSuccess || buildInfo.fragCompileSuccess) 2496 { 2497 buildInfo.logs = getLogs(shaders); 2498 logProgramData(buildInfo, progCtx); 2499 cleanup(shaders); 2500 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compilation of a shader erroneously succeeded"); 2501 return STOP; 2502 } 2503 cleanup(shaders); 2504 } 2505 2506 vector<Measurement> measurements; 2507 // \note These are logged after measurements are done. 2508 ProgramContext latestProgramContext; 2509 BuildInfo latestBuildInfo; 2510 2511 if (WARMUP_CPU_AT_BEGINNING_OF_CASE) 2512 tcu::warmupCPU(); 2513 2514 // Actual test measurements. 2515 while (!goodEnoughMeasurements(measurements)) 2516 { 2517 // Create shader and compile. Measure time. 2518 2519 // \note Shader sources are generated and GL shader objects are created before any time measurements. 2520 ProgramContext progCtx = generateShaderSources((int)measurements.size()); 2521 Shaders shaders = createShaders(); 2522 BuildInfo buildInfo; 2523 2524 if (WARMUP_CPU_BEFORE_EACH_MEASUREMENT) 2525 tcu::warmupCPU(); 2526 2527 // \note Do NOT do anything too hefty between the first and last deGetMicroseconds() here (other than the gl calls); it would disturb the measurement. 2528 2529 deUint64 startTime = deGetMicroseconds(); 2530 2531 setShaderSources(shaders, progCtx); 2532 deUint64 shaderSourceSetEndTime = deGetMicroseconds(); 2533 2534 buildInfo.vertCompileSuccess = compileShader(shaders.vertShader); 2535 deUint64 vertexShaderCompileEndTime = deGetMicroseconds(); 2536 2537 buildInfo.fragCompileSuccess = compileShader(shaders.fragShader); 2538 deUint64 fragmentShaderCompileEndTime = deGetMicroseconds(); 2539 2540 buildInfo.logs = getLogs(shaders); 2541 2542 // Both shader compilations should have failed. 2543 if (buildInfo.vertCompileSuccess || buildInfo.fragCompileSuccess) 2544 { 2545 logProgramData(buildInfo, progCtx); 2546 cleanup(shaders); 2547 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compilation of a shader erroneously succeeded"); 2548 return STOP; 2549 } 2550 2551 // De-initializations (delete shaders). 2552 2553 cleanup(shaders); 2554 2555 // Output measurement log later (after last measurement). 2556 2557 measurements.push_back(Measurement((deInt64)(shaderSourceSetEndTime - startTime), 2558 (deInt64)(vertexShaderCompileEndTime - shaderSourceSetEndTime), 2559 (deInt64)(fragmentShaderCompileEndTime - vertexShaderCompileEndTime))); 2560 2561 latestBuildInfo = buildInfo; 2562 latestProgramContext = progCtx; 2563 2564 m_testCtx.touchWatchdog(); // \note Measurements may take a while in a bad case. 2565 } 2566 2567 // End of test case, log information about measurements. 2568 { 2569 TestLog& log = m_testCtx.getLog(); 2570 2571 vector<deInt64> sourceSetTimes; 2572 vector<deInt64> vertexCompileTimes; 2573 vector<deInt64> fragmentCompileTimes; 2574 vector<deInt64> totalTimes; 2575 2576 log << TestLog::Section("IterationMeasurements", "Iteration measurements of compilation times"); 2577 2578 for (int ndx = 0; ndx < (int)measurements.size(); ndx++) 2579 { 2580 sourceSetTimes.push_back (measurements[ndx].sourceSetTime); 2581 vertexCompileTimes.push_back (measurements[ndx].vertexCompileTime); 2582 fragmentCompileTimes.push_back (measurements[ndx].fragmentCompileTime); 2583 totalTimes.push_back (measurements[ndx].totalTime()); 2584 2585 // Log this measurement. 2586 log << TestLog::Float("Measurement" + de::toString(ndx) + "Time", 2587 "Measurement " + de::toString(ndx) + " time", 2588 "ms", QP_KEY_TAG_TIME, (float)measurements[ndx].totalTime()/1000.0f); 2589 } 2590 2591 // Log some statistics. 2592 2593 for (int entireRangeOrLowestHalf = 0; entireRangeOrLowestHalf < 2; entireRangeOrLowestHalf++) 2594 { 2595 bool isEntireRange = entireRangeOrLowestHalf == 0; 2596 string statNamePrefix = isEntireRange ? "" : "LowestHalf"; 2597 vector<deInt64> rangeTimes = isEntireRange ? totalTimes : vectorLowestPercentage(totalTimes, 0.5f); 2598 2599 log << TestLog::Message << "\nStatistics computed from " 2600 << (isEntireRange ? "all" : "only the lowest 50%") 2601 << " of the above measurements:" 2602 << TestLog::EndMessage; 2603 2604 #define LOG_TIME_STAT(NAME, DESC, FUNC) log << TestLog::Float(statNamePrefix + "TotalTime" + (NAME), (DESC) + string(" of total time"), "ms", QP_KEY_TAG_TIME, (FUNC)(rangeTimes)/1000.0f) 2605 #define LOG_RELATIVE_STAT(NAME, DESC, FUNC) log << TestLog::Float(statNamePrefix + "TotalTime" + (NAME), (DESC) + string(" of total time"), "", QP_KEY_TAG_NONE, (FUNC)(rangeTimes)) 2606 2607 LOG_TIME_STAT ("Median", "Median", vectorFloatMedian); 2608 LOG_TIME_STAT ("Average", "Average", vectorFloatAverage); 2609 LOG_TIME_STAT ("Minimum", "Minimum", vectorFloatMinimum); 2610 LOG_TIME_STAT ("Maximum", "Maximum", vectorFloatMaximum); 2611 LOG_TIME_STAT ("MedianAbsoluteDeviation", "Median absolute deviation", vectorFloatMedianAbsoluteDeviation); 2612 LOG_RELATIVE_STAT ("RelativeMedianAbsoluteDeviation", "Relative median absolute deviation", vectorFloatRelativeMedianAbsoluteDeviation); 2613 LOG_TIME_STAT ("StandardDeviation", "Standard deviation", vectorFloatStandardDeviation); 2614 LOG_RELATIVE_STAT ("RelativeStandardDeviation", "Relative standard deviation", vectorFloatRelativeStandardDeviation); 2615 LOG_TIME_STAT ("MaxMinusMin", "Max-min", vectorFloatMaximumMinusMinimum); 2616 LOG_RELATIVE_STAT ("RelativeMaxMinusMin", "Relative max-min", vectorFloatRelativeMaximumMinusMinimum); 2617 2618 #undef LOG_TIME_STAT 2619 #undef LOG_RELATIVE_STAT 2620 2621 if (!isEntireRange && vectorFloatRelativeMedianAbsoluteDeviation(rangeTimes) > RELATIVE_MEDIAN_ABSOLUTE_DEVIATION_THRESHOLD) 2622 log << TestLog::Message << "\nWARNING: couldn't achieve relative median absolute deviation under threshold value " << RELATIVE_MEDIAN_ABSOLUTE_DEVIATION_THRESHOLD << TestLog::EndMessage; 2623 } 2624 2625 log << TestLog::EndSection; // End section IterationMeasurements 2626 2627 for (int medianOrAverage = 0; medianOrAverage < 2; medianOrAverage++) 2628 { 2629 typedef float (*VecFunc)(const vector<deInt64>&); 2630 2631 bool isMedian = medianOrAverage == 0; 2632 string singular = isMedian ? "Median" : "Average"; 2633 string plural = singular + "s"; 2634 VecFunc func = isMedian ? (VecFunc) vectorFloatMedian<deInt64> : (VecFunc) vectorFloatAverage<deInt64>; 2635 2636 log << TestLog::Section(plural + "PerPhase", plural + " per phase"); 2637 2638 for (int entireRangeOrLowestHalf = 0; entireRangeOrLowestHalf < 2; entireRangeOrLowestHalf++) 2639 { 2640 bool isEntireRange = entireRangeOrLowestHalf == 0; 2641 string statNamePrefix = isEntireRange ? "" : "LowestHalf"; 2642 float rangeSizeRatio = isEntireRange ? 1.0f : 0.5f; 2643 2644 #define LOG_TIME(NAME, DESC, DATA) log << TestLog::Float(statNamePrefix + (NAME) + singular, singular + " of " + (DESC), "ms", QP_KEY_TAG_TIME, func(vectorLowestPercentage((DATA), rangeSizeRatio))/1000.0f); 2645 2646 log << TestLog::Message << (isEntireRange ? "For all measurements:" : "\nFor only the lowest 50% of the measurements:") << TestLog::EndMessage; 2647 LOG_TIME("ShaderSourceSetTime", "shader source set time", sourceSetTimes); 2648 LOG_TIME("VertexShaderCompileTime", "vertex shader compile time", vertexCompileTimes); 2649 LOG_TIME("FragmentShaderCompileTime", "fragment shader compile time", fragmentCompileTimes); 2650 2651 #undef LOG_TIME 2652 } 2653 2654 log << TestLog::EndSection; 2655 } 2656 2657 // Set result. 2658 2659 { 2660 log << TestLog::Message << "Note: test result is the first quartile (i.e. median of the lowest half of measurements) of total times" << TestLog::EndMessage; 2661 float result = vectorFloatFirstQuartile(totalTimes) / 1000.0f; 2662 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString(result, 2).c_str()); 2663 } 2664 2665 // Log shaders. 2666 2667 log << TestLog::Message << "Note: the following shaders are the ones from the last iteration; variables' names and some constant expressions differ between iterations." << TestLog::EndMessage; 2668 2669 logProgramData(latestBuildInfo, latestProgramContext); 2670 2671 return STOP; 2672 } 2673 } 2674 2675 InvalidShaderCompilerLightCase::InvalidShaderCompilerLightCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, bool isVertexCase, int numLights, LightType lightType) 2676 : InvalidShaderCompilerCase (context, name, description, caseID, invalidityType) 2677 , m_isVertexCase (isVertexCase) 2678 , m_numLights (numLights) 2679 , m_lightType (lightType) 2680 { 2681 } 2682 2683 InvalidShaderCompilerLightCase::~InvalidShaderCompilerLightCase (void) 2684 { 2685 } 2686 2687 InvalidShaderCompilerCase::ProgramContext InvalidShaderCompilerLightCase::generateShaderSources (int measurementNdx) const 2688 { 2689 deUint32 specID = getSpecializationID(measurementNdx); 2690 ProgramContext result; 2691 ShaderValidity shaderValidity = m_invalidityType == INVALIDITY_INVALID_CHAR ? SHADER_VALIDITY_INVALID_CHAR 2692 : m_invalidityType == INVALIDITY_SEMANTIC_ERROR ? SHADER_VALIDITY_SEMANTIC_ERROR 2693 : SHADER_VALIDITY_LAST; 2694 2695 DE_ASSERT(shaderValidity != SHADER_VALIDITY_LAST); 2696 2697 result.vertShaderSource = specializeShaderSource(lightVertexTemplate(m_numLights, m_isVertexCase, m_lightType), specID, shaderValidity); 2698 result.fragShaderSource = specializeShaderSource(lightFragmentTemplate(m_numLights, m_isVertexCase, m_lightType), specID, shaderValidity); 2699 2700 return result; 2701 } 2702 2703 InvalidShaderCompilerTextureCase::InvalidShaderCompilerTextureCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, int numLookups, ConditionalUsage conditionalUsage, ConditionalType conditionalType) 2704 : InvalidShaderCompilerCase (context, name, description, caseID, invalidityType) 2705 , m_numLookups (numLookups) 2706 , m_conditionalUsage (conditionalUsage) 2707 , m_conditionalType (conditionalType) 2708 { 2709 } 2710 2711 InvalidShaderCompilerTextureCase::~InvalidShaderCompilerTextureCase (void) 2712 { 2713 } 2714 2715 InvalidShaderCompilerCase::ProgramContext InvalidShaderCompilerTextureCase::generateShaderSources (int measurementNdx) const 2716 { 2717 deUint32 specID = getSpecializationID(measurementNdx); 2718 ProgramContext result; 2719 ShaderValidity shaderValidity = m_invalidityType == INVALIDITY_INVALID_CHAR ? SHADER_VALIDITY_INVALID_CHAR 2720 : m_invalidityType == INVALIDITY_SEMANTIC_ERROR ? SHADER_VALIDITY_SEMANTIC_ERROR 2721 : SHADER_VALIDITY_LAST; 2722 2723 DE_ASSERT(shaderValidity != SHADER_VALIDITY_LAST); 2724 2725 result.vertShaderSource = specializeShaderSource(textureLookupVertexTemplate(m_conditionalUsage, m_conditionalType), specID, shaderValidity); 2726 result.fragShaderSource = specializeShaderSource(textureLookupFragmentTemplate(m_numLookups, m_conditionalUsage, m_conditionalType), specID, shaderValidity); 2727 2728 return result; 2729 } 2730 2731 InvalidShaderCompilerLoopCase::InvalidShaderCompilerLoopCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, bool isVertexCase, LoopType type, int numLoopIterations, int nestingDepth) 2732 : InvalidShaderCompilerCase (context, name, description, caseID, invalidityType) 2733 , m_isVertexCase (isVertexCase) 2734 , m_numLoopIterations (numLoopIterations) 2735 , m_nestingDepth (nestingDepth) 2736 , m_type (type) 2737 { 2738 } 2739 2740 InvalidShaderCompilerLoopCase::~InvalidShaderCompilerLoopCase (void) 2741 { 2742 } 2743 2744 InvalidShaderCompilerCase::ProgramContext InvalidShaderCompilerLoopCase::generateShaderSources (int measurementNdx) const 2745 { 2746 deUint32 specID = getSpecializationID(measurementNdx); 2747 ProgramContext result; 2748 ShaderValidity shaderValidity = m_invalidityType == INVALIDITY_INVALID_CHAR ? SHADER_VALIDITY_INVALID_CHAR 2749 : m_invalidityType == INVALIDITY_SEMANTIC_ERROR ? SHADER_VALIDITY_SEMANTIC_ERROR 2750 : SHADER_VALIDITY_LAST; 2751 2752 DE_ASSERT(shaderValidity != SHADER_VALIDITY_LAST); 2753 2754 result.vertShaderSource = specializeShaderSource(loopVertexTemplate(m_type, m_isVertexCase, m_numLoopIterations, m_nestingDepth), specID, shaderValidity); 2755 result.fragShaderSource = specializeShaderSource(loopFragmentTemplate(m_type, m_isVertexCase, m_numLoopIterations, m_nestingDepth), specID, shaderValidity); 2756 2757 return result; 2758 } 2759 2760 InvalidShaderCompilerOperCase::InvalidShaderCompilerOperCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, bool isVertexCase, const char* oper, int numOperations) 2761 : InvalidShaderCompilerCase (context, name, description, caseID, invalidityType) 2762 , m_isVertexCase (isVertexCase) 2763 , m_oper (oper) 2764 , m_numOperations (numOperations) 2765 { 2766 } 2767 2768 InvalidShaderCompilerOperCase::~InvalidShaderCompilerOperCase (void) 2769 { 2770 } 2771 2772 InvalidShaderCompilerCase::ProgramContext InvalidShaderCompilerOperCase::generateShaderSources (int measurementNdx) const 2773 { 2774 deUint32 specID = getSpecializationID(measurementNdx); 2775 ProgramContext result; 2776 ShaderValidity shaderValidity = m_invalidityType == INVALIDITY_INVALID_CHAR ? SHADER_VALIDITY_INVALID_CHAR 2777 : m_invalidityType == INVALIDITY_SEMANTIC_ERROR ? SHADER_VALIDITY_SEMANTIC_ERROR 2778 : SHADER_VALIDITY_LAST; 2779 2780 DE_ASSERT(shaderValidity != SHADER_VALIDITY_LAST); 2781 2782 if (m_isVertexCase) 2783 { 2784 result.vertShaderSource = specializeShaderSource(binaryOpVertexTemplate(m_numOperations, m_oper.c_str()), specID, shaderValidity); 2785 result.fragShaderSource = specializeShaderSource(singleVaryingFragmentTemplate(), specID, shaderValidity); 2786 } 2787 else 2788 { 2789 result.vertShaderSource = specializeShaderSource(singleVaryingVertexTemplate(), specID, shaderValidity); 2790 result.fragShaderSource = specializeShaderSource(binaryOpFragmentTemplate(m_numOperations, m_oper.c_str()), specID, shaderValidity); 2791 } 2792 2793 return result; 2794 } 2795 2796 InvalidShaderCompilerMandelbrotCase::InvalidShaderCompilerMandelbrotCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, int numFractalIterations) 2797 : InvalidShaderCompilerCase (context, name, description, caseID, invalidityType) 2798 , m_numFractalIterations (numFractalIterations) 2799 { 2800 } 2801 2802 InvalidShaderCompilerMandelbrotCase::~InvalidShaderCompilerMandelbrotCase (void) 2803 { 2804 } 2805 2806 InvalidShaderCompilerCase::ProgramContext InvalidShaderCompilerMandelbrotCase::generateShaderSources (int measurementNdx) const 2807 { 2808 deUint32 specID = getSpecializationID(measurementNdx); 2809 ProgramContext result; 2810 ShaderValidity shaderValidity = m_invalidityType == INVALIDITY_INVALID_CHAR ? SHADER_VALIDITY_INVALID_CHAR 2811 : m_invalidityType == INVALIDITY_SEMANTIC_ERROR ? SHADER_VALIDITY_SEMANTIC_ERROR 2812 : SHADER_VALIDITY_LAST; 2813 2814 DE_ASSERT(shaderValidity != SHADER_VALIDITY_LAST); 2815 2816 result.vertShaderSource = specializeShaderSource(mandelbrotVertexTemplate(), specID, shaderValidity); 2817 result.fragShaderSource = specializeShaderSource(mandelbrotFragmentTemplate(m_numFractalIterations), specID, shaderValidity); 2818 2819 return result; 2820 } 2821 2822 void addShaderCompilationPerformanceCases (TestCaseGroup& parentGroup) 2823 { 2824 Context& context = parentGroup.getContext(); 2825 int caseID = 0; // Increment this after adding each case. Used for avoiding cache hits between cases. 2826 2827 TestCaseGroup* validGroup = new TestCaseGroup(context, "valid_shader", "Valid Shader Compiler Cases"); 2828 TestCaseGroup* invalidGroup = new TestCaseGroup(context, "invalid_shader", "Invalid Shader Compiler Cases"); 2829 TestCaseGroup* cacheGroup = new TestCaseGroup(context, "cache", "Allow shader caching"); 2830 parentGroup.addChild(validGroup); 2831 parentGroup.addChild(invalidGroup); 2832 parentGroup.addChild(cacheGroup); 2833 2834 TestCaseGroup* invalidCharGroup = new TestCaseGroup(context, "invalid_char", "Invalid Character Shader Compiler Cases"); 2835 TestCaseGroup* semanticErrorGroup = new TestCaseGroup(context, "semantic_error", "Semantic Error Shader Compiler Cases"); 2836 invalidGroup->addChild(invalidCharGroup); 2837 invalidGroup->addChild(semanticErrorGroup); 2838 2839 // Lighting shader compilation cases. 2840 2841 { 2842 static const int lightCounts[] = { 1, 2, 4, 8 }; 2843 2844 TestCaseGroup* validLightingGroup = new TestCaseGroup(context, "lighting", "Shader Compiler Lighting Cases"); 2845 TestCaseGroup* invalidCharLightingGroup = new TestCaseGroup(context, "lighting", "Invalid Character Shader Compiler Lighting Cases"); 2846 TestCaseGroup* semanticErrorLightingGroup = new TestCaseGroup(context, "lighting", "Semantic Error Shader Compiler Lighting Cases"); 2847 TestCaseGroup* cacheLightingGroup = new TestCaseGroup(context, "lighting", "Shader Compiler Lighting Cache Cases"); 2848 validGroup->addChild(validLightingGroup); 2849 invalidCharGroup->addChild(invalidCharLightingGroup); 2850 semanticErrorGroup->addChild(semanticErrorLightingGroup); 2851 cacheGroup->addChild(cacheLightingGroup); 2852 2853 for (int lightType = 0; lightType < (int)LIGHT_LAST; lightType++) 2854 { 2855 const char* lightTypeName = lightType == (int)LIGHT_DIRECTIONAL ? "directional" 2856 : lightType == (int)LIGHT_POINT ? "point" 2857 : DE_NULL; 2858 2859 DE_ASSERT(lightTypeName != DE_NULL); 2860 2861 for (int isFrag = 0; isFrag <= 1; isFrag++) 2862 { 2863 bool isVertex = isFrag == 0; 2864 const char* vertFragStr = isVertex ? "vertex" : "fragment"; 2865 2866 for (int lightCountNdx = 0; lightCountNdx < DE_LENGTH_OF_ARRAY(lightCounts); lightCountNdx++) 2867 { 2868 int numLights = lightCounts[lightCountNdx]; 2869 2870 string caseName = string("") + lightTypeName + "_" + de::toString(numLights) + "_lights_" + vertFragStr; 2871 2872 // Valid shader case, no-cache and cache versions. 2873 2874 validLightingGroup->addChild(new ShaderCompilerLightCase(context, caseName.c_str(), "", caseID++, true /* avoid cache */, false, isVertex, numLights, (LightType)lightType)); 2875 cacheLightingGroup->addChild(new ShaderCompilerLightCase(context, caseName.c_str(), "", caseID++, false /* allow cache */, false, isVertex, numLights, (LightType)lightType)); 2876 2877 // Invalid shader cases. 2878 2879 for (int invalidityType = 0; invalidityType < (int)InvalidShaderCompilerCase::INVALIDITY_LAST; invalidityType++) 2880 { 2881 TestCaseGroup* curInvalidGroup = invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_INVALID_CHAR ? invalidCharLightingGroup 2882 : invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_SEMANTIC_ERROR ? semanticErrorLightingGroup 2883 : DE_NULL; 2884 2885 DE_ASSERT(curInvalidGroup != DE_NULL); 2886 2887 curInvalidGroup->addChild(new InvalidShaderCompilerLightCase(context, caseName.c_str(), "", caseID++, (InvalidShaderCompilerCase::InvalidityType)invalidityType, isVertex, numLights, (LightType)lightType)); 2888 } 2889 } 2890 } 2891 } 2892 } 2893 2894 // Texture lookup shader compilation cases. 2895 2896 { 2897 static const int texLookupCounts[] = { 1, 2, 4, 8 }; 2898 2899 TestCaseGroup* validTexGroup = new TestCaseGroup(context, "texture", "Shader Compiler Texture Lookup Cases"); 2900 TestCaseGroup* invalidCharTexGroup = new TestCaseGroup(context, "texture", "Invalid Character Shader Compiler Texture Lookup Cases"); 2901 TestCaseGroup* semanticErrorTexGroup = new TestCaseGroup(context, "texture", "Semantic Error Shader Compiler Texture Lookup Cases"); 2902 TestCaseGroup* cacheTexGroup = new TestCaseGroup(context, "texture", "Shader Compiler Texture Lookup Cache Cases"); 2903 validGroup->addChild(validTexGroup); 2904 invalidCharGroup->addChild(invalidCharTexGroup); 2905 semanticErrorGroup->addChild(semanticErrorTexGroup); 2906 cacheGroup->addChild(cacheTexGroup); 2907 2908 for (int conditionalUsage = 0; conditionalUsage < (int)CONDITIONAL_USAGE_LAST; conditionalUsage++) 2909 { 2910 const char* conditionalUsageName = conditionalUsage == (int)CONDITIONAL_USAGE_NONE ? "no_conditionals" 2911 : conditionalUsage == (int)CONDITIONAL_USAGE_FIRST_HALF ? "first_half" 2912 : conditionalUsage == (int)CONDITIONAL_USAGE_EVERY_OTHER ? "every_other" 2913 : DE_NULL; 2914 2915 DE_ASSERT(conditionalUsageName != DE_NULL); 2916 2917 int lastConditionalType = conditionalUsage == (int)CONDITIONAL_USAGE_NONE ? 1 : (int)CONDITIONAL_TYPE_LAST; 2918 2919 for (int conditionalType = 0; conditionalType < lastConditionalType; conditionalType++) 2920 { 2921 const char* conditionalTypeName = conditionalType == (int)CONDITIONAL_TYPE_STATIC ? "static_conditionals" 2922 : conditionalType == (int)CONDITIONAL_TYPE_UNIFORM ? "uniform_conditionals" 2923 : conditionalType == (int)CONDITIONAL_TYPE_DYNAMIC ? "dynamic_conditionals" 2924 : DE_NULL; 2925 2926 DE_ASSERT(conditionalTypeName != DE_NULL); 2927 2928 for (int lookupCountNdx = 0; lookupCountNdx < DE_LENGTH_OF_ARRAY(texLookupCounts); lookupCountNdx++) 2929 { 2930 int numLookups = texLookupCounts[lookupCountNdx]; 2931 2932 string caseName = de::toString(numLookups) + "_lookups_" + conditionalUsageName + (conditionalUsage == (int)CONDITIONAL_USAGE_NONE ? "" : string("_") + conditionalTypeName); 2933 2934 // Valid shader case, no-cache and cache versions. 2935 2936 validTexGroup->addChild(new ShaderCompilerTextureCase(context, caseName.c_str(), "", caseID++, true /* avoid cache */, false, numLookups, (ConditionalUsage)conditionalUsage, (ConditionalType)conditionalType)); 2937 cacheTexGroup->addChild(new ShaderCompilerTextureCase(context, caseName.c_str(), "", caseID++, false /* allow cache */, false, numLookups, (ConditionalUsage)conditionalUsage, (ConditionalType)conditionalType)); 2938 2939 // Invalid shader cases. 2940 2941 for (int invalidityType = 0; invalidityType < (int)InvalidShaderCompilerCase::INVALIDITY_LAST; invalidityType++) 2942 { 2943 TestCaseGroup* curInvalidGroup = invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_INVALID_CHAR ? invalidCharTexGroup 2944 : invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_SEMANTIC_ERROR ? semanticErrorTexGroup 2945 : DE_NULL; 2946 2947 DE_ASSERT(curInvalidGroup != DE_NULL); 2948 2949 curInvalidGroup->addChild(new InvalidShaderCompilerTextureCase(context, caseName.c_str(), "", caseID++, (InvalidShaderCompilerCase::InvalidityType)invalidityType, numLookups, (ConditionalUsage)conditionalUsage, (ConditionalType)conditionalType)); 2950 } 2951 } 2952 } 2953 } 2954 } 2955 2956 // Loop shader compilation cases. 2957 2958 { 2959 static const int loopIterCounts[] = { 10, 100, 1000 }; 2960 static const int maxLoopNestingDepth = 3; 2961 static const int maxTotalLoopIterations = 2000; // If <loop iteration count> ** <loop nesting depth> (where ** is exponentiation) exceeds this, don't generate the case. 2962 2963 TestCaseGroup* validLoopGroup = new TestCaseGroup(context, "loop", "Shader Compiler Loop Cases"); 2964 TestCaseGroup* invalidCharLoopGroup = new TestCaseGroup(context, "loop", "Invalid Character Shader Compiler Loop Cases"); 2965 TestCaseGroup* semanticErrorLoopGroup = new TestCaseGroup(context, "loop", "Semantic Error Shader Compiler Loop Cases"); 2966 TestCaseGroup* cacheLoopGroup = new TestCaseGroup(context, "loop", "Shader Compiler Loop Cache Cases"); 2967 validGroup->addChild(validLoopGroup); 2968 invalidCharGroup->addChild(invalidCharLoopGroup); 2969 semanticErrorGroup->addChild(semanticErrorLoopGroup); 2970 cacheGroup->addChild(cacheLoopGroup); 2971 2972 for (int loopType = 0; loopType < (int)LOOP_LAST; loopType++) 2973 { 2974 const char* loopTypeName = loopType == (int)LOOP_TYPE_STATIC ? "static" 2975 : loopType == (int)LOOP_TYPE_UNIFORM ? "uniform" 2976 : loopType == (int)LOOP_TYPE_DYNAMIC ? "dynamic" 2977 : DE_NULL; 2978 2979 DE_ASSERT(loopTypeName != DE_NULL); 2980 2981 TestCaseGroup* validLoopTypeGroup = new TestCaseGroup(context, loopTypeName, ""); 2982 TestCaseGroup* invalidCharLoopTypeGroup = new TestCaseGroup(context, loopTypeName, ""); 2983 TestCaseGroup* semanticErrorLoopTypeGroup = new TestCaseGroup(context, loopTypeName, ""); 2984 TestCaseGroup* cacheLoopTypeGroup = new TestCaseGroup(context, loopTypeName, ""); 2985 validLoopGroup->addChild(validLoopTypeGroup); 2986 invalidCharLoopGroup->addChild(invalidCharLoopTypeGroup); 2987 semanticErrorLoopGroup->addChild(semanticErrorLoopTypeGroup); 2988 cacheLoopGroup->addChild(cacheLoopTypeGroup); 2989 2990 for (int isFrag = 0; isFrag <= 1; isFrag++) 2991 { 2992 bool isVertex = isFrag == 0; 2993 const char* vertFragStr = isVertex ? "vertex" : "fragment"; 2994 2995 // \note Non-static loop cases with different iteration counts have identical shaders, so only make one of each. 2996 int loopIterCountMaxNdx = loopType != (int)LOOP_TYPE_STATIC ? 1 : DE_LENGTH_OF_ARRAY(loopIterCounts); 2997 2998 for (int nestingDepth = 1; nestingDepth <= maxLoopNestingDepth; nestingDepth++) 2999 { 3000 for (int loopIterCountNdx = 0; loopIterCountNdx < loopIterCountMaxNdx; loopIterCountNdx++) 3001 { 3002 int numIterations = loopIterCounts[loopIterCountNdx]; 3003 3004 if (deFloatPow((float)numIterations, (float)nestingDepth) > (float)maxTotalLoopIterations) 3005 continue; // Don't generate too heavy tasks. 3006 3007 string validCaseName = de::toString(numIterations) + "_iterations_" + de::toString(nestingDepth) + "_levels_" + vertFragStr; 3008 3009 // Valid shader case, no-cache and cache versions. 3010 3011 validLoopTypeGroup->addChild(new ShaderCompilerLoopCase(context, validCaseName.c_str(), "", caseID++, true /* avoid cache */, false, isVertex, (LoopType)loopType, numIterations, nestingDepth)); 3012 cacheLoopTypeGroup->addChild(new ShaderCompilerLoopCase(context, validCaseName.c_str(), "", caseID++, false /* allow cache */, false, isVertex, (LoopType)loopType, numIterations, nestingDepth)); 3013 3014 // Invalid shader cases. 3015 3016 for (int invalidityType = 0; invalidityType < (int)InvalidShaderCompilerCase::INVALIDITY_LAST; invalidityType++) 3017 { 3018 TestCaseGroup* curInvalidGroup = invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_INVALID_CHAR ? invalidCharLoopTypeGroup 3019 : invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_SEMANTIC_ERROR ? semanticErrorLoopTypeGroup 3020 : DE_NULL; 3021 3022 DE_ASSERT(curInvalidGroup != DE_NULL); 3023 3024 string invalidCaseName = de::toString(nestingDepth) + "_levels_" + vertFragStr; 3025 3026 if (loopType == (int)LOOP_TYPE_STATIC) 3027 invalidCaseName = de::toString(numIterations) + "_iterations_" + invalidCaseName; // \note For invalid, non-static loop cases the iteration count means nothing (since no uniforms or attributes are set). 3028 3029 curInvalidGroup->addChild(new InvalidShaderCompilerLoopCase(context, invalidCaseName.c_str(), "", caseID++, (InvalidShaderCompilerCase::InvalidityType)invalidityType, isVertex, (LoopType)loopType, numIterations, nestingDepth)); 3030 } 3031 } 3032 } 3033 } 3034 } 3035 } 3036 3037 // Multiplication shader compilation cases. 3038 3039 { 3040 static const int multiplicationCounts[] = { 10, 100, 1000 }; 3041 3042 TestCaseGroup* validMulGroup = new TestCaseGroup(context, "multiplication", "Shader Compiler Multiplication Cases"); 3043 TestCaseGroup* invalidCharMulGroup = new TestCaseGroup(context, "multiplication", "Invalid Character Shader Compiler Multiplication Cases"); 3044 TestCaseGroup* semanticErrorMulGroup = new TestCaseGroup(context, "multiplication", "Semantic Error Shader Compiler Multiplication Cases"); 3045 TestCaseGroup* cacheMulGroup = new TestCaseGroup(context, "multiplication", "Shader Compiler Multiplication Cache Cases"); 3046 validGroup->addChild(validMulGroup); 3047 invalidCharGroup->addChild(invalidCharMulGroup); 3048 semanticErrorGroup->addChild(semanticErrorMulGroup); 3049 cacheGroup->addChild(cacheMulGroup); 3050 3051 for (int isFrag = 0; isFrag <= 1; isFrag++) 3052 { 3053 bool isVertex = isFrag == 0; 3054 const char* vertFragStr = isVertex ? "vertex" : "fragment"; 3055 3056 for (int operCountNdx = 0; operCountNdx < DE_LENGTH_OF_ARRAY(multiplicationCounts); operCountNdx++) 3057 { 3058 int numOpers = multiplicationCounts[operCountNdx]; 3059 3060 string caseName = de::toString(numOpers) + "_operations_" + vertFragStr; 3061 3062 // Valid shader case, no-cache and cache versions. 3063 3064 validMulGroup->addChild(new ShaderCompilerOperCase(context, caseName.c_str(), "", caseID++, true /* avoid cache */, false, isVertex, "*", numOpers)); 3065 cacheMulGroup->addChild(new ShaderCompilerOperCase(context, caseName.c_str(), "", caseID++, false /* allow cache */, false, isVertex, "*", numOpers)); 3066 3067 // Invalid shader cases. 3068 3069 for (int invalidityType = 0; invalidityType < (int)InvalidShaderCompilerCase::INVALIDITY_LAST; invalidityType++) 3070 { 3071 TestCaseGroup* curInvalidGroup = invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_INVALID_CHAR ? invalidCharMulGroup 3072 : invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_SEMANTIC_ERROR ? semanticErrorMulGroup 3073 : DE_NULL; 3074 3075 DE_ASSERT(curInvalidGroup != DE_NULL); 3076 3077 curInvalidGroup->addChild(new InvalidShaderCompilerOperCase(context, caseName.c_str(), "", caseID++, (InvalidShaderCompilerCase::InvalidityType)invalidityType, isVertex, "*", numOpers)); 3078 } 3079 } 3080 } 3081 } 3082 3083 // Mandelbrot shader compilation cases. 3084 3085 { 3086 static const int mandelbrotIterationCounts[] = { 32, 64, 128 }; 3087 3088 TestCaseGroup* validMandelbrotGroup = new TestCaseGroup(context, "mandelbrot", "Shader Compiler Mandelbrot Fractal Cases"); 3089 TestCaseGroup* invalidCharMandelbrotGroup = new TestCaseGroup(context, "mandelbrot", "Invalid Character Shader Compiler Mandelbrot Fractal Cases"); 3090 TestCaseGroup* semanticErrorMandelbrotGroup = new TestCaseGroup(context, "mandelbrot", "Semantic Error Shader Compiler Mandelbrot Fractal Cases"); 3091 TestCaseGroup* cacheMandelbrotGroup = new TestCaseGroup(context, "mandelbrot", "Shader Compiler Mandelbrot Fractal Cache Cases"); 3092 validGroup->addChild(validMandelbrotGroup); 3093 invalidCharGroup->addChild(invalidCharMandelbrotGroup); 3094 semanticErrorGroup->addChild(semanticErrorMandelbrotGroup); 3095 cacheGroup->addChild(cacheMandelbrotGroup); 3096 3097 for (int iterCountNdx = 0; iterCountNdx < DE_LENGTH_OF_ARRAY(mandelbrotIterationCounts); iterCountNdx++) 3098 { 3099 int numFractalIterations = mandelbrotIterationCounts[iterCountNdx]; 3100 string caseName = de::toString(numFractalIterations) + "_iterations"; 3101 3102 // Valid shader case, no-cache and cache versions. 3103 3104 validMandelbrotGroup->addChild(new ShaderCompilerMandelbrotCase(context, caseName.c_str(), "", caseID++, true /* avoid cache */, false, numFractalIterations)); 3105 cacheMandelbrotGroup->addChild(new ShaderCompilerMandelbrotCase(context, caseName.c_str(), "", caseID++, false /* allow cache */, false, numFractalIterations)); 3106 3107 // Invalid shader cases. 3108 3109 for (int invalidityType = 0; invalidityType < (int)InvalidShaderCompilerCase::INVALIDITY_LAST; invalidityType++) 3110 { 3111 TestCaseGroup* curInvalidGroup = invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_INVALID_CHAR ? invalidCharMandelbrotGroup 3112 : invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_SEMANTIC_ERROR ? semanticErrorMandelbrotGroup 3113 : DE_NULL; 3114 3115 DE_ASSERT(curInvalidGroup != DE_NULL); 3116 3117 curInvalidGroup->addChild(new InvalidShaderCompilerMandelbrotCase(context, caseName.c_str(), "", caseID++, (InvalidShaderCompilerCase::InvalidityType)invalidityType, numFractalIterations)); 3118 } 3119 } 3120 } 3121 3122 // Cases testing cache behaviour when whitespace and comments are added. 3123 3124 { 3125 TestCaseGroup* whitespaceCommentCacheGroup = new TestCaseGroup(context, "cache_whitespace_comment", "Cases testing the effect of whitespace and comments on caching"); 3126 parentGroup.addChild(whitespaceCommentCacheGroup); 3127 3128 // \note Add just a small subset of the cases that were added above for the main performance tests. 3129 3130 // Cases with both vertex and fragment variants. 3131 for (int isFrag = 0; isFrag <= 1; isFrag++) 3132 { 3133 bool isVertex = isFrag == 0; 3134 string vtxFragSuffix = isVertex ? "_vertex" : "_fragment"; 3135 string dirLightName = "directional_2_lights" + vtxFragSuffix; 3136 string loopName = "static_loop_100_iterations" + vtxFragSuffix; 3137 string multCase = "multiplication_100_operations" + vtxFragSuffix; 3138 3139 whitespaceCommentCacheGroup->addChild(new ShaderCompilerLightCase(context, dirLightName.c_str(), "", caseID++, false, true, isVertex, 2, LIGHT_DIRECTIONAL)); 3140 whitespaceCommentCacheGroup->addChild(new ShaderCompilerLoopCase(context, loopName.c_str(), "", caseID++, false, true, isVertex, LOOP_TYPE_STATIC, 100, 1)); 3141 whitespaceCommentCacheGroup->addChild(new ShaderCompilerOperCase(context, multCase.c_str(), "", caseID++, false, true, isVertex, "*", 100)); 3142 } 3143 3144 // Cases that don't have vertex and fragment variants. 3145 whitespaceCommentCacheGroup->addChild(new ShaderCompilerTextureCase(context, "texture_4_lookups", "", caseID++, false, true, 4, CONDITIONAL_USAGE_NONE, CONDITIONAL_TYPE_STATIC)); 3146 whitespaceCommentCacheGroup->addChild(new ShaderCompilerMandelbrotCase(context, "mandelbrot_32_operations", "", caseID++, false, true, 32)); 3147 } 3148 } 3149 3150 } // Performance 3151 } // gles3 3152 } // deqp 3153