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