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
31using std::string;
32
33namespace deqp
34{
35namespace gles2
36{
37namespace Stress
38{
39
40LongRunningTests::LongRunningTests (Context& context)
41	: TestCaseGroup(context, "long", "Long-running stress tests")
42{
43}
44
45LongRunningTests::~LongRunningTests (void)
46{
47}
48
49void 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