1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Long-running stress tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es2sLongRunningTests.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 gles2
36 {
37 namespace Stress
38 {
39
LongRunningTests(Context & context)40 LongRunningTests::LongRunningTests (Context& context)
41 : TestCaseGroup(context, "long", "Long-running stress tests")
42 {
43 }
44
~LongRunningTests(void)45 LongRunningTests::~LongRunningTests (void)
46 {
47 }
48
init(void)49 void LongRunningTests::init (void)
50 {
51 static const int Mi = 1<<20;
52 const gls::LongStressTestUtil::ProgramLibrary progLib (glu::GLSL_VERSION_100_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 } // gles2
357 } // deqp
358