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 
40 namespace deqp
41 {
42 namespace gls
43 {
44 
45 namespace LongStressCaseInternal
46 {
47 
48 template <typename T> class GLObjectManager;
49 class Program;
50 class Buffer;
51 class Texture;
52 class DebugInfoRenderer;
53 
54 }
55 
56 struct 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>
VarSpecdeqp::gls::VarSpec70 	VarSpec (const std::string& name_, const T& minValue_, const T& maxValue_)	: name(name_) { set(minValue_, maxValue_); }
71 
72 	template <typename T>
VarSpecdeqp::gls::VarSpec73 	VarSpec (const std::string& name_, const T& value)							: name(name_) { set(value, value); }
74 
setdeqp::gls::VarSpec75 	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>
setdeqp::gls::VarSpec83 	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>
setdeqp::gls::VarSpec91 	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 
setdeqp::gls::VarSpec98 	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>
setdeqp::gls::VarSpec106 	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 
113 private:
114 	template <typename T, int SrcSize, int DstSize>
vecToArrdeqp::gls::VarSpec115 	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>
matToArrdeqp::gls::VarSpec123 	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 
132 struct 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 
TextureSpecdeqp::gls::TextureSpec149 	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  *//*--------------------------------------------------------------------*/
192 struct 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 
ProgramContextdeqp::gls::ProgramContext203 	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 
213 class LongStressCase : public tcu::TestCase
214 {
215 public:
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)
pRebuildProgramdeqp::gls::LongStressCase::FeatureProbabilities236 		FeatureProbabilities& pRebuildProgram				(const float prob) { rebuildProgram					= prob; return *this; }
pReuploadTexturedeqp::gls::LongStressCase::FeatureProbabilities237 		FeatureProbabilities& pReuploadTexture				(const float prob) { reuploadTexture				= prob; return *this; }
pReuploadBufferdeqp::gls::LongStressCase::FeatureProbabilities238 		FeatureProbabilities& pReuploadBuffer				(const float prob) { reuploadBuffer					= prob; return *this; }
pReuploadWithTexImagedeqp::gls::LongStressCase::FeatureProbabilities239 		FeatureProbabilities& pReuploadWithTexImage			(const float prob) { reuploadWithTexImage			= prob; return *this; }
pReuploadWithBufferDatadeqp::gls::LongStressCase::FeatureProbabilities240 		FeatureProbabilities& pReuploadWithBufferData		(const float prob) { reuploadWithBufferData			= prob; return *this; }
pDeleteTexturedeqp::gls::LongStressCase::FeatureProbabilities241 		FeatureProbabilities& pDeleteTexture				(const float prob) { deleteTexture					= prob; return *this; }
pDeleteBufferdeqp::gls::LongStressCase::FeatureProbabilities242 		FeatureProbabilities& pDeleteBuffer					(const float prob) { deleteBuffer					= prob; return *this; }
pWastefulTextureMemoryUsagedeqp::gls::LongStressCase::FeatureProbabilities243 		FeatureProbabilities& pWastefulTextureMemoryUsage	(const float prob) { wastefulTextureMemoryUsage		= prob; return *this; }
pWastefulBufferMemoryUsagedeqp::gls::LongStressCase::FeatureProbabilities244 		FeatureProbabilities& pWastefulBufferMemoryUsage	(const float prob) { wastefulBufferMemoryUsage		= prob; return *this; }
pClientMemoryAttributeDatadeqp::gls::LongStressCase::FeatureProbabilities245 		FeatureProbabilities& pClientMemoryAttributeData	(const float prob) { clientMemoryAttributeData		= prob; return *this; }
pClientMemoryIndexDatadeqp::gls::LongStressCase::FeatureProbabilities246 		FeatureProbabilities& pClientMemoryIndexData		(const float prob) { clientMemoryIndexData			= prob; return *this; }
pRandomBufferUploadTargetdeqp::gls::LongStressCase::FeatureProbabilities247 		FeatureProbabilities& pRandomBufferUploadTarget		(const float prob) { randomBufferUploadTarget		= prob; return *this; }
pRandomBufferUsagedeqp::gls::LongStressCase::FeatureProbabilities248 		FeatureProbabilities& pRandomBufferUsage			(const float prob) { randomBufferUsage				= prob; return *this; }
pUseDrawArraysdeqp::gls::LongStressCase::FeatureProbabilities249 		FeatureProbabilities& pUseDrawArrays				(const float prob) { useDrawArrays					= prob; return *this; }
pSeparateAttribBuffersdeqp::gls::LongStressCase::FeatureProbabilities250 		FeatureProbabilities& pSeparateAttribBuffers		(const float prob) { separateAttributeBuffers		= prob; return *this; }
251 
FeatureProbabilitiesdeqp::gls::LongStressCase::FeatureProbabilities252 		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 
294 private:
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