1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Shader compilation performance tests.
22 *//*--------------------------------------------------------------------*/
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"
42 #include "glwEnums.hpp"
43 #include "glwFunctions.hpp"
57 using namespace glw; // GL types
68 static const bool WARMUP_CPU_AT_BEGINNING_OF_CASE = false;
69 static const bool WARMUP_CPU_BEFORE_EACH_MEASUREMENT = true;
71 static const int MAX_VIEWPORT_WIDTH = 64;
72 static const int MAX_VIEWPORT_HEIGHT = 64;
74 static const int DEFAULT_MINIMUM_MEASUREMENT_COUNT = 15;
75 static const float RELATIVE_MEDIAN_ABSOLUTE_DEVIATION_THRESHOLD = 0.05f;
77 // Texture size for the light shader and texture lookup shader cases.
78 static const int TEXTURE_WIDTH = 64;
79 static const int TEXTURE_HEIGHT = 64;
82 inline string toStringWithPadding (T value, int minLength)
85 s << std::setfill('0') << std::setw(minLength) << value;
89 // Add some whitespace and comments to str. They should depend on uniqueNumber.
90 static string strWithWhiteSpaceAndComments (const string& str, deUint32 uniqueNumber)
94 // Find the first newline.
95 int firstLineEndNdx = 0;
96 while (firstLineEndNdx < (int)str.size() && str[firstLineEndNdx] != '\n')
98 res += str[firstLineEndNdx];
102 DE_ASSERT(firstLineEndNdx < (int)str.size());
104 // Add the whitespaces and comments just after the first line.
106 de::Random rnd (uniqueNumber);
107 int numWS = rnd.getInt(10, 20);
109 for (int i = 0; i < numWS; i++)
110 res += " \t\n"[rnd.getInt(0, 2)];
112 res += "/* unique comment " + de::toString(uniqueNumber) + " */\n";
113 res += "// unique comment " + de::toString(uniqueNumber) + "\n";
115 for (int i = 0; i < numWS; i++)
116 res += " \t\n"[rnd.getInt(0, 2)];
118 // Add the rest of the string.
119 res.append(&str.c_str()[firstLineEndNdx + 1]);
124 //! Helper for computing relative magnitudes while avoiding division by zero.
125 static float hackySafeRelativeResult (float x, float y)
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;
137 template <typename T>
138 static float vectorFloatAverage (const vector<T>& v)
140 DE_ASSERT(!v.empty());
142 for (int i = 0; i < (int)v.size(); i++)
143 result += (float)v[i];
144 return result / (float)v.size();
147 template <typename T>
148 static float vectorFloatMedian (const vector<T>& v)
150 DE_ASSERT(!v.empty());
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];
158 template <typename T>
159 static float vectorFloatMinimum (const vector<T>& v)
161 DE_ASSERT(!v.empty());
162 return (float)*std::min_element(v.begin(), v.end());
165 template <typename T>
166 static float vectorFloatMaximum (const vector<T>& v)
168 DE_ASSERT(!v.empty());
169 return (float)*std::max_element(v.begin(), v.end());
172 template <typename T>
173 static float vectorFloatStandardDeviation (const vector<T>& v)
175 float average = vectorFloatAverage(v);
177 for (int i = 0; i < (int)v.size(); i++)
179 float d = (float)v[i] - average;
182 return deFloatSqrt(result/(float)v.size());
185 template <typename T>
186 static float vectorFloatRelativeStandardDeviation (const vector<T>& v)
188 return hackySafeRelativeResult(vectorFloatStandardDeviation(v), vectorFloatAverage(v));
191 template <typename T>
192 static float vectorFloatMedianAbsoluteDeviation (const vector<T>& v)
194 float median = vectorFloatMedian(v);
195 vector<float> absoluteDeviations (v.size());
197 for (int i = 0; i < (int)v.size(); i++)
198 absoluteDeviations[i] = deFloatAbs((float)v[i] - median);
200 return vectorFloatMedian(absoluteDeviations);
203 template <typename T>
204 static float vectorFloatRelativeMedianAbsoluteDeviation (const vector<T>& v)
206 return hackySafeRelativeResult(vectorFloatMedianAbsoluteDeviation(v), vectorFloatMedian(v));
209 template <typename T>
210 static float vectorFloatMaximumMinusMinimum (const vector<T>& v)
212 return vectorFloatMaximum(v) - vectorFloatMinimum(v);
215 template <typename T>
216 static float vectorFloatRelativeMaximumMinusMinimum (const vector<T>& v)
218 return hackySafeRelativeResult(vectorFloatMaximumMinusMinimum(v), vectorFloatMaximum(v));
221 template <typename T>
222 static vector<T> vectorLowestPercentage (const vector<T>& v, float factor)
224 DE_ASSERT(0.0f < factor && factor <= 1.0f);
226 int targetSize = (int)(deFloatCeil(factor*(float)v.size()));
228 std::sort(temp.begin(), temp.end());
230 while ((int)temp.size() > targetSize)
236 template <typename T>
237 static float vectorFloatFirstQuartile (const vector<T>& v)
239 return vectorFloatMedian(vectorLowestPercentage(v, 0.5f));
242 // Helper function for combining 4 tcu::Vec4's into one tcu::Vector<float, 16>.
243 static tcu::Vector<float, 16> combineVec4ToVec16 (const Vec4& a0, const Vec4& a1, const Vec4& a2, const Vec4& a3)
245 tcu::Vector<float, 16> result;
247 for (int vecNdx = 0; vecNdx < 4; vecNdx++)
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];
257 // Helper function for extending an n-sized (n <= 16) vector to a 16-sized vector (padded with zeros).
259 static tcu::Vector<float, 16> vecTo16 (const tcu::Vector<float, Size>& vec)
261 DE_STATIC_ASSERT(Size <= 16);
263 tcu::Vector<float, 16> res(0.0f);
265 for (int i = 0; i < Size; i++)
271 // Helper function for extending an n-sized (n <= 16) array to a 16-sized vector (padded with zeros).
273 static tcu::Vector<float, 16> arrTo16 (const tcu::Array<float, Size>& arr)
275 DE_STATIC_ASSERT(Size <= 16);
277 tcu::Vector<float, 16> res(0.0f);
279 for(int i = 0; i < Size; i++)
285 static string getShaderInfoLog (const glw::Functions& gl, deUint32 shader)
289 vector<char> infoLogBuf;
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];
299 static string getProgramInfoLog (const glw::Functions& gl, deUint32 program)
303 vector<char> infoLogBuf;
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];
315 LIGHT_DIRECTIONAL = 0,
323 LOOP_TYPE_STATIC = 0,
330 // For texture lookup cases: which texture lookups are inside a conditional statement.
331 enum ConditionalUsage
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.
337 CONDITIONAL_USAGE_LAST
342 CONDITIONAL_TYPE_STATIC = 0,
343 CONDITIONAL_TYPE_UNIFORM,
344 CONDITIONAL_TYPE_DYNAMIC,
346 CONDITIONAL_TYPE_LAST
349 // For the invalid shader compilation tests; what kind of invalidity a shader shall contain.
352 SHADER_VALIDITY_VALID = 0,
353 SHADER_VALIDITY_INVALID_CHAR,
354 SHADER_VALIDITY_SEMANTIC_ERROR,
359 class ShaderCompilerCase : public TestCase
365 tcu::Vector<float, 16> value;
367 AttribSpec (const string& n, const tcu::Vector<float, 16>& v) : name(n), value(v) {}
389 tcu::Vector<float, 16> value;
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) {}
395 ShaderCompilerCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments);
396 ~ShaderCompilerCase (void);
400 IterateResult iterate (void);
403 struct ProgramContext
405 string vertShaderSource;
406 string fragShaderSource;
407 vector<AttribSpec> vertexAttributes;
408 vector<UniformSpec> uniforms;
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.
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;
425 deInt64 secondInputSetTime;
426 deInt64 secondDrawTime;
428 deInt64 firstPhase (void) const { return sourceSetTime + vertexCompileTime + fragmentCompileTime + programLinkTime + firstInputSetTime + firstDrawTime; }
429 deInt64 secondPhase (void) const { return secondInputSetTime + secondDrawTime; }
431 deInt64 totalTimeWithoutDraw (void) const { return firstPhase() - de::min(secondPhase(), firstInputSetTime + firstDrawTime); }
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_)
453 struct ShadersAndProgram
469 bool vertCompileSuccess;
470 bool fragCompileSuccess;
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.
484 Logs getLogs (const ShadersAndProgram&) const;
485 void logProgramData (const BuildInfo&, const ProgramContext&) const;
486 bool goodEnoughMeasurements (const vector<Measurement>& measurements) const;
489 int m_viewportHeight;
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.
495 int m_minimumMeasurementCount;
496 int m_maximumMeasurementCount;
499 class ShaderCompilerLightCase : public ShaderCompilerCase
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);
509 ProgramContext generateShaderData (int measurementNdx) const;
514 LightType m_lightType;
515 glu::Texture2D* m_texture;
518 class ShaderCompilerTextureCase : public ShaderCompilerCase
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);
528 ProgramContext generateShaderData (int measurementNdx) const;
532 vector<glu::Texture2D*> m_textures;
533 ConditionalUsage m_conditionalUsage;
534 ConditionalType m_conditionalType;
537 class ShaderCompilerLoopCase : public ShaderCompilerCase
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);
544 ProgramContext generateShaderData (int measurementNdx) const;
547 int m_numLoopIterations;
553 class ShaderCompilerOperCase : public ShaderCompilerCase
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);
560 ProgramContext generateShaderData (int measurementNdx) const;
568 class ShaderCompilerMandelbrotCase : public ShaderCompilerCase
571 ShaderCompilerMandelbrotCase (Context& context, const char* name, const char* description, int caseID, bool avoidCache, bool addWhitespaceAndComments, int numFractalIterations);
572 ~ShaderCompilerMandelbrotCase (void);
575 ProgramContext generateShaderData (int measurementNdx) const;
578 int m_numFractalIterations;
581 class InvalidShaderCompilerCase : public TestCase
584 // \note Similar to the ShaderValidity enum, but doesn't have a VALID type.
587 INVALIDITY_INVALID_CHAR = 0,
588 INVALIDITY_SEMANTIC_ERROR,
593 InvalidShaderCompilerCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType);
594 ~InvalidShaderCompilerCase (void);
596 IterateResult iterate (void);
599 struct ProgramContext
601 string vertShaderSource;
602 string fragShaderSource;
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.
608 InvalidityType m_invalidityType;
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;
618 deInt64 totalTime (void) const { return sourceSetTime + vertexCompileTime + fragmentCompileTime; }
620 Measurement (deInt64 sourceSetTime_,
621 deInt64 vertexCompileTime_,
622 deInt64 fragmentCompileTime_)
623 : sourceSetTime (sourceSetTime_)
624 , vertexCompileTime (vertexCompileTime_)
625 , fragmentCompileTime (fragmentCompileTime_)
644 bool vertCompileSuccess;
645 bool fragCompileSuccess;
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;
655 Logs getLogs (const Shaders&) const;
656 void logProgramData (const BuildInfo&, const ProgramContext&) const;
657 bool goodEnoughMeasurements (const vector<Measurement>& measurements) const;
659 deUint32 m_startHash; // A hash from case id and time, at the time of construction.
661 int m_minimumMeasurementCount;
662 int m_maximumMeasurementCount;
665 class InvalidShaderCompilerLightCase : public InvalidShaderCompilerCase
668 InvalidShaderCompilerLightCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, bool isVertexCase, int numLights, LightType lightType);
669 ~InvalidShaderCompilerLightCase (void);
672 ProgramContext generateShaderSources (int measurementNdx) const;
677 LightType m_lightType;
680 class InvalidShaderCompilerTextureCase : public InvalidShaderCompilerCase
683 InvalidShaderCompilerTextureCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, int numLookups, ConditionalUsage conditionalUsage, ConditionalType conditionalType);
684 ~InvalidShaderCompilerTextureCase (void);
687 ProgramContext generateShaderSources (int measurementNdx) const;
691 ConditionalUsage m_conditionalUsage;
692 ConditionalType m_conditionalType;
695 class InvalidShaderCompilerLoopCase : public InvalidShaderCompilerCase
698 InvalidShaderCompilerLoopCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, bool , LoopType type, int numLoopIterations, int nestingDepth);
699 ~InvalidShaderCompilerLoopCase (void);
702 ProgramContext generateShaderSources (int measurementNdx) const;
706 int m_numLoopIterations;
711 class InvalidShaderCompilerOperCase : public InvalidShaderCompilerCase
714 InvalidShaderCompilerOperCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, bool isVertexCase, const char* oper, int numOperations);
715 ~InvalidShaderCompilerOperCase (void);
718 ProgramContext generateShaderSources (int measurementNdx) const;
726 class InvalidShaderCompilerMandelbrotCase : public InvalidShaderCompilerCase
729 InvalidShaderCompilerMandelbrotCase (Context& context, const char* name, const char* description, int caseID, InvalidityType invalidityType, int numFractalIterations);
730 ~InvalidShaderCompilerMandelbrotCase (void);
733 ProgramContext generateShaderSources (int measurementNdx) const;
736 int m_numFractalIterations;
739 static string getNameSpecialization (deUint32 id)
741 return "_" + toStringWithPadding(id, 10);
744 // Substitute StringTemplate parameters for attribute/uniform/varying name and constant expression specialization as well as possible shader compilation error causes.
745 static string specializeShaderSource (const string& shaderSourceTemplate, deUint32 cacheAvoidanceID, ShaderValidity validity)
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.
753 return tcu::StringTemplate(shaderSourceTemplate).specialize(params);
756 // Function for generating the vertex shader of a (directional or point) light case.
757 static string lightVertexTemplate (int numLights, bool isVertexCase, LightType lightType)
759 string 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";
771 for (int lightNdx = 0; lightNdx < numLights; lightNdx++)
773 string ndxStr = de::toString(lightNdx);
776 "uniform mediump vec3 u_light" + ndxStr + "_color${NAME_SPEC};\n"
777 "uniform mediump vec3 u_light" + ndxStr + "_direction${NAME_SPEC};\n";
779 if (lightType == LIGHT_POINT)
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";
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";
797 resultTemplate += "varying mediump vec3 v_eyeNormal${NAME_SPEC};\n";
799 if (lightType == LIGHT_POINT)
801 "varying mediump vec3 v_directionToLight${NAME_SPEC}[" + de::toString(numLights) + "];\n"
802 "varying mediump float v_distanceToLight${NAME_SPEC}[" + de::toString(numLights) + "];\n";
806 "mediump vec3 direction (mediump vec4 from, mediump vec4 to)\n"
808 " return vec3(to.xyz * from.w - from.xyz * to.w);\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"
820 " mediump float normalDotDirection = max(dot(normal, directionToLight), 0.0);\n"
821 " mediump vec3 color = normalDotDirection * diffuseColor * lightColor;\n"
823 " if (normalDotDirection != 0.0)\n"
824 " color += pow(max(dot(normal, halfVector), 0.0), shininess) * specularColor * lightColor;\n"
830 if (lightType == LIGHT_POINT)
832 "mediump float computeDistanceAttenuation (mediump float distToLight, mediump float constAtt, mediump float linearAtt, mediump float quadraticAtt)\n"
834 " return 1.0 / (constAtt + linearAtt * distToLight + quadraticAtt * distToLight * distToLight);\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"
847 " highp vec4 eyePosition = u_modelViewMatrix${NAME_SPEC} * position;\n"
848 " mediump vec3 eyeNormal = normalize(u_normalMatrix${NAME_SPEC} * normal);\n";
851 resultTemplate += "\tv_eyeNormal${NAME_SPEC} = eyeNormal;\n";
853 resultTemplate += "\n";
855 for (int lightNdx = 0; lightNdx < numLights; lightNdx++)
857 string ndxStr = de::toString(lightNdx);
860 " /* Light " + ndxStr + " */\n";
862 if (lightType == LIGHT_POINT)
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";
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";
876 " v_directionToLight${NAME_SPEC}[" + ndxStr + "] = directionToLight" + ndxStr + ";\n"
877 " v_distanceToLight${NAME_SPEC}[" + ndxStr + "] = distanceToLight" + ndxStr + ";\n";
879 else if (lightType == LIGHT_DIRECTIONAL)
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";
890 resultTemplate += "\n";
894 " v_color${NAME_SPEC} = color;\n"
899 return resultTemplate;
902 // Function for generating the fragment shader of a (directional or point) light case.
903 static string lightFragmentTemplate (int numLights, bool isVertexCase, LightType lightType)
905 string 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";
916 for (int lightNdx = 0; lightNdx < numLights; lightNdx++)
918 string ndxStr = de::toString(lightNdx);
921 "uniform mediump vec3 u_light" + ndxStr + "_color${NAME_SPEC};\n"
922 "uniform mediump vec3 u_light" + ndxStr + "_direction${NAME_SPEC};\n";
924 if (lightType == LIGHT_POINT)
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";
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";
941 "varying mediump vec3 v_eyeNormal${NAME_SPEC};\n";
943 if (lightType == LIGHT_POINT)
945 "varying mediump vec3 v_directionToLight${NAME_SPEC}[" + de::toString(numLights) + "];\n"
946 "varying mediump float v_distanceToLight${NAME_SPEC}[" + de::toString(numLights) + "];\n";
949 "mediump vec3 direction (mediump vec4 from, mediump vec4 to)\n"
951 " return vec3(to.xyz * from.w - from.xyz * to.w);\n"
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"
965 " mediump float normalDotDirection = max(dot(normal, directionToLight), 0.0);\n"
966 " mediump vec3 color = normalDotDirection * diffuseColor * lightColor;\n"
968 " if (normalDotDirection != 0.0)\n"
969 " color += pow(max(dot(normal, halfVector), 0.0), shininess) * specularColor * lightColor;\n"
975 if (lightType == LIGHT_POINT)
977 "mediump float computeDistanceAttenuation (mediump float distToLight, mediump float constAtt, mediump float linearAtt, mediump float quadraticAtt)\n"
979 " return 1.0 / (constAtt + linearAtt * distToLight + quadraticAtt * distToLight * distToLight);\n"
987 " mediump vec2 texCoord0 = v_texCoord0${NAME_SPEC}.xy;\n"
988 " mediump vec4 color = v_color${NAME_SPEC};\n";
993 " mediump vec3 eyeNormal = normalize(v_eyeNormal${NAME_SPEC});\n"
996 for (int lightNdx = 0; lightNdx < numLights; lightNdx++)
998 string ndxStr = de::toString(lightNdx);
1001 " /* Light " + ndxStr + " */\n";
1003 if (lightType == LIGHT_POINT)
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"
1012 else if (lightType == LIGHT_DIRECTIONAL)
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"
1019 DE_ASSERT(DE_FALSE);
1024 " color *= texture2D(u_sampler0${NAME_SPEC}, texCoord0);\n"
1025 " gl_FragColor = color + ${FLOAT01};\n"
1030 return resultTemplate;
1033 // Function for generating the shader attributes of a (directional or point) light case.
1034 static vector<ShaderCompilerCase::AttribSpec> lightShaderAttributes (const string& nameSpecialization)
1036 vector<ShaderCompilerCase::AttribSpec> result;
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))));
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))));
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))));
1059 // Function for generating the shader uniforms of a (directional or point) light case.
1060 static vector<ShaderCompilerCase::UniformSpec> lightShaderUniforms (const string& nameSpecialization, int numLights, LightType lightType)
1062 vector<ShaderCompilerCase::UniformSpec> result;
1064 result.push_back(ShaderCompilerCase::UniformSpec("u_material_ambientColor" + nameSpecialization,
1065 ShaderCompilerCase::UniformSpec::TYPE_VEC3,
1066 vecTo16(Vec3(0.5f, 0.7f, 0.9f))));
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))));
1072 result.push_back(ShaderCompilerCase::UniformSpec("u_material_emissiveColor" + nameSpecialization,
1073 ShaderCompilerCase::UniformSpec::TYPE_VEC3,
1074 vecTo16(Vec3(0.7f, 0.2f, 0.2f))));
1076 result.push_back(ShaderCompilerCase::UniformSpec("u_material_specularColor" + nameSpecialization,
1077 ShaderCompilerCase::UniformSpec::TYPE_VEC3,
1078 vecTo16(Vec3(0.2f, 0.6f, 1.0f))));
1080 result.push_back(ShaderCompilerCase::UniformSpec("u_material_shininess" + nameSpecialization,
1081 ShaderCompilerCase::UniformSpec::TYPE_FLOAT,
1084 for (int lightNdx = 0; lightNdx < numLights; lightNdx++)
1086 string ndxStr = de::toString(lightNdx);
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))));
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))));
1096 if (lightType == LIGHT_POINT)
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))));
1102 result.push_back(ShaderCompilerCase::UniformSpec("u_light" + ndxStr + "_constantAttenuation" + nameSpecialization,
1103 ShaderCompilerCase::UniformSpec::TYPE_FLOAT,
1106 result.push_back(ShaderCompilerCase::UniformSpec("u_light" + ndxStr + "_linearAttenuation" + nameSpecialization,
1107 ShaderCompilerCase::UniformSpec::TYPE_FLOAT,
1110 result.push_back(ShaderCompilerCase::UniformSpec("u_light" + ndxStr + "_quadraticAttenuation" + nameSpecialization,
1111 ShaderCompilerCase::UniformSpec::TYPE_FLOAT,
1116 result.push_back(ShaderCompilerCase::UniformSpec("u_mvpMatrix" + nameSpecialization,
1117 ShaderCompilerCase::UniformSpec::TYPE_MAT4,
1118 arrTo16(Mat4(1.0f).getColumnMajorData())));
1120 result.push_back(ShaderCompilerCase::UniformSpec("u_modelViewMatrix" + nameSpecialization,
1121 ShaderCompilerCase::UniformSpec::TYPE_MAT4,
1122 arrTo16(Mat4(1.0f).getColumnMajorData())));
1124 result.push_back(ShaderCompilerCase::UniformSpec("u_normalMatrix" + nameSpecialization,
1125 ShaderCompilerCase::UniformSpec::TYPE_MAT3,
1126 arrTo16(Mat3(1.0f).getColumnMajorData())));
1128 result.push_back(ShaderCompilerCase::UniformSpec("u_texCoordMatrix0" + nameSpecialization,
1129 ShaderCompilerCase::UniformSpec::TYPE_MAT4,
1130 arrTo16(Mat4(1.0f).getColumnMajorData())));
1132 result.push_back(ShaderCompilerCase::UniformSpec("u_sampler0" + nameSpecialization,
1133 ShaderCompilerCase::UniformSpec::TYPE_TEXTURE_UNIT,
1139 // Function for generating a vertex shader with a for loop.
1140 static string loopVertexTemplate (LoopType type, bool isVertexCase, int numLoopIterations, int nestingDepth)
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})"
1148 DE_ASSERT(!loopBound.empty());
1151 "attribute highp vec4 a_position${NAME_SPEC};\n";
1153 if (type == LOOP_TYPE_DYNAMIC)
1155 "attribute mediump float a_loopBound${NAME_SPEC};\n";
1158 "attribute mediump vec4 a_value${NAME_SPEC};\n"
1159 "varying mediump vec4 v_value${NAME_SPEC};\n";
1163 if (type == LOOP_TYPE_UNIFORM)
1164 resultTemplate += "uniform mediump float u_loopBound${NAME_SPEC};\n";
1170 " gl_Position = a_position${NAME_SPEC} * (0.95 + 0.05*${FLOAT01});\n"
1171 " mediump vec4 value = a_value${NAME_SPEC};\n";
1173 for (int i = 0; i < nestingDepth; i++)
1175 string iterName = "i" + de::toString(i);
1176 resultTemplate += string(i + 1, '\t') + "for (int " + iterName + " = 0; " + iterName + " < " + loopBound + "; " + iterName + "++)\n";
1179 resultTemplate += string(nestingDepth + 1, '\t') + "value *= a_value${NAME_SPEC};\n";
1182 " v_value${NAME_SPEC} = value;\n";
1186 if (type == LOOP_TYPE_DYNAMIC)
1188 "varying mediump float v_loopBound${NAME_SPEC};\n";
1194 " gl_Position = a_position${NAME_SPEC} * (0.95 + 0.05*${FLOAT01});\n"
1195 " v_value${NAME_SPEC} = a_value${NAME_SPEC};\n";
1197 if (type == LOOP_TYPE_DYNAMIC)
1199 " v_loopBound${NAME_SPEC} = a_loopBound${NAME_SPEC};\n";
1207 return resultTemplate;
1210 // Function for generating a fragment shader with a for loop.
1211 static string loopFragmentTemplate (LoopType type, bool isVertexCase, int numLoopIterations, int nestingDepth)
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})"
1219 DE_ASSERT(!loopBound.empty());
1222 "varying mediump vec4 v_value${NAME_SPEC};\n";
1226 if (type == LOOP_TYPE_DYNAMIC)
1228 "varying mediump float v_loopBound${NAME_SPEC};\n";
1229 else if (type == LOOP_TYPE_UNIFORM)
1231 "uniform mediump float u_loopBound${NAME_SPEC};\n";
1237 " mediump vec4 value = v_value${NAME_SPEC};\n";
1239 for (int i = 0; i < nestingDepth; i++)
1241 string iterName = "i" + de::toString(i);
1242 resultTemplate += string(i + 1, '\t') + "for (int " + iterName + " = 0; " + iterName + " < " + loopBound + "; " + iterName + "++)\n";
1245 resultTemplate += string(nestingDepth + 1, '\t') + "value *= v_value${NAME_SPEC};\n";
1248 " gl_FragColor = value + ${FLOAT01};\n";
1255 " gl_FragColor = v_value${NAME_SPEC} + ${FLOAT01};\n";
1262 return resultTemplate;
1265 // Function for generating the shader attributes for a loop case.
1266 static vector<ShaderCompilerCase::AttribSpec> loopShaderAttributes (const string& nameSpecialization, LoopType type, int numLoopIterations)
1268 vector<ShaderCompilerCase::AttribSpec> result;
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))));
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))));
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))));
1292 static vector<ShaderCompilerCase::UniformSpec> loopShaderUniforms (const string& nameSpecialization, LoopType type, int numLoopIterations)
1294 vector<ShaderCompilerCase::UniformSpec> result;
1296 if (type == LOOP_TYPE_UNIFORM)
1297 result.push_back(ShaderCompilerCase::UniformSpec("u_loopBound" + nameSpecialization,
1298 ShaderCompilerCase::UniformSpec::TYPE_FLOAT,
1299 (float)numLoopIterations));
1304 // Function for generating the shader attributes for a case with only one attribute value in addition to the position attribute.
1305 static vector<ShaderCompilerCase::AttribSpec> singleValueShaderAttributes (const string& nameSpecialization)
1307 vector<ShaderCompilerCase::AttribSpec> result;
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))));
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))));
1324 // Function for generating a vertex shader with a binary operation chain.
1325 static string binaryOpVertexTemplate (int numOperations, const char* op)
1327 string 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"
1336 " gl_Position = a_position${NAME_SPEC} * (0.95 + 0.05*${FLOAT01});\n"
1337 " mediump vec4 value = ";
1339 for (int i = 0; i < numOperations; i++)
1340 resultTemplate += string(i > 0 ? op : "") + "a_value${NAME_SPEC}";
1344 " v_value${NAME_SPEC} = value;\n"
1349 return resultTemplate;
1352 // Function for generating a fragment shader with a binary operation chain.
1353 static string binaryOpFragmentTemplate (int numOperations, const char* op)
1355 string resultTemplate;
1358 "varying mediump vec4 v_value${NAME_SPEC};\n"
1362 " mediump vec4 value = ";
1364 for (int i = 0; i < numOperations; i++)
1365 resultTemplate += string(i > 0 ? op : "") + "v_value${NAME_SPEC}";
1369 " gl_FragColor = value + ${FLOAT01};\n"
1374 return resultTemplate;
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.
1378 static string singleVaryingVertexTemplate (void)
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"
1387 " gl_Position = a_position${NAME_SPEC} * (0.95 + 0.05*${FLOAT01});\n"
1388 " v_value${NAME_SPEC} = a_value${NAME_SPEC};\n"
1393 return resultTemplate;
1396 // Function for generating a fragment shader that takes a single varying and uses it as the color.
1397 static string singleVaryingFragmentTemplate (void)
1399 const char* resultTemplate =
1400 "varying mediump vec4 v_value${NAME_SPEC};\n"
1404 " gl_FragColor = v_value${NAME_SPEC} + ${FLOAT01};\n"
1409 return resultTemplate;
1412 // Function for generating the vertex shader of a texture lookup case.
1413 static string textureLookupVertexTemplate (ConditionalUsage conditionalUsage, ConditionalType conditionalType)
1415 string resultTemplate;
1416 bool conditionVaryingNeeded = conditionalUsage != CONDITIONAL_USAGE_NONE && conditionalType == CONDITIONAL_TYPE_DYNAMIC;
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";
1423 if (conditionVaryingNeeded)
1425 "attribute mediump float a_condition${NAME_SPEC};\n"
1426 "varying mediump float v_condition${NAME_SPEC};\n";
1432 " gl_Position = a_position${NAME_SPEC} * (0.95 + 0.05*${FLOAT01});\n"
1433 " v_coords${NAME_SPEC} = a_coords${NAME_SPEC};\n";
1435 if (conditionVaryingNeeded)
1437 " v_condition${NAME_SPEC} = a_condition${NAME_SPEC};\n";
1444 return resultTemplate;
1447 // Function for generating the fragment shader of a texture lookup case.
1448 static string textureLookupFragmentTemplate (int numLookups, ConditionalUsage conditionalUsage, ConditionalType conditionalType)
1450 string resultTemplate;
1453 "varying mediump vec2 v_coords${NAME_SPEC};\n";
1455 if (conditionalUsage != CONDITIONAL_USAGE_NONE && conditionalType == CONDITIONAL_TYPE_DYNAMIC)
1457 "varying mediump float v_condition${NAME_SPEC};\n";
1459 for (int i = 0; i < numLookups; i++)
1461 "uniform sampler2D u_sampler" + de::toString(i) + "${NAME_SPEC};\n";
1463 if (conditionalUsage != CONDITIONAL_USAGE_NONE && conditionalType == CONDITIONAL_TYPE_UNIFORM)
1465 "uniform mediump float u_condition${NAME_SPEC};\n";
1471 " mediump vec4 color = vec4(0.0);\n";
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"
1478 DE_ASSERT(conditionalTerm != DE_NULL);
1480 if (conditionalUsage == CONDITIONAL_USAGE_FIRST_HALF)
1481 resultTemplate += string("") +
1482 " if (" + conditionalTerm + ")\n"
1485 for (int i = 0; i < numLookups; i++)
1487 if (conditionalUsage == CONDITIONAL_USAGE_FIRST_HALF)
1489 if (i < (numLookups + 1) / 2)
1490 resultTemplate += "\t";
1492 else if (conditionalUsage == CONDITIONAL_USAGE_EVERY_OTHER)
1495 resultTemplate += string("") +
1496 " if (" + conditionalTerm + ")\n"
1501 " color += texture2D(u_sampler" + de::toString(i) + "${NAME_SPEC}, v_coords${NAME_SPEC});\n";
1503 if (conditionalUsage == CONDITIONAL_USAGE_FIRST_HALF && i == (numLookups - 1) / 2)
1504 resultTemplate += "\t}\n";
1508 " gl_FragColor = color/" + de::toString(numLookups) + ".0 + ${FLOAT01};\n" +
1513 return resultTemplate;
1516 // Function for generating the shader attributes of a texture lookup case.
1517 static vector<ShaderCompilerCase::AttribSpec> textureLookupShaderAttributes (const string& nameSpecialization, ConditionalUsage conditionalUsage, ConditionalType conditionalType)
1519 vector<ShaderCompilerCase::AttribSpec> result;
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))));
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))));
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))));
1540 // Function for generating the shader uniforms of a texture lookup case.
1541 static vector<ShaderCompilerCase::UniformSpec> textureLookupShaderUniforms (const string& nameSpecialization, int numLookups, ConditionalUsage conditionalUsage, ConditionalType conditionalType)
1543 vector<ShaderCompilerCase::UniformSpec> result;
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,
1550 if (conditionalUsage != CONDITIONAL_USAGE_NONE && conditionalType == CONDITIONAL_TYPE_UNIFORM)
1551 result.push_back(ShaderCompilerCase::UniformSpec("u_condition" + nameSpecialization,
1552 ShaderCompilerCase::UniformSpec::TYPE_FLOAT,
1558 static string mandelbrotVertexTemplate (void)
1560 const char* resultTemplate =
1561 "uniform highp mat4 u_mvp${NAME_SPEC};\n"
1563 "attribute highp vec4 a_vertex${NAME_SPEC};\n"
1564 "attribute highp vec4 a_coord${NAME_SPEC};\n"
1566 "varying mediump vec2 v_coord${NAME_SPEC};\n"
1570 " gl_Position = u_mvp${NAME_SPEC} * a_vertex${NAME_SPEC} * (0.95 + 0.05*${FLOAT01});\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"
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"
1583 return resultTemplate;
1586 static string mandelbrotFragmentTemplate (int numFractalIterations)
1588 string resultTemplate =
1589 "varying mediump vec2 v_coord${NAME_SPEC};\n"
1591 "precision mediump float;\n"
1593 "#define NUM_ITERS " + de::toString(numFractalIterations) + "\n"
1595 "void main (void)\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"
1602 " for (iter = 0; iter < NUM_ITERS; iter++)\n"
1604 " tmp = vec2((tmp.x + tmp.y) * (tmp.x - tmp.y), 2.0 * (tmp.x * tmp.y)) + coords;\n"
1606 " if (dot(tmp, tmp) > u_limit)\n"
1610 " vec3 color = vec3(float(iter) * (1.0 / float(NUM_ITERS)));\n"
1612 " gl_FragColor = vec4(color, 1.0) + ${FLOAT01};\n"
1617 return resultTemplate;
1620 static vector<ShaderCompilerCase::AttribSpec> mandelbrotShaderAttributes (const string& nameSpecialization)
1622 vector<ShaderCompilerCase::AttribSpec> result;
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))));
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))));
1639 static vector<ShaderCompilerCase::UniformSpec> mandelbrotShaderUniforms (const string& nameSpecialization)
1641 vector<ShaderCompilerCase::UniformSpec> result;
1643 result.push_back(ShaderCompilerCase::UniformSpec("u_mvp" + nameSpecialization,
1644 ShaderCompilerCase::UniformSpec::TYPE_MAT4,
1645 arrTo16(Mat4(1.0f).getColumnMajorData())));
1650 ShaderCompilerCase::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)))
1658 int cmdLineIterCount = context.getTestContext().getCommandLine().getTestIterationCount();
1659 m_minimumMeasurementCount = cmdLineIterCount > 0 ? cmdLineIterCount : DEFAULT_MINIMUM_MEASUREMENT_COUNT;
1660 m_maximumMeasurementCount = m_minimumMeasurementCount*3;
1663 ShaderCompilerCase::~ShaderCompilerCase (void)
1667 deUint32 ShaderCompilerCase::getSpecializationID (int measurementNdx) const
1670 return m_startHash ^ (deUint32)deInt32Hash((deInt32)measurementNdx);
1675 void ShaderCompilerCase::init (void)
1677 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1678 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
1680 m_viewportWidth = deMin32(MAX_VIEWPORT_WIDTH, renderTarget.getWidth());
1681 m_viewportHeight = deMin32(MAX_VIEWPORT_HEIGHT, renderTarget.getHeight());
1683 gl.viewport(0, 0, m_viewportWidth, m_viewportHeight);
1686 ShaderCompilerCase::ShadersAndProgram ShaderCompilerCase::createShadersAndProgram (void) const
1688 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1689 ShadersAndProgram result;
1691 result.vertShader = gl.createShader(GL_VERTEX_SHADER);
1692 result.fragShader = gl.createShader(GL_FRAGMENT_SHADER);
1693 result.program = gl.createProgram();
1695 gl.attachShader(result.program, result.vertShader);
1696 gl.attachShader(result.program, result.fragShader);
1701 void ShaderCompilerCase::setShaderSources (deUint32 vertShader, deUint32 fragShader, const ProgramContext& progCtx) const
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);
1710 bool ShaderCompilerCase::compileShader (deUint32 shader) const
1712 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1714 gl.compileShader(shader);
1715 gl.getShaderiv(shader, GL_COMPILE_STATUS, &status);
1719 bool ShaderCompilerCase::linkAndUseProgram (deUint32 program) const
1721 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1722 GLint linkStatus = 0;
1724 gl.linkProgram(program);
1725 gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
1727 if (linkStatus != 0)
1728 gl.useProgram(program);
1730 return linkStatus != 0;
1733 void ShaderCompilerCase::setShaderInputs (deUint32 program, const ProgramContext& progCtx) const
1735 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1737 // Setup attributes.
1739 for (int attribNdx = 0; attribNdx < (int)progCtx.vertexAttributes.size(); attribNdx++)
1741 int location = gl.getAttribLocation(program, progCtx.vertexAttributes[attribNdx].name.c_str());
1744 gl.enableVertexAttribArray(location);
1745 gl.vertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, 0, progCtx.vertexAttributes[attribNdx].value.getPtr());
1751 for (int uniformNdx = 0; uniformNdx < (int)progCtx.uniforms.size(); uniformNdx++)
1753 int location = gl.getUniformLocation(program, progCtx.uniforms[uniformNdx].name.c_str());
1756 const float* floatPtr = progCtx.uniforms[uniformNdx].value.getPtr();
1758 switch (progCtx.uniforms[uniformNdx].type)
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;
1768 DE_ASSERT(DE_FALSE);
1774 void ShaderCompilerCase::draw (void) const
1776 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1778 static const deUint8 indices[] =
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);
1787 // \note Read one pixel to force compilation.
1789 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
1792 void ShaderCompilerCase::cleanup (const ShadersAndProgram& shadersAndProgram, const ProgramContext& progCtx, bool linkSuccess) const
1794 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1798 for (int attribNdx = 0; attribNdx < (int)progCtx.vertexAttributes.size(); attribNdx++)
1800 int location = gl.getAttribLocation(shadersAndProgram.program, progCtx.vertexAttributes[attribNdx].name.c_str());
1802 gl.disableVertexAttribArray(location);
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);
1814 void ShaderCompilerCase::logProgramData (const BuildInfo& buildInfo, const ProgramContext& progCtx) const
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;
1822 ShaderCompilerCase::Logs ShaderCompilerCase::getLogs (const ShadersAndProgram& shadersAndProgram) const
1824 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1827 result.vert = getShaderInfoLog(gl, shadersAndProgram.vertShader);
1828 result.frag = getShaderInfoLog(gl, shadersAndProgram.fragShader);
1829 result.link = getProgramInfoLog(gl, shadersAndProgram.program);
1834 bool ShaderCompilerCase::goodEnoughMeasurements (const vector<Measurement>& measurements) const
1836 if ((int)measurements.size() < m_minimumMeasurementCount)
1840 if ((int)measurements.size() >= m_maximumMeasurementCount)
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;
1852 ShaderCompilerCase::IterateResult ShaderCompilerCase::iterate (void)
1854 // Before actual measurements, compile and draw with a dummy shader to avoid possible initial slowdowns in the actual test.
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));
1862 ShadersAndProgram shadersAndProgram = createShadersAndProgram();
1863 setShaderSources(shadersAndProgram.vertShader, shadersAndProgram.fragShader, progCtx);
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))
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");
1877 setShaderInputs(shadersAndProgram.program, progCtx);
1879 cleanup(shadersAndProgram, progCtx, buildInfo.linkSuccess);
1882 vector<Measurement> measurements;
1883 // \note These are logged after measurements are done.
1884 ProgramContext latestProgramContext;
1885 BuildInfo latestBuildInfo;
1887 if (WARMUP_CPU_AT_BEGINNING_OF_CASE)
1890 // Actual test measurements.
1891 while (!goodEnoughMeasurements(measurements))
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.
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;
1901 if (m_addWhitespaceAndComments)
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);
1908 if (WARMUP_CPU_BEFORE_EACH_MEASUREMENT)
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.
1913 deUint64 startTime = deGetMicroseconds();
1915 setShaderSources(shadersAndProgram.vertShader, shadersAndProgram.fragShader, progCtx);
1916 deUint64 shaderSourceSetEndTime = deGetMicroseconds();
1918 buildInfo.vertCompileSuccess = compileShader(shadersAndProgram.vertShader);
1919 deUint64 vertexShaderCompileEndTime = deGetMicroseconds();
1921 buildInfo.fragCompileSuccess = compileShader(shadersAndProgram.fragShader);
1922 deUint64 fragmentShaderCompileEndTime = deGetMicroseconds();
1924 buildInfo.linkSuccess = linkAndUseProgram(shadersAndProgram.program);
1925 deUint64 programLinkEndTime = deGetMicroseconds();
1927 // Check compilation and linking status here, after all compilation and linking gl calls are made.
1928 if (!(buildInfo.vertCompileSuccess && buildInfo.fragCompileSuccess && buildInfo.linkSuccess))
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");
1937 setShaderInputs(shadersAndProgram.program, progCtx);
1938 deUint64 firstShaderInputSetEndTime = deGetMicroseconds();
1940 // Draw for the first time.
1942 deUint64 firstDrawEndTime = deGetMicroseconds();
1944 // Set inputs and draw again.
1946 setShaderInputs(shadersAndProgram.program, progCtx);
1947 deUint64 secondShaderInputSetEndTime = deGetMicroseconds();
1950 deUint64 secondDrawEndTime = deGetMicroseconds();
1952 // De-initializations (detach shaders etc.).
1954 buildInfo.logs = getLogs(shadersAndProgram);
1955 cleanup(shadersAndProgram, progCtx, buildInfo.linkSuccess);
1957 // Output measurement log later (after last measurement).
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)));
1968 latestBuildInfo = buildInfo;
1969 latestProgramContext = progCtx;
1971 m_testCtx.touchWatchdog(); // \note Measurements may take a while in a bad case.
1974 // End of test case, log information about measurements.
1976 TestLog& log = m_testCtx.getLog();
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;
1992 log << TestLog::Message << "Note: Testing cache hits, so the medians and averages exclude the first iteration." << TestLog::EndMessage;
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;
1997 log << TestLog::Section("IterationMeasurements", "Iteration measurements of compilation and linking times");
1999 DE_ASSERT((int)measurements.size() > (m_avoidCache ? 0 : 1));
2001 for (int ndx = 0; ndx < (int)measurements.size(); ndx++)
2003 const Measurement& curMeas = measurements[ndx];
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();
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);
2012 if (ndx > 0 || m_avoidCache) // \note When allowing cache hits, don't account for the first measurement when calculating median or average.
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);
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);
2037 // Log some statistics.
2039 for (int entireRangeOrLowestHalf = 0; entireRangeOrLowestHalf < 2; entireRangeOrLowestHalf++)
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);
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)
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))
2054 log << TestLog::Message << "\nStatistics computed from "
2055 << (isEntireRange ? "all" : "only the lowest 50%")
2056 << " of the above measurements:"
2057 << TestLog::EndMessage;
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);
2070 #undef LOG_COMPILE_SPECIALIZE_RELATIVE_STAT
2071 #undef LOG_COMPILE_SPECIALIZE_TIME_STAT
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;
2079 log << TestLog::EndSection; // End section IterationMeasurements
2081 for (int medianOrAverage = 0; medianOrAverage < 2; medianOrAverage++)
2083 typedef float (*VecFunc)(const vector<deInt64>&);
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>;
2090 log << TestLog::Section(plural + "PerPhase", plural + " per phase");
2092 for (int entireRangeOrLowestHalf = 0; entireRangeOrLowestHalf < 2; entireRangeOrLowestHalf++)
2094 bool isEntireRange = entireRangeOrLowestHalf == 0;
2095 string statNamePrefix = isEntireRange ? "" : "LowestHalf";
2096 float rangeSizeRatio = isEntireRange ? 1.0f : 0.5f;
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);
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);
2113 log << TestLog::EndSection;
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());
2126 if (m_avoidCache || m_addWhitespaceAndComments)
2128 string msg = "Note: the following shaders are the ones from the last iteration; ";
2131 msg += "variables' names and some constant expressions";
2132 if (m_addWhitespaceAndComments)
2133 msg += string(m_avoidCache ? " as well as " : "") + "whitespace and comments";
2135 msg += " differ between iterations.";
2137 log << TestLog::Message << msg.c_str() << TestLog::EndMessage;
2140 logProgramData(latestBuildInfo, latestProgramContext);
2146 ShaderCompilerLightCase::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)
2155 ShaderCompilerLightCase::~ShaderCompilerLightCase (void)
2157 ShaderCompilerLightCase::deinit();
2160 void ShaderCompilerLightCase::deinit (void)
2163 m_texture = DE_NULL;
2166 void ShaderCompilerLightCase::init (void)
2168 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2172 DE_ASSERT(m_texture == DE_NULL);
2174 m_texture = new glu::Texture2D(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, TEXTURE_WIDTH, TEXTURE_HEIGHT);
2176 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(m_texture->getRefTexture().getFormat());
2178 m_texture->getRefTexture().allocLevel(0);
2179 tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(0), fmtInfo.valueMin, fmtInfo.valueMax);
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();
2189 ShaderCompilerCase::init();
2192 ShaderCompilerCase::ProgramContext ShaderCompilerLightCase::generateShaderData (int measurementNdx) const
2194 deUint32 specID = getSpecializationID(measurementNdx);
2195 string nameSpec = getNameSpecialization(specID);
2196 ProgramContext result;
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);
2206 ShaderCompilerTextureCase::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)
2214 ShaderCompilerTextureCase::~ShaderCompilerTextureCase (void)
2216 ShaderCompilerTextureCase::deinit();
2219 void ShaderCompilerTextureCase::deinit (void)
2221 for (vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
2226 void ShaderCompilerTextureCase::init (void)
2228 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2232 DE_ASSERT(m_textures.empty());
2234 m_textures.reserve(m_numLookups);
2236 for (int i = 0; i < m_numLookups; i++)
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());
2241 tex->getRefTexture().allocLevel(0);
2242 tcu::fillWithComponentGradients(tex->getRefTexture().getLevel(0), fmtInfo.valueMin, fmtInfo.valueMax);
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);
2252 m_textures.push_back(tex);
2255 ShaderCompilerCase::init();
2258 ShaderCompilerCase::ProgramContext ShaderCompilerTextureCase::generateShaderData (int measurementNdx) const
2260 deUint32 specID = getSpecializationID(measurementNdx);
2261 string nameSpec = getNameSpecialization(specID);
2262 ProgramContext result;
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);
2272 ShaderCompilerLoopCase::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)
2281 ShaderCompilerLoopCase::~ShaderCompilerLoopCase (void)
2285 ShaderCompilerCase::ProgramContext ShaderCompilerLoopCase::generateShaderData (int measurementNdx) const
2287 deUint32 specID = getSpecializationID(measurementNdx);
2288 string nameSpec = getNameSpecialization(specID);
2289 ProgramContext result;
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);
2294 result.vertexAttributes = loopShaderAttributes(nameSpec, m_type, m_numLoopIterations);
2295 result.uniforms = loopShaderUniforms(nameSpec, m_type, m_numLoopIterations);
2300 ShaderCompilerOperCase::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)
2303 , m_numOperations (numOperations)
2304 , m_isVertexCase (isVertexCase)
2308 ShaderCompilerOperCase::~ShaderCompilerOperCase (void)
2312 ShaderCompilerCase::ProgramContext ShaderCompilerOperCase::generateShaderData (int measurementNdx) const
2314 deUint32 specID = getSpecializationID(measurementNdx);
2315 string nameSpec = getNameSpecialization(specID);
2316 ProgramContext result;
2320 result.vertShaderSource = specializeShaderSource(binaryOpVertexTemplate(m_numOperations, m_oper.c_str()), specID, SHADER_VALIDITY_VALID);
2321 result.fragShaderSource = specializeShaderSource(singleVaryingFragmentTemplate(), specID, SHADER_VALIDITY_VALID);
2325 result.vertShaderSource = specializeShaderSource(singleVaryingVertexTemplate(), specID, SHADER_VALIDITY_VALID);
2326 result.fragShaderSource = specializeShaderSource(binaryOpFragmentTemplate(m_numOperations, m_oper.c_str()), specID, SHADER_VALIDITY_VALID);
2329 result.vertexAttributes = singleValueShaderAttributes(nameSpec);
2331 result.uniforms.clear(); // No uniforms used.
2336 ShaderCompilerMandelbrotCase::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)
2342 ShaderCompilerMandelbrotCase::~ShaderCompilerMandelbrotCase (void)
2346 ShaderCompilerCase::ProgramContext ShaderCompilerMandelbrotCase::generateShaderData (int measurementNdx) const
2348 deUint32 specID = getSpecializationID(measurementNdx);
2349 string nameSpec = getNameSpecialization(specID);
2350 ProgramContext result;
2352 result.vertShaderSource = specializeShaderSource(mandelbrotVertexTemplate(), specID, SHADER_VALIDITY_VALID);
2353 result.fragShaderSource = specializeShaderSource(mandelbrotFragmentTemplate(m_numFractalIterations), specID, SHADER_VALIDITY_VALID);
2355 result.vertexAttributes = mandelbrotShaderAttributes(nameSpec);
2356 result.uniforms = mandelbrotShaderUniforms(nameSpec);
2361 InvalidShaderCompilerCase::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)))
2366 int cmdLineIterCount = context.getTestContext().getCommandLine().getTestIterationCount();
2367 m_minimumMeasurementCount = cmdLineIterCount > 0 ? cmdLineIterCount : DEFAULT_MINIMUM_MEASUREMENT_COUNT;
2368 m_maximumMeasurementCount = 3*m_minimumMeasurementCount;
2371 InvalidShaderCompilerCase::~InvalidShaderCompilerCase (void)
2375 deUint32 InvalidShaderCompilerCase::getSpecializationID (int measurementNdx) const
2377 return m_startHash ^ (deUint32)deInt32Hash((deInt32)measurementNdx);
2380 InvalidShaderCompilerCase::Shaders InvalidShaderCompilerCase::createShaders (void) const
2382 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2385 result.vertShader = gl.createShader(GL_VERTEX_SHADER);
2386 result.fragShader = gl.createShader(GL_FRAGMENT_SHADER);
2391 void InvalidShaderCompilerCase::setShaderSources (const Shaders& shaders, const ProgramContext& progCtx) const
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);
2400 bool InvalidShaderCompilerCase::compileShader (deUint32 shader) const
2402 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2404 gl.compileShader(shader);
2405 gl.getShaderiv(shader, GL_COMPILE_STATUS, &status);
2409 void InvalidShaderCompilerCase::logProgramData (const BuildInfo& buildInfo, const ProgramContext& progCtx) const
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;
2417 InvalidShaderCompilerCase::Logs InvalidShaderCompilerCase::getLogs (const Shaders& shaders) const
2419 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2422 result.vert = getShaderInfoLog(gl, shaders.vertShader);
2423 result.frag = getShaderInfoLog(gl, shaders.fragShader);
2428 void InvalidShaderCompilerCase::cleanup (const Shaders& shaders) const
2430 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2432 gl.deleteShader(shaders.vertShader);
2433 gl.deleteShader(shaders.fragShader);
2436 bool InvalidShaderCompilerCase::goodEnoughMeasurements (const vector<Measurement>& measurements) const
2438 if ((int)measurements.size() < m_minimumMeasurementCount)
2442 if ((int)measurements.size() >= m_maximumMeasurementCount)
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;
2454 InvalidShaderCompilerCase::IterateResult InvalidShaderCompilerCase::iterate (void)
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;
2460 DE_ASSERT(shaderValidity != SHADER_VALIDITY_LAST);
2462 // Before actual measurements, compile a dummy shader to avoid possible initial slowdowns in the actual test.
2464 deUint32 specID = getSpecializationID(0);
2465 ProgramContext progCtx;
2466 progCtx.vertShaderSource = specializeShaderSource(singleVaryingVertexTemplate(), specID, shaderValidity);
2467 progCtx.fragShaderSource = specializeShaderSource(singleVaryingFragmentTemplate(), specID, shaderValidity);
2469 Shaders shaders = createShaders();
2470 setShaderSources(shaders, progCtx);
2472 BuildInfo buildInfo;
2473 buildInfo.vertCompileSuccess = compileShader(shaders.vertShader);
2474 buildInfo.fragCompileSuccess = compileShader(shaders.fragShader);
2475 if (buildInfo.vertCompileSuccess || buildInfo.fragCompileSuccess)
2477 buildInfo.logs = getLogs(shaders);
2478 logProgramData(buildInfo, progCtx);
2480 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compilation of a shader erroneously succeeded");
2486 vector<Measurement> measurements;
2487 // \note These are logged after measurements are done.
2488 ProgramContext latestProgramContext;
2489 BuildInfo latestBuildInfo;
2491 if (WARMUP_CPU_AT_BEGINNING_OF_CASE)
2494 // Actual test measurements.
2495 while (!goodEnoughMeasurements(measurements))
2497 // Create shader and compile. Measure time.
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;
2504 if (WARMUP_CPU_BEFORE_EACH_MEASUREMENT)
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.
2509 deUint64 startTime = deGetMicroseconds();
2511 setShaderSources(shaders, progCtx);
2512 deUint64 shaderSourceSetEndTime = deGetMicroseconds();
2514 buildInfo.vertCompileSuccess = compileShader(shaders.vertShader);
2515 deUint64 vertexShaderCompileEndTime = deGetMicroseconds();
2517 buildInfo.fragCompileSuccess = compileShader(shaders.fragShader);
2518 deUint64 fragmentShaderCompileEndTime = deGetMicroseconds();
2520 buildInfo.logs = getLogs(shaders);
2522 // Both shader compilations should have failed.
2523 if (buildInfo.vertCompileSuccess || buildInfo.fragCompileSuccess)
2525 logProgramData(buildInfo, progCtx);
2527 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compilation of a shader erroneously succeeded");
2531 // De-initializations (delete shaders).
2535 // Output measurement log later (after last measurement).
2537 measurements.push_back(Measurement((deInt64)(shaderSourceSetEndTime - startTime),
2538 (deInt64)(vertexShaderCompileEndTime - shaderSourceSetEndTime),
2539 (deInt64)(fragmentShaderCompileEndTime - vertexShaderCompileEndTime)));
2541 latestBuildInfo = buildInfo;
2542 latestProgramContext = progCtx;
2544 m_testCtx.touchWatchdog(); // \note Measurements may take a while in a bad case.
2547 // End of test case, log information about measurements.
2549 TestLog& log = m_testCtx.getLog();
2551 vector<deInt64> sourceSetTimes;
2552 vector<deInt64> vertexCompileTimes;
2553 vector<deInt64> fragmentCompileTimes;
2554 vector<deInt64> totalTimes;
2556 log << TestLog::Section("IterationMeasurements", "Iteration measurements of compilation times");
2558 for (int ndx = 0; ndx < (int)measurements.size(); ndx++)
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());
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);
2571 // Log some statistics.
2573 for (int entireRangeOrLowestHalf = 0; entireRangeOrLowestHalf < 2; entireRangeOrLowestHalf++)
2575 bool isEntireRange = entireRangeOrLowestHalf == 0;
2576 string statNamePrefix = isEntireRange ? "" : "LowestHalf";
2577 vector<deInt64> rangeTimes = isEntireRange ? totalTimes : vectorLowestPercentage(totalTimes, 0.5f);
2579 log << TestLog::Message << "\nStatistics computed from "
2580 << (isEntireRange ? "all" : "only the lowest 50%")
2581 << " of the above measurements:"
2582 << TestLog::EndMessage;
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))
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);
2598 #undef LOG_TIME_STAT
2599 #undef LOG_RELATIVE_STAT
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;
2605 log << TestLog::EndSection; // End section IterationMeasurements
2607 for (int medianOrAverage = 0; medianOrAverage < 2; medianOrAverage++)
2609 typedef float (*VecFunc)(const vector<deInt64>&);
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>;
2616 log << TestLog::Section(plural + "PerPhase", plural + " per phase");
2618 for (int entireRangeOrLowestHalf = 0; entireRangeOrLowestHalf < 2; entireRangeOrLowestHalf++)
2620 bool isEntireRange = entireRangeOrLowestHalf == 0;
2621 string statNamePrefix = isEntireRange ? "" : "LowestHalf";
2622 float rangeSizeRatio = isEntireRange ? 1.0f : 0.5f;
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);
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);
2634 log << TestLog::EndSection;
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());
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;
2649 logProgramData(latestBuildInfo, latestProgramContext);
2655 InvalidShaderCompilerLightCase::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)
2663 InvalidShaderCompilerLightCase::~InvalidShaderCompilerLightCase (void)
2667 InvalidShaderCompilerCase::ProgramContext InvalidShaderCompilerLightCase::generateShaderSources (int measurementNdx) const
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;
2675 DE_ASSERT(shaderValidity != SHADER_VALIDITY_LAST);
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);
2683 InvalidShaderCompilerTextureCase::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)
2691 InvalidShaderCompilerTextureCase::~InvalidShaderCompilerTextureCase (void)
2695 InvalidShaderCompilerCase::ProgramContext InvalidShaderCompilerTextureCase::generateShaderSources (int measurementNdx) const
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;
2703 DE_ASSERT(shaderValidity != SHADER_VALIDITY_LAST);
2705 result.vertShaderSource = specializeShaderSource(textureLookupVertexTemplate(m_conditionalUsage, m_conditionalType), specID, shaderValidity);
2706 result.fragShaderSource = specializeShaderSource(textureLookupFragmentTemplate(m_numLookups, m_conditionalUsage, m_conditionalType), specID, shaderValidity);
2711 InvalidShaderCompilerLoopCase::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)
2720 InvalidShaderCompilerLoopCase::~InvalidShaderCompilerLoopCase (void)
2724 InvalidShaderCompilerCase::ProgramContext InvalidShaderCompilerLoopCase::generateShaderSources (int measurementNdx) const
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;
2732 DE_ASSERT(shaderValidity != SHADER_VALIDITY_LAST);
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);
2740 InvalidShaderCompilerOperCase::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)
2744 , m_numOperations (numOperations)
2748 InvalidShaderCompilerOperCase::~InvalidShaderCompilerOperCase (void)
2752 InvalidShaderCompilerCase::ProgramContext InvalidShaderCompilerOperCase::generateShaderSources (int measurementNdx) const
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;
2760 DE_ASSERT(shaderValidity != SHADER_VALIDITY_LAST);
2764 result.vertShaderSource = specializeShaderSource(binaryOpVertexTemplate(m_numOperations, m_oper.c_str()), specID, shaderValidity);
2765 result.fragShaderSource = specializeShaderSource(singleVaryingFragmentTemplate(), specID, shaderValidity);
2769 result.vertShaderSource = specializeShaderSource(singleVaryingVertexTemplate(), specID, shaderValidity);
2770 result.fragShaderSource = specializeShaderSource(binaryOpFragmentTemplate(m_numOperations, m_oper.c_str()), specID, shaderValidity);
2776 InvalidShaderCompilerMandelbrotCase::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)
2782 InvalidShaderCompilerMandelbrotCase::~InvalidShaderCompilerMandelbrotCase (void)
2786 InvalidShaderCompilerCase::ProgramContext InvalidShaderCompilerMandelbrotCase::generateShaderSources (int measurementNdx) const
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;
2794 DE_ASSERT(shaderValidity != SHADER_VALIDITY_LAST);
2796 result.vertShaderSource = specializeShaderSource(mandelbrotVertexTemplate(), specID, shaderValidity);
2797 result.fragShaderSource = specializeShaderSource(mandelbrotFragmentTemplate(m_numFractalIterations), specID, shaderValidity);
2802 void addShaderCompilationPerformanceCases (TestCaseGroup& parentGroup)
2804 Context& context = parentGroup.getContext();
2805 int caseID = 0; // Increment this after adding each case. Used for avoiding cache hits between cases.
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);
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);
2819 // Lighting shader compilation cases.
2822 static const int lightCounts[] = { 1, 2, 4, 8 };
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);
2833 for (int lightType = 0; lightType < (int)LIGHT_LAST; lightType++)
2835 const char* lightTypeName = lightType == (int)LIGHT_DIRECTIONAL ? "directional"
2836 : lightType == (int)LIGHT_POINT ? "point"
2839 DE_ASSERT(lightTypeName != DE_NULL);
2841 for (int isFrag = 0; isFrag <= 1; isFrag++)
2843 bool isVertex = isFrag == 0;
2844 const char* vertFragStr = isVertex ? "vertex" : "fragment";
2846 for (int lightCountNdx = 0; lightCountNdx < DE_LENGTH_OF_ARRAY(lightCounts); lightCountNdx++)
2848 int numLights = lightCounts[lightCountNdx];
2850 string caseName = string("") + lightTypeName + "_" + de::toString(numLights) + "_lights_" + vertFragStr;
2852 // Valid shader case, no-cache and cache versions.
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));
2857 // Invalid shader cases.
2859 for (int invalidityType = 0; invalidityType < (int)InvalidShaderCompilerCase::INVALIDITY_LAST; invalidityType++)
2861 TestCaseGroup* curInvalidGroup = invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_INVALID_CHAR ? invalidCharLightingGroup
2862 : invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_SEMANTIC_ERROR ? semanticErrorLightingGroup
2865 DE_ASSERT(curInvalidGroup != DE_NULL);
2867 curInvalidGroup->addChild(new InvalidShaderCompilerLightCase(context, caseName.c_str(), "", caseID++, (InvalidShaderCompilerCase::InvalidityType)invalidityType, isVertex, numLights, (LightType)lightType));
2874 // Texture lookup shader compilation cases.
2877 static const int texLookupCounts[] = { 1, 2, 4, 8 };
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);
2888 for (int conditionalUsage = 0; conditionalUsage < (int)CONDITIONAL_USAGE_LAST; conditionalUsage++)
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"
2895 DE_ASSERT(conditionalUsageName != DE_NULL);
2897 int lastConditionalType = conditionalUsage == (int)CONDITIONAL_USAGE_NONE ? 1 : (int)CONDITIONAL_TYPE_LAST;
2899 for (int conditionalType = 0; conditionalType < lastConditionalType; conditionalType++)
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"
2906 DE_ASSERT(conditionalTypeName != DE_NULL);
2908 for (int lookupCountNdx = 0; lookupCountNdx < DE_LENGTH_OF_ARRAY(texLookupCounts); lookupCountNdx++)
2910 int numLookups = texLookupCounts[lookupCountNdx];
2912 string caseName = de::toString(numLookups) + "_lookups_" + conditionalUsageName + (conditionalUsage == (int)CONDITIONAL_USAGE_NONE ? "" : string("_") + conditionalTypeName);
2914 // Valid shader case, no-cache and cache versions.
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));
2919 // Invalid shader cases.
2921 for (int invalidityType = 0; invalidityType < (int)InvalidShaderCompilerCase::INVALIDITY_LAST; invalidityType++)
2923 TestCaseGroup* curInvalidGroup = invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_INVALID_CHAR ? invalidCharTexGroup
2924 : invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_SEMANTIC_ERROR ? semanticErrorTexGroup
2927 DE_ASSERT(curInvalidGroup != DE_NULL);
2929 curInvalidGroup->addChild(new InvalidShaderCompilerTextureCase(context, caseName.c_str(), "", caseID++, (InvalidShaderCompilerCase::InvalidityType)invalidityType, numLookups, (ConditionalUsage)conditionalUsage, (ConditionalType)conditionalType));
2936 // Loop shader compilation cases.
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.
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);
2952 for (int loopType = 0; loopType < (int)LOOP_LAST; loopType++)
2954 const char* loopTypeName = loopType == (int)LOOP_TYPE_STATIC ? "static"
2955 : loopType == (int)LOOP_TYPE_UNIFORM ? "uniform"
2956 : loopType == (int)LOOP_TYPE_DYNAMIC ? "dynamic"
2959 DE_ASSERT(loopTypeName != DE_NULL);
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);
2970 for (int isFrag = 0; isFrag <= 1; isFrag++)
2972 bool isVertex = isFrag == 0;
2973 const char* vertFragStr = isVertex ? "vertex" : "fragment";
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);
2978 for (int nestingDepth = 1; nestingDepth <= maxLoopNestingDepth; nestingDepth++)
2980 for (int loopIterCountNdx = 0; loopIterCountNdx < loopIterCountMaxNdx; loopIterCountNdx++)
2982 int numIterations = loopIterCounts[loopIterCountNdx];
2984 if (deFloatPow((float)numIterations, (float)nestingDepth) > (float)maxTotalLoopIterations)
2985 continue; // Don't generate too heavy tasks.
2987 string validCaseName = de::toString(numIterations) + "_iterations_" + de::toString(nestingDepth) + "_levels_" + vertFragStr;
2989 // Valid shader case, no-cache and cache versions.
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));
2994 // Invalid shader cases.
2996 for (int invalidityType = 0; invalidityType < (int)InvalidShaderCompilerCase::INVALIDITY_LAST; invalidityType++)
2998 TestCaseGroup* curInvalidGroup = invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_INVALID_CHAR ? invalidCharLoopTypeGroup
2999 : invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_SEMANTIC_ERROR ? semanticErrorLoopTypeGroup
3002 DE_ASSERT(curInvalidGroup != DE_NULL);
3004 string invalidCaseName = de::toString(nestingDepth) + "_levels_" + vertFragStr;
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).
3009 curInvalidGroup->addChild(new InvalidShaderCompilerLoopCase(context, invalidCaseName.c_str(), "", caseID++, (InvalidShaderCompilerCase::InvalidityType)invalidityType, isVertex, (LoopType)loopType, numIterations, nestingDepth));
3017 // Multiplication shader compilation cases.
3020 static const int multiplicationCounts[] = { 10, 100, 1000 };
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);
3031 for (int isFrag = 0; isFrag <= 1; isFrag++)
3033 bool isVertex = isFrag == 0;
3034 const char* vertFragStr = isVertex ? "vertex" : "fragment";
3036 for (int operCountNdx = 0; operCountNdx < DE_LENGTH_OF_ARRAY(multiplicationCounts); operCountNdx++)
3038 int numOpers = multiplicationCounts[operCountNdx];
3040 string caseName = de::toString(numOpers) + "_operations_" + vertFragStr;
3042 // Valid shader case, no-cache and cache versions.
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));
3047 // Invalid shader cases.
3049 for (int invalidityType = 0; invalidityType < (int)InvalidShaderCompilerCase::INVALIDITY_LAST; invalidityType++)
3051 TestCaseGroup* curInvalidGroup = invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_INVALID_CHAR ? invalidCharMulGroup
3052 : invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_SEMANTIC_ERROR ? semanticErrorMulGroup
3055 DE_ASSERT(curInvalidGroup != DE_NULL);
3057 curInvalidGroup->addChild(new InvalidShaderCompilerOperCase(context, caseName.c_str(), "", caseID++, (InvalidShaderCompilerCase::InvalidityType)invalidityType, isVertex, "*", numOpers));
3063 // Mandelbrot shader compilation cases.
3066 static const int mandelbrotIterationCounts[] = { 32, 64, 128 };
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);
3077 for (int iterCountNdx = 0; iterCountNdx < DE_LENGTH_OF_ARRAY(mandelbrotIterationCounts); iterCountNdx++)
3079 int numFractalIterations = mandelbrotIterationCounts[iterCountNdx];
3080 string caseName = de::toString(numFractalIterations) + "_iterations";
3082 // Valid shader case, no-cache and cache versions.
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));
3087 // Invalid shader cases.
3089 for (int invalidityType = 0; invalidityType < (int)InvalidShaderCompilerCase::INVALIDITY_LAST; invalidityType++)
3091 TestCaseGroup* curInvalidGroup = invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_INVALID_CHAR ? invalidCharMandelbrotGroup
3092 : invalidityType == (int)InvalidShaderCompilerCase::INVALIDITY_SEMANTIC_ERROR ? semanticErrorMandelbrotGroup
3095 DE_ASSERT(curInvalidGroup != DE_NULL);
3097 curInvalidGroup->addChild(new InvalidShaderCompilerMandelbrotCase(context, caseName.c_str(), "", caseID++, (InvalidShaderCompilerCase::InvalidityType)invalidityType, numFractalIterations));
3102 // Cases testing cache behaviour when whitespace and comments are added.
3105 TestCaseGroup* whitespaceCommentCacheGroup = new TestCaseGroup(context, "cache_whitespace_comment", "Cases testing the effect of whitespace and comments on caching");
3106 parentGroup.addChild(whitespaceCommentCacheGroup);
3108 // \note Add just a small subset of the cases that were added above for the main performance tests.
3110 // Cases with both vertex and fragment variants.
3111 for (int isFrag = 0; isFrag <= 1; isFrag++)
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;
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));
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));