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 stress tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es3sLongRunningTests.hpp" 25 #include "glsLongStressCase.hpp" 26 #include "glsLongStressTestUtil.hpp" 27 #include "glwEnums.hpp" 28 29 #include <string> 30 31 using std::string; 32 33 namespace deqp 34 { 35 namespace gles3 36 { 37 namespace Stress 38 { 39 40 LongRunningTests::LongRunningTests (Context& context) 41 : TestCaseGroup(context, "long", "Long-running stress tests") 42 { 43 } 44 45 LongRunningTests::~LongRunningTests (void) 46 { 47 } 48 49 void LongRunningTests::init (void) 50 { 51 static const int Mi = 1<<20; 52 const gls::LongStressTestUtil::ProgramLibrary progLib (glu::GLSL_VERSION_300_ES); 53 54 typedef gls::LongStressCase::FeatureProbabilities Probs; 55 56 // Buffer cases. 57 58 { 59 static const struct MemCase 60 { 61 const char* const nameSuffix; 62 const char* const descSuffix; 63 const int limit; 64 const int redundantBufferFactor; 65 MemCase (const char* n, const char* d, int l, int r) : nameSuffix(n), descSuffix(d), limit(l), redundantBufferFactor(r) {} 66 } memoryLimitCases[] = 67 { 68 MemCase("_low_memory", "; use a low buffer memory usage limit", 8*Mi, 2), 69 MemCase("_high_memory", "; use a high buffer memory usage limit", 256*Mi, 64) 70 }; 71 72 const std::vector<gls::ProgramContext> contexts(1, progLib.generateBufferContext(4)); 73 74 static const struct Case 75 { 76 const char* const name; 77 const char* const desc; 78 const int redundantBufferFactor; //!< If non-positive, taken from memoryLimitCases. 79 const Probs probs; 80 Case (const char* const name_, const char* const desc_, int bufFact, const Probs& probs_ = Probs()) : name(name_), desc(desc_), redundantBufferFactor(bufFact), probs(probs_) {} 81 } cases[] = 82 { 83 Case("always_reupload", 84 "Re-upload buffer data at the beginning of each iteration", 85 -1, 86 Probs().pReuploadBuffer(1.0f)), 87 88 Case("always_reupload_bufferdata", 89 "Re-upload buffer data at the beginning of each iteration, using glBufferData", 90 -1, 91 Probs().pReuploadBuffer(1.0f).pReuploadWithBufferData(1.0f)), 92 93 Case("always_delete", 94 "Delete buffers at the end of each iteration, and re-create at the beginning of the next", 95 -1, 96 Probs().pDeleteBuffer(1.0f)), 97 98 Case("wasteful", 99 "Don't reuse buffers, and only delete them when given memory limit is reached", 100 2, 101 Probs().pWastefulBufferMemoryUsage(1.0f)), 102 103 Case("separate_attribute_buffers_wasteful", 104 "Give each vertex attribute its own buffer", 105 2, 106 Probs().pSeparateAttribBuffers(1.0f).pWastefulBufferMemoryUsage(1.0f)) 107 }; 108 109 TestCaseGroup* const bufferGroup = new TestCaseGroup(m_context, "buffer", "Buffer stress tests"); 110 addChild(bufferGroup); 111 112 for (int memoryLimitNdx = 0; memoryLimitNdx < DE_LENGTH_OF_ARRAY(memoryLimitCases); memoryLimitNdx++) 113 { 114 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++) 115 { 116 const int redundantBufferFactor = cases[caseNdx].redundantBufferFactor > 0 ? cases[caseNdx].redundantBufferFactor : memoryLimitCases[memoryLimitNdx].redundantBufferFactor; 117 118 bufferGroup->addChild(new gls::LongStressCase(m_context.getTestContext(), m_context.getRenderContext(), 119 (string() + cases[caseNdx].name + memoryLimitCases[memoryLimitNdx].nameSuffix).c_str(), 120 (string() + cases[caseNdx].desc + memoryLimitCases[memoryLimitNdx].descSuffix).c_str(), 121 0 /* tex memory */, memoryLimitCases[memoryLimitNdx].limit, 122 1 /* draw calls per iteration */, 50000 /* tris per call */, 123 contexts, cases[caseNdx].probs, 124 GL_DYNAMIC_DRAW, GL_DYNAMIC_DRAW, 125 redundantBufferFactor)); 126 } 127 } 128 } 129 130 // Texture cases. 131 132 { 133 static const struct MemCase 134 { 135 const char* const nameSuffix; 136 const char* const descSuffix; 137 const int limit; 138 const int numTextures; 139 MemCase (const char* n, const char* d, int l, int t) : nameSuffix(n), descSuffix(d), limit(l), numTextures(t) {} 140 } memoryLimitCases[] = 141 { 142 MemCase("_low_memory", "; use a low texture memory usage limit", 8*Mi, 6), 143 MemCase("_high_memory", "; use a high texture memory usage limit", 256*Mi, 192) 144 }; 145 146 static const struct Case 147 { 148 const char* const name; 149 const char* const desc; 150 const int numTextures; //!< If non-positive, taken from memoryLimitCases. 151 const Probs probs; 152 Case (const char* const name_, const char* const desc_, int numTextures_, const Probs& probs_ = Probs()) : name(name_), desc(desc_), numTextures(numTextures_), probs(probs_) {} 153 } cases[] = 154 { 155 Case("always_reupload", 156 "Re-upload texture data at the beginning of each iteration", 157 -1, 158 Probs().pReuploadTexture(1.0f)), 159 160 Case("always_reupload_teximage", 161 "Re-upload texture data at the beginning of each iteration, using glTexImage*", 162 -1, 163 Probs().pReuploadTexture(1.0f).pReuploadWithTexImage(1.0f)), 164 165 Case("always_delete", 166 "Delete textures at the end of each iteration, and re-create at the beginning of the next", 167 -1, 168 Probs().pDeleteTexture(1.0f)), 169 170 Case("wasteful", 171 "Don't reuse textures, and only delete them when given memory limit is reached", 172 6, 173 Probs().pWastefulTextureMemoryUsage(1.0f)) 174 }; 175 176 TestCaseGroup* const textureGroup = new TestCaseGroup(m_context, "texture", "Texture stress tests"); 177 addChild(textureGroup); 178 179 for (int memoryLimitNdx = 0; memoryLimitNdx < DE_LENGTH_OF_ARRAY(memoryLimitCases); memoryLimitNdx++) 180 { 181 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++) 182 { 183 const int numTextures = cases[caseNdx].numTextures > 0 ? cases[caseNdx].numTextures : memoryLimitCases[memoryLimitNdx].numTextures; 184 const std::vector<gls::ProgramContext> contexts (1, progLib.generateTextureContext(numTextures, 512, 512, 0.1f)); 185 186 textureGroup->addChild(new gls::LongStressCase(m_context.getTestContext(), m_context.getRenderContext(), 187 (string() + cases[caseNdx].name + memoryLimitCases[memoryLimitNdx].nameSuffix).c_str(), 188 (string() + cases[caseNdx].desc + memoryLimitCases[memoryLimitNdx].descSuffix).c_str(), 189 memoryLimitCases[memoryLimitNdx].limit, 1*Mi /* buf memory */, 190 1 /* draw calls per iteration */, 10000 /* tris per call */, 191 contexts, cases[caseNdx].probs, 192 GL_STATIC_DRAW, GL_STATIC_DRAW)); 193 } 194 } 195 } 196 197 // Draw call cases. 198 199 { 200 const std::vector<gls::ProgramContext> contexts(1, progLib.generateTextureContext(1, 128, 128, 0.5f)); 201 202 static const struct Case 203 { 204 const char* const name; 205 const char* const desc; 206 const int drawCallsPerIteration; 207 const int numTrisPerDrawCall; 208 const Probs probs; 209 Case (const char* const name_, const char* const desc_, const int calls, const int tris, const Probs& probs_ = Probs()) 210 : name(name_), desc(desc_), drawCallsPerIteration(calls), numTrisPerDrawCall(tris), probs(probs_) {} 211 } cases[] = 212 { 213 Case("client_memory_data", 214 "Use client-memory for index and attribute data, instead of GL buffers", 215 200, 500, 216 Probs().pClientMemoryAttributeData(1.0f).pClientMemoryIndexData(1.0f)), 217 218 Case("vary_draw_function", 219 "Choose between glDrawElements and glDrawArrays each iteration, with uniform probability", 220 200, 500, 221 Probs().pUseDrawArrays(0.5f)), 222 223 Case("few_big_calls", 224 "Per iteration, do a few draw calls with a big number of triangles per call", 225 2, 50000), 226 227 Case("many_small_calls", 228 "Per iteration, do many draw calls with a small number of triangles per call", 229 2000, 50) 230 }; 231 232 TestCaseGroup* const drawCallGroup = new TestCaseGroup(m_context, "draw_call", "Draw call stress tests"); 233 addChild(drawCallGroup); 234 235 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++) 236 { 237 drawCallGroup->addChild(new gls::LongStressCase(m_context.getTestContext(), m_context.getRenderContext(), 238 cases[caseNdx].name, cases[caseNdx].desc, 239 1*Mi /* tex memory */, 2*Mi /* buf memory */, 240 cases[caseNdx].drawCallsPerIteration, cases[caseNdx].numTrisPerDrawCall, 241 contexts, cases[caseNdx].probs, 242 GL_STATIC_DRAW, GL_STATIC_DRAW)); 243 } 244 } 245 246 // Shader cases. 247 248 { 249 std::vector<gls::ProgramContext> contexts; 250 contexts.push_back(progLib.generateFragmentPointLightContext(512, 512)); 251 contexts.push_back(progLib.generateVertexUniformLoopLightContext(512, 512)); 252 253 static const struct Case 254 { 255 const char* const name; 256 const char* const desc; 257 const Probs probs; 258 Case (const char* const name_, const char* const desc_, const Probs& probs_ = Probs()) : name(name_), desc(desc_), probs(probs_) {} 259 } cases[] = 260 { 261 Case("several_programs", 262 "Use several different programs, choosing between them uniformly on each iteration"), 263 264 Case("several_programs_always_rebuild", 265 "Use several different programs, choosing between them uniformly on each iteration, and always rebuild the program", 266 Probs().pRebuildProgram(1.0f)) 267 }; 268 269 TestCaseGroup* const shaderGroup = new TestCaseGroup(m_context, "program", "Shader program stress tests"); 270 addChild(shaderGroup); 271 272 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++) 273 { 274 shaderGroup->addChild(new gls::LongStressCase(m_context.getTestContext(), m_context.getRenderContext(), 275 cases[caseNdx].name, cases[caseNdx].desc, 276 3*Mi /* tex memory */, 1*Mi /* buf memory */, 277 1 /* draw calls per iteration */, 10000 /* tris per call */, 278 contexts, cases[caseNdx].probs, 279 GL_STATIC_DRAW, GL_STATIC_DRAW)); 280 } 281 } 282 283 // Mixed cases. 284 285 { 286 static const struct MemCase 287 { 288 const char* const nameSuffix; 289 const char* const descSuffix; 290 const int texLimit; 291 const int bufLimit; 292 MemCase (const char* n, const char* d, int t, int b) : nameSuffix(n), descSuffix(d), texLimit(t), bufLimit(b) {} 293 } memoryLimitCases[] = 294 { 295 MemCase("_low_memory", "; use a low memory usage limit", 8*Mi, 8*Mi), 296 MemCase("_high_memory", "; use a high memory usage limit", 128*Mi, 128*Mi) 297 }; 298 299 TestCaseGroup* const mixedGroup = new TestCaseGroup(m_context, "mixed", "Mixed stress tests"); 300 addChild(mixedGroup); 301 302 for (int memoryLimitNdx = 0; memoryLimitNdx < DE_LENGTH_OF_ARRAY(memoryLimitCases); memoryLimitNdx++) 303 { 304 mixedGroup->addChild(new gls::LongStressCase(m_context.getTestContext(), m_context.getRenderContext(), 305 (string() + "buffer_texture_wasteful" + memoryLimitCases[memoryLimitNdx].nameSuffix).c_str(), 306 (string() + "Use both buffers and textures wastefully" + memoryLimitCases[memoryLimitNdx].descSuffix).c_str(), 307 memoryLimitCases[memoryLimitNdx].texLimit, memoryLimitCases[memoryLimitNdx].bufLimit, 308 1 /* draw calls per iteration */, 10000 /* tris per call */, 309 std::vector<gls::ProgramContext>(1, progLib.generateBufferAndTextureContext(4, 512, 512)), 310 Probs() 311 .pReuploadTexture (0.3f) 312 .pReuploadWithTexImage (0.5f) 313 .pReuploadBuffer (0.3f) 314 .pReuploadWithBufferData (0.5f) 315 .pDeleteTexture (0.2f) 316 .pDeleteBuffer (0.2f) 317 .pWastefulTextureMemoryUsage (0.5f) 318 .pWastefulBufferMemoryUsage (0.5f) 319 .pRandomBufferUploadTarget (1.0f) 320 .pRandomBufferUsage (1.0f), 321 GL_STATIC_DRAW, GL_STATIC_DRAW)); 322 323 { 324 std::vector<gls::ProgramContext> contexts; 325 contexts.push_back(progLib.generateFragmentPointLightContext(512, 512)); 326 contexts.push_back(progLib.generateVertexUniformLoopLightContext(512, 512)); 327 mixedGroup->addChild(new gls::LongStressCase(m_context.getTestContext(), m_context.getRenderContext(), 328 (string() + "random" + memoryLimitCases[memoryLimitNdx].nameSuffix).c_str(), 329 (string() + "Highly random behavior" + memoryLimitCases[memoryLimitNdx].descSuffix).c_str(), 330 memoryLimitCases[memoryLimitNdx].texLimit, memoryLimitCases[memoryLimitNdx].bufLimit, 331 1 /* draw calls per iteration */, 10000 /* tris per call */, 332 contexts, 333 Probs() 334 .pRebuildProgram (0.3f) 335 .pReuploadTexture (0.3f) 336 .pReuploadWithTexImage (0.3f) 337 .pReuploadBuffer (0.3f) 338 .pReuploadWithBufferData (0.3f) 339 .pDeleteTexture (0.2f) 340 .pDeleteBuffer (0.2f) 341 .pWastefulTextureMemoryUsage (0.3f) 342 .pWastefulBufferMemoryUsage (0.3f) 343 .pClientMemoryAttributeData (0.2f) 344 .pClientMemoryIndexData (0.2f) 345 .pSeparateAttribBuffers (0.4f) 346 .pUseDrawArrays (0.4f) 347 .pRandomBufferUploadTarget (1.0f) 348 .pRandomBufferUsage (1.0f), 349 GL_STATIC_DRAW, GL_STATIC_DRAW)); 350 } 351 } 352 } 353 } 354 355 } // Stress 356 } // gles3 357 } // deqp 358