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