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