1#ifndef _GLSLONGSTRESSCASE_HPP
2#define _GLSLONGSTRESSCASE_HPP
3/*-------------------------------------------------------------------------
4 * drawElements Quality Program OpenGL (ES) Module
5 * -----------------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Parametrized, long-running stress case.
24 *//*--------------------------------------------------------------------*/
25
26#include "tcuDefs.hpp"
27#include "tcuTestCase.hpp"
28#include "tcuTexture.hpp"
29#include "tcuMatrix.hpp"
30#include "gluRenderContext.hpp"
31#include "gluShaderUtil.hpp"
32#include "glsTextureTestUtil.hpp"
33#include "deRandom.hpp"
34#include "deSharedPtr.hpp"
35
36#include <string>
37#include <vector>
38#include <map>
39
40namespace deqp
41{
42namespace gls
43{
44
45namespace LongStressCaseInternal
46{
47
48template <typename T> class GLObjectManager;
49class Program;
50class Buffer;
51class Texture;
52class DebugInfoRenderer;
53
54}
55
56struct VarSpec
57{
58	union Value
59	{
60		float	f[4*4]; // \note Matrices are stored in column major order.
61		int		i[4];
62	};
63
64	std::string		name;
65	glu::DataType	type;
66	Value			minValue;
67	Value			maxValue;
68
69	template <typename T>
70	VarSpec (const std::string& name_, const T& minValue_, const T& maxValue_)	: name(name_) { set(minValue_, maxValue_); }
71
72	template <typename T>
73	VarSpec (const std::string& name_, const T& value)							: name(name_) { set(value, value); }
74
75	void set (float minValue_, float maxValue_)
76	{
77		type			= glu::TYPE_FLOAT;
78		minValue.f[0]	= minValue_;
79		maxValue.f[0]	= maxValue_;
80	}
81
82	template <int ValSize>
83	void set (const tcu::Vector<float, ValSize>& minValue_, const tcu::Vector<float, ValSize>& maxValue_)
84	{
85		type = glu::getDataTypeFloatVec(ValSize);
86		vecToArr(minValue_, minValue.f);
87		vecToArr(maxValue_, maxValue.f);
88	}
89
90	template <int ValRows, int ValCols>
91	void set (const tcu::Matrix<float, ValRows, ValCols>& minValue_, const tcu::Matrix<float, ValRows, ValCols>& maxValue_)
92	{
93		type = glu::getDataTypeMatrix(ValCols, ValRows);
94		matToArr(minValue_, minValue.f);
95		matToArr(maxValue_, maxValue.f);
96	}
97
98	void set (int minValue_, int maxValue_)
99	{
100		type			= glu::TYPE_INT;
101		minValue.i[0]	= minValue_;
102		maxValue.i[0]	= maxValue_;
103	}
104
105	template <int ValSize>
106	void set (const tcu::Vector<int, ValSize>& minValue_, const tcu::Vector<int, ValSize>& maxValue_)
107	{
108		type = glu::getDataTypeVector(glu::TYPE_INT, ValSize);
109		vecToArr(minValue_, minValue.i);
110		vecToArr(maxValue_, maxValue.i);
111	}
112
113private:
114	template <typename T, int SrcSize, int DstSize>
115	static inline void vecToArr (const tcu::Vector<T, SrcSize>& src, T (&dst)[DstSize])
116	{
117		DE_STATIC_ASSERT(DstSize >= SrcSize);
118		for (int i = 0; i < SrcSize; i++)
119			dst[i] = src[i];
120	}
121
122	template <int ValRows, int ValCols, int DstSize>
123	static inline void matToArr (const tcu::Matrix<float, ValRows, ValCols>& src, float (&dst)[DstSize])
124	{
125		DE_STATIC_ASSERT(DstSize >= ValRows*ValCols);
126		tcu::Array<float, ValRows*ValCols> data = src.getColumnMajorData();
127		for (int i = 0; i < ValRows*ValCols; i++)
128			dst[i] = data[i];
129	}
130};
131
132struct TextureSpec
133{
134	gls::TextureTestUtil::TextureType	textureType;
135	deUint32							textureUnit;
136	int									width;
137	int									height;
138	deUint32							format;
139	deUint32							dataType;
140	deUint32							internalFormat;
141	bool								useMipmap;
142	deUint32							minFilter;
143	deUint32							magFilter;
144	deUint32							sWrap;
145	deUint32							tWrap;
146	tcu::Vec4							minValue;
147	tcu::Vec4							maxValue;
148
149	TextureSpec (const gls::TextureTestUtil::TextureType	texType,
150				 const deUint32								unit,
151				 const int									width_,
152				 const int									height_,
153				 const deUint32								format_,
154				 const deUint32								dataType_,
155				 const deUint32								internalFormat_,
156				 const bool									useMipmap_,
157				 const deUint32								minFilter_,
158				 const deUint32								magFilter_,
159				 const deUint32								sWrap_,
160				 const deUint32								tWrap_,
161				 const tcu::Vec4&							minValue_,
162				 const tcu::Vec4&							maxValue_)
163		: textureType		(texType)
164		, textureUnit		(unit)
165		, width				(width_)
166		, height			(height_)
167		, format			(format_)
168		, dataType			(dataType_)
169		, internalFormat	(internalFormat_)
170		, useMipmap			(useMipmap_)
171		, minFilter			(minFilter_)
172		, magFilter			(magFilter_)
173		, sWrap				(sWrap_)
174		, tWrap				(tWrap_)
175		, minValue			(minValue_)
176		, maxValue			(maxValue_)
177	{
178	}
179};
180
181/*--------------------------------------------------------------------*//*!
182 * \brief Struct for a shader program sources and related data
183 *
184 * A ProgramContext holds a program's vertex and fragment shader sources
185 * as well as specifications of its attributes, uniforms, and textures.
186 * When given to a StressCase, the string ${NS} is replaced by a magic
187 * number that varies between different compilations of the same program;
188 * the same replacement is done in attributes' and uniforms' names. This
189 * can be used to avoid shader caching by the GL, by e.g. suffixing each
190 * attribute, uniform and varying name with ${NS} in the shader source.
191 *//*--------------------------------------------------------------------*/
192struct ProgramContext
193{
194	std::string							vertexSource;
195	std::string							fragmentSource;
196	std::vector<VarSpec>				attributes;
197	std::vector<VarSpec>				uniforms;
198
199	std::vector<TextureSpec>			textureSpecs;		//!< \note If multiple textures have same unit, one of them is picked randomly.
200
201	std::string							positionAttrName;	//!< \note Position attribute may get a bit more careful handling than just complete random.
202
203	ProgramContext (const char* const vtxShaderSource_,
204					const char* const fragShaderSource_,
205					const char* const positionAttrName_)
206		: vertexSource		(vtxShaderSource_)
207		, fragmentSource	(fragShaderSource_)
208		, positionAttrName	(positionAttrName_)
209	{
210	}
211};
212
213class LongStressCase : public tcu::TestCase
214{
215public:
216	//! Probabilities for actions that may be taken on each iteration. \note The texture and buffer specific actions are randomized per texture or buffer.
217	struct FeatureProbabilities
218	{
219		float rebuildProgram;				//!< Rebuild program, with variable name-mangling.
220		float reuploadTexture;				//!< Reupload texture, even if it already exists and has been uploaded.
221		float reuploadBuffer;				//!< Reupload buffer, even if it already exists and has been uploaded.
222		float reuploadWithTexImage;			//!< Use glTexImage*() when re-uploading texture, not glTexSubImage*().
223		float reuploadWithBufferData;		//!< Use glBufferData() when re-uploading buffer, not glBufferSubData().
224		float deleteTexture;				//!< Delete texture at end of iteration, even if we could re-use it.
225		float deleteBuffer;					//!< Delete buffer at end of iteration, even if we could re-use it.
226		float wastefulTextureMemoryUsage;	//!< Don't re-use a texture, and don't delete it until given memory limit is hit.
227		float wastefulBufferMemoryUsage;	//!< Don't re-use a buffer, and don't delete it until given memory limit is hit.
228		float clientMemoryAttributeData;	//!< Use client memory for vertex attribute data when drawing (instead of GL buffers).
229		float clientMemoryIndexData;		//!< Use client memory for vertex indices when drawing (instead of GL buffers).
230		float randomBufferUploadTarget;		//!< Use a random target when setting buffer data (i.e. not necessarily the one it'll be ultimately bound to).
231		float randomBufferUsage;			//!< Use a random buffer usage parameter with glBufferData(), instead of the ones specified as params for the case.
232		float useDrawArrays;				//!< Use glDrawArrays() instead of glDrawElements().
233		float separateAttributeBuffers;		//!< Give each vertex attribute its own buffer.
234
235		// Named parameter idiom: helpers that can be used when making temporaries, e.g. FeatureProbabilities().pReuploadTexture(1.0f).pReuploadWithTexImage(1.0f)
236		FeatureProbabilities& pRebuildProgram				(const float prob) { rebuildProgram					= prob; return *this; }
237		FeatureProbabilities& pReuploadTexture				(const float prob) { reuploadTexture				= prob; return *this; }
238		FeatureProbabilities& pReuploadBuffer				(const float prob) { reuploadBuffer					= prob; return *this; }
239		FeatureProbabilities& pReuploadWithTexImage			(const float prob) { reuploadWithTexImage			= prob; return *this; }
240		FeatureProbabilities& pReuploadWithBufferData		(const float prob) { reuploadWithBufferData			= prob; return *this; }
241		FeatureProbabilities& pDeleteTexture				(const float prob) { deleteTexture					= prob; return *this; }
242		FeatureProbabilities& pDeleteBuffer					(const float prob) { deleteBuffer					= prob; return *this; }
243		FeatureProbabilities& pWastefulTextureMemoryUsage	(const float prob) { wastefulTextureMemoryUsage		= prob; return *this; }
244		FeatureProbabilities& pWastefulBufferMemoryUsage	(const float prob) { wastefulBufferMemoryUsage		= prob; return *this; }
245		FeatureProbabilities& pClientMemoryAttributeData	(const float prob) { clientMemoryAttributeData		= prob; return *this; }
246		FeatureProbabilities& pClientMemoryIndexData		(const float prob) { clientMemoryIndexData			= prob; return *this; }
247		FeatureProbabilities& pRandomBufferUploadTarget		(const float prob) { randomBufferUploadTarget		= prob; return *this; }
248		FeatureProbabilities& pRandomBufferUsage			(const float prob) { randomBufferUsage				= prob; return *this; }
249		FeatureProbabilities& pUseDrawArrays				(const float prob) { useDrawArrays					= prob; return *this; }
250		FeatureProbabilities& pSeparateAttribBuffers		(const float prob) { separateAttributeBuffers		= prob; return *this; }
251
252		FeatureProbabilities (void)
253			: rebuildProgram				(0.0f)
254			, reuploadTexture				(0.0f)
255			, reuploadBuffer				(0.0f)
256			, reuploadWithTexImage			(0.0f)
257			, reuploadWithBufferData		(0.0f)
258			, deleteTexture					(0.0f)
259			, deleteBuffer					(0.0f)
260			, wastefulTextureMemoryUsage	(0.0f)
261			, wastefulBufferMemoryUsage		(0.0f)
262			, clientMemoryAttributeData		(0.0f)
263			, clientMemoryIndexData			(0.0f)
264			, randomBufferUploadTarget		(0.0f)
265			, randomBufferUsage				(0.0f)
266			, useDrawArrays					(0.0f)
267			, separateAttributeBuffers		(0.0f)
268		{
269		}
270	};
271
272															LongStressCase						(tcu::TestContext&						testCtx,
273																								 const glu::RenderContext&				renderCtx,
274																								 const char*							name,
275																								 const char*							desc,
276																								 int									maxTexMemoryUsageBytes, //!< Approximate upper bound on GL texture memory usage.
277																								 int									maxBufMemoryUsageBytes, //!< Approximate upper bound on GL buffer memory usage.
278																								 int									numDrawCallsPerIteration,
279																								 int									numTrianglesPerDrawCall,
280																								 const std::vector<ProgramContext>&		programContexts,
281																								 const FeatureProbabilities&			probabilities,
282																								 deUint32								indexBufferUsage,
283																								 deUint32								attrBufferUsage,
284																								 int									redundantBufferFactor = 1,
285																								 bool									showDebugInfo = false);
286
287															~LongStressCase						(void);
288
289	void													init								(void);
290	void													deinit								(void);
291
292	IterateResult											iterate								(void);
293
294private:
295															LongStressCase						(const LongStressCase&);
296	LongStressCase&											operator=							(const LongStressCase&);
297
298	const glu::RenderContext&								m_renderCtx;
299	const int												m_maxTexMemoryUsageBytes;
300	const int												m_maxBufMemoryUsageBytes;
301	const int												m_numDrawCallsPerIteration;
302	const int												m_numTrianglesPerDrawCall;
303	const int												m_numVerticesPerDrawCall;
304	const std::vector<ProgramContext>						m_programContexts;
305	const FeatureProbabilities								m_probabilities;
306	const deUint32											m_indexBufferUsage;
307	const deUint32											m_attrBufferUsage;
308	const int												m_redundantBufferFactor; //!< By what factor we allocate redundant buffers. Default is 1, i.e. no redundancy.
309	const bool												m_showDebugInfo;
310
311	const int												m_numIterations;
312	const bool												m_isGLES3;
313
314	int														m_currentIteration;
315	deUint64												m_startTimeSeconds; //!< Set at beginning of first iteration.
316	deUint64												m_lastLogTime;
317	int														m_lastLogIteration;
318	int														m_currentLogEntryNdx;
319
320	de::Random												m_rnd;
321	LongStressCaseInternal::GLObjectManager<
322		LongStressCaseInternal::Program>*					m_programs;
323	LongStressCaseInternal::GLObjectManager<
324		LongStressCaseInternal::Buffer>*					m_buffers;
325	LongStressCaseInternal::GLObjectManager<
326		LongStressCaseInternal::Texture>*					m_textures;
327	std::vector<deUint16>									m_vertexIndices;
328
329	struct ProgramResources
330	{
331		std::vector<deUint8>							attrDataBuf;
332		std::vector<int>								attrDataOffsets;
333		std::vector<int>								attrDataSizes;
334		std::vector<de::SharedPtr<tcu::TextureLevel> >	dummyTextures;
335		std::string										shaderNameManglingSuffix;
336	};
337
338	std::vector<ProgramResources>							m_programResources;
339
340	LongStressCaseInternal::DebugInfoRenderer*				m_debugInfoRenderer;
341};
342
343
344} // gls
345} // deqp
346
347#endif // _GLSLONGSTRESSCASE_HPP
348