1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Long running shader stress tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es3sLongRunningShaderTests.hpp" 25 26#include "gluShaderProgram.hpp" 27#include "gluShaderUtil.hpp" 28#include "gluDrawUtil.hpp" 29 30#include "tcuRenderTarget.hpp" 31#include "tcuVector.hpp" 32#include "tcuTestLog.hpp" 33 34#include "deRandom.hpp" 35#include "deStringUtil.hpp" 36#include "deString.h" 37 38#include "glwFunctions.hpp" 39#include "glwEnums.hpp" 40 41namespace deqp 42{ 43namespace gles3 44{ 45namespace Stress 46{ 47 48using tcu::TestLog; 49using tcu::Vec2; 50using std::vector; 51 52namespace 53{ 54 55enum LoopType 56{ 57 LOOPTYPE_FOR = 0, 58 LOOPTYPE_WHILE, 59 LOOPTYPE_DO_WHILE, 60 61 LOOPTYPE_LAST 62}; 63 64enum IterCountType 65{ 66 ITERCOUNTTYPE_STATIC = 0, 67 ITERCOUNTTYPE_UNIFORM, 68 ITERCOUNTTYPE_DYNAMIC, 69 70 ITERCOUNTTYPE_LAST 71}; 72 73class LongRunningShaderCase : public TestCase 74{ 75public: 76 struct Params 77 { 78 const char* name; 79 const char* description; 80 glu::ShaderType shaderType; 81 LoopType loopType; 82 IterCountType iterCountType; 83 int numInvocations; 84 int minLoopIterCount; 85 int maxLoopIterCount; 86 }; 87 88 LongRunningShaderCase (Context& context, const Params* params); 89 ~LongRunningShaderCase (void); 90 91 void init (void); 92 void deinit (void); 93 IterateResult iterate (void); 94 95private: 96 LongRunningShaderCase (const LongRunningShaderCase&); 97 LongRunningShaderCase& operator= (const LongRunningShaderCase&); 98 99 static glu::ProgramSources genSources (const Params& params); 100 static deUint32 getSeed (const Params& params); 101 102 const Params* const m_params; 103 const int m_numCaseIters; 104 105 glu::ShaderProgram* m_program; 106 int m_caseIterNdx; 107}; 108 109LongRunningShaderCase::LongRunningShaderCase (Context& context, const Params* params) 110 : TestCase (context, params->name, params->description) 111 , m_params (params) 112 , m_numCaseIters (5) 113 , m_program (DE_NULL) 114 , m_caseIterNdx (0) 115{ 116} 117 118LongRunningShaderCase::~LongRunningShaderCase (void) 119{ 120 deinit(); 121} 122 123glu::ProgramSources LongRunningShaderCase::genSources (const Params& params) 124{ 125 const bool isVertCase = params.shaderType == glu::SHADERTYPE_VERTEX; 126 std::ostringstream vert, frag; 127 128 vert << "#version 300 es\n" 129 << "in highp vec2 a_position;\n"; 130 131 frag << "#version 300 es\n"; 132 133 if (params.iterCountType == ITERCOUNTTYPE_DYNAMIC) 134 { 135 vert << "in highp int a_iterCount;\n"; 136 if (!isVertCase) 137 { 138 vert << "flat out highp int v_iterCount;\n"; 139 frag << "flat in highp int v_iterCount;\n"; 140 } 141 } 142 else if (params.iterCountType == ITERCOUNTTYPE_UNIFORM) 143 (isVertCase ? vert : frag) << "uniform highp int u_iterCount;\n"; 144 145 if (isVertCase) 146 { 147 vert << "out mediump vec4 v_color;\n"; 148 frag << "in mediump vec4 v_color;\n"; 149 } 150 151 frag << "out mediump vec4 o_color;\n"; 152 153 vert << "\nvoid main (void)\n{\n" 154 << " gl_Position = vec4(a_position, 0.0, 1.0);\n" 155 << " gl_PointSize = 1.0;\n"; 156 157 if (!isVertCase && params.iterCountType == ITERCOUNTTYPE_DYNAMIC) 158 vert << " v_iterCount = a_iterCount;\n"; 159 160 frag << "\nvoid main (void)\n{\n"; 161 162 { 163 const std::string iterCount = params.iterCountType == ITERCOUNTTYPE_DYNAMIC ? (isVertCase ? "a_iterCount" : "v_iterCount") : 164 params.iterCountType == ITERCOUNTTYPE_UNIFORM ? "u_iterCount" : 165 params.iterCountType == ITERCOUNTTYPE_STATIC ? de::toString(params.maxLoopIterCount) : "<invalid>"; 166 const char* const body = "color = cos(sin(color*1.25)*0.8);"; 167 std::ostringstream& op = isVertCase ? vert : frag; 168 169 op << " mediump vec4 color = " << (isVertCase ? "a_position.xyxy" : "gl_FragCoord") << ";\n"; 170 171 if (params.loopType == LOOPTYPE_FOR) 172 { 173 op << " for (highp int i = 0; i < " << iterCount << " || " << iterCount << " < 0; ++i)\n" 174 << " " << body << "\n"; 175 } 176 else if (params.loopType == LOOPTYPE_WHILE) 177 { 178 op << " highp int i = 0;\n" 179 << " while (i < " << iterCount << " || " << iterCount << " < 0) {\n" 180 << " i += 1;\n" 181 << " " << body << "\n" 182 << " }\n"; 183 } 184 else 185 { 186 DE_ASSERT(params.loopType == LOOPTYPE_DO_WHILE); 187 op << " highp int i = 0;\n" 188 << " do {\n" 189 << " i += 1;\n" 190 << " " << body << "\n" 191 << " } while (i <= " << iterCount << " || " << iterCount << " < 0);\n"; 192 } 193 } 194 195 if (isVertCase) 196 { 197 vert << " v_color = color;\n"; 198 frag << " o_color = v_color;\n"; 199 } 200 else 201 frag << " o_color = color;\n"; 202 203 vert << "}\n"; 204 frag << "}\n"; 205 206 return glu::ProgramSources() << glu::VertexSource(vert.str()) << glu::FragmentSource(frag.str()); 207} 208 209void LongRunningShaderCase::init (void) 210{ 211 DE_ASSERT(!m_program); 212 m_program = new glu::ShaderProgram(m_context.getRenderContext(), genSources(*m_params)); 213 214 m_testCtx.getLog() << *m_program; 215 216 if (!m_program->isOk()) 217 { 218 deinit(); 219 TCU_FAIL("Failed to compile shader program"); 220 } 221 222 m_caseIterNdx = 0; 223 224 if (m_params->iterCountType != ITERCOUNTTYPE_STATIC) 225 { 226 m_testCtx.getLog() << TestLog::Message << "Loop iteration counts in range: [" << m_params->minLoopIterCount 227 << ", " << m_params->maxLoopIterCount << "]" 228 << TestLog::EndMessage; 229 } 230 231 m_testCtx.getLog() << TestLog::Message << "Number of vertices and fragments: " << m_params->numInvocations << TestLog::EndMessage; 232 233 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Test will pass or timeout, unless driver/device crashes. 234} 235 236void LongRunningShaderCase::deinit (void) 237{ 238 delete m_program; 239 m_program = DE_NULL; 240} 241 242void genPositions (const tcu::RenderTarget& renderTarget, int numPoints, Vec2* positions) 243{ 244 const int width = renderTarget.getWidth(); 245 const int height = renderTarget.getHeight(); 246 247 if (width*height < numPoints) 248 throw tcu::NotSupportedError("Too small viewport to fit all test points"); 249 250 for (int pointNdx = 0; pointNdx < numPoints; pointNdx++) 251 { 252 const int xi = pointNdx % width; 253 const int yi = pointNdx / height; 254 const float xf = 2.0f * ((float(xi) + 0.5f) / float(width)) - 1.0f; 255 const float yf = 2.0f * ((float(yi) + 0.5f) / float(height)) - 1.0f; 256 257 positions[pointNdx] = Vec2(xf, yf); 258 } 259} 260 261deUint32 LongRunningShaderCase::getSeed (const Params& params) 262{ 263 const deUint32 seed = deStringHash(params.name) 264 ^ deInt32Hash(params.shaderType) 265 ^ deInt32Hash(params.loopType) 266 ^ deInt32Hash(params.iterCountType) 267 ^ deInt32Hash(params.minLoopIterCount) 268 ^ deInt32Hash(params.maxLoopIterCount) 269 ^ deInt32Hash(params.numInvocations); 270 return seed; 271} 272 273LongRunningShaderCase::IterateResult LongRunningShaderCase::iterate (void) 274{ 275 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 276 de::Random rnd (getSeed(*m_params)); 277 vector<Vec2> positions (m_params->numInvocations); 278 vector<int> iterCounts (m_params->iterCountType == ITERCOUNTTYPE_DYNAMIC ? m_params->numInvocations : 1); 279 vector<glu::VertexArrayBinding> vertexArrays; 280 281 vertexArrays.push_back(glu::va::Float("a_position", 2, (int)positions.size(), 0, positions[0].getPtr())); 282 if (m_params->iterCountType == ITERCOUNTTYPE_DYNAMIC) 283 vertexArrays.push_back(glu::va::Int32("a_iterCount", 1, (int)iterCounts.size(), 0, &iterCounts[0])); 284 285 genPositions(m_context.getRenderTarget(), (int)positions.size(), &positions[0]); 286 287 for (vector<int>::iterator i = iterCounts.begin(); i != iterCounts.end(); ++i) 288 *i = rnd.getInt(m_params->minLoopIterCount, m_params->maxLoopIterCount); 289 290 gl.useProgram(m_program->getProgram()); 291 292 if (m_params->iterCountType == ITERCOUNTTYPE_UNIFORM) 293 gl.uniform1i(gl.getUniformLocation(m_program->getProgram(), "u_iterCount"), iterCounts[0]); 294 295 glu::draw(m_context.getRenderContext(), m_program->getProgram(), 296 (int)vertexArrays.size(), &vertexArrays[0], 297 glu::pr::Points(m_params->numInvocations)); 298 299 m_caseIterNdx += 1; 300 return (m_caseIterNdx < m_numCaseIters) ? CONTINUE : STOP; 301} 302 303} // anonymous 304 305LongRunningShaderTests::LongRunningShaderTests (Context& context) 306 : TestCaseGroup(context, "long_running_shaders", "Long-running shader stress tests") 307{ 308} 309 310LongRunningShaderTests::~LongRunningShaderTests (void) 311{ 312} 313 314void LongRunningShaderTests::init (void) 315{ 316 const int numInvocations = 4096; 317 const int shortLoopMin = 5; 318 const int shortLoopMax = 10; 319 const int mediumLoopMin = 10000; 320 const int mediumLoopMax = 50000; 321 const int longLoopMin = 100000; 322 const int longLoopMax = 500000; 323 324 static const LongRunningShaderCase::Params s_cases[] = 325 { 326 { "short_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, shortLoopMin, shortLoopMax }, 327 { "short_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, shortLoopMin, shortLoopMax }, 328 { "short_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, shortLoopMin, shortLoopMax }, 329 { "short_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, shortLoopMin, shortLoopMax }, 330 { "short_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, shortLoopMin, shortLoopMax }, 331 { "short_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, shortLoopMin, shortLoopMax }, 332 333 { "medium_static_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_STATIC, numInvocations, mediumLoopMin, mediumLoopMax }, 334 { "medium_static_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_STATIC, numInvocations, mediumLoopMin, mediumLoopMax }, 335 { "medium_uniform_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_UNIFORM, numInvocations, mediumLoopMin, mediumLoopMax }, 336 { "medium_uniform_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_UNIFORM, numInvocations, mediumLoopMin, mediumLoopMax }, 337 338 { "medium_dynamic_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, mediumLoopMin, mediumLoopMax }, 339 { "medium_dynamic_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, mediumLoopMin, mediumLoopMax }, 340 { "medium_dynamic_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, mediumLoopMin, mediumLoopMax }, 341 { "medium_dynamic_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, mediumLoopMin, mediumLoopMax }, 342 { "medium_dynamic_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, mediumLoopMin, mediumLoopMax }, 343 { "medium_dynamic_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, mediumLoopMin, mediumLoopMax }, 344 345 { "long_static_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_STATIC, numInvocations, longLoopMin, longLoopMax }, 346 { "long_static_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_STATIC, numInvocations, longLoopMin, longLoopMax }, 347 { "long_uniform_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_UNIFORM, numInvocations, longLoopMin, longLoopMax }, 348 { "long_uniform_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_UNIFORM, numInvocations, longLoopMin, longLoopMax }, 349 350 { "long_dynamic_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, longLoopMin, longLoopMax }, 351 { "long_dynamic_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, longLoopMin, longLoopMax }, 352 { "long_dynamic_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, longLoopMin, longLoopMax }, 353 { "long_dynamic_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, longLoopMin, longLoopMax }, 354 { "long_dynamic_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, longLoopMin, longLoopMax }, 355 { "long_dynamic_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, longLoopMin, longLoopMax }, 356 357 { "infinite_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1, -1 }, 358 { "infinite_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1, -1 }, 359 { "infinite_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1, -1 }, 360 { "infinite_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1, -1 }, 361 { "infinite_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1, -1 }, 362 { "infinite_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1, -1 }, 363 }; 364 365 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_cases); ndx++) 366 addChild(new LongRunningShaderCase(m_context, &s_cases[ndx])); 367} 368 369} // Stress 370} // gles3 371} // deqp 372