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 Vertex array and buffer unaligned access stress tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es2sVertexArrayTests.hpp"
25 #include "glsVertexArrayTests.hpp"
26 
27 #include "glwEnums.hpp"
28 
29 using namespace deqp::gls;
30 
31 namespace deqp
32 {
33 namespace gles2
34 {
35 namespace Stress
36 {
37 namespace
38 {
39 
40 template<class T>
typeToString(T t)41 static std::string typeToString (T t)
42 {
43 	std::stringstream strm;
44 	strm << t;
45 	return strm.str();
46 }
47 
48 class SingleVertexArrayUsageTests : public TestCaseGroup
49 {
50 public:
51 									SingleVertexArrayUsageTests		(Context& context);
52 	virtual							~SingleVertexArrayUsageTests	(void);
53 
54 	virtual void					init							(void);
55 
56 private:
57 									SingleVertexArrayUsageTests		(const SingleVertexArrayUsageTests& other);
58 	SingleVertexArrayUsageTests&	operator=						(const SingleVertexArrayUsageTests& other);
59 };
60 
SingleVertexArrayUsageTests(Context & context)61 SingleVertexArrayUsageTests::SingleVertexArrayUsageTests (Context& context)
62 	: TestCaseGroup(context, "usages", "Single vertex atribute, usage")
63 {
64 }
65 
~SingleVertexArrayUsageTests(void)66 SingleVertexArrayUsageTests::~SingleVertexArrayUsageTests (void)
67 {
68 }
69 
init(void)70 void SingleVertexArrayUsageTests::init (void)
71 {
72 	// Test usage
73 	Array::Usage		usages[]		= {Array::USAGE_STATIC_DRAW, Array::USAGE_STREAM_DRAW, Array::USAGE_DYNAMIC_DRAW};
74 	int					counts[]		= {1, 256};
75 	int					strides[]		= {17};
76 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE};
77 
78 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
79 	{
80 		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
81 		{
82 			for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
83 			{
84 				for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++)
85 				{
86 					const int	componentCount	= 2;
87 					const int	stride			= (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * componentCount : strides[strideNdx]);
88 					const bool	aligned			= (stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0;
89 					MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
90 																	Array::OUTPUTTYPE_VEC2,
91 																	Array::STORAGE_BUFFER,
92 																	usages[usageNdx],
93 																	componentCount,
94 																	0,
95 																	stride,
96 																	false,
97 																	GLValue::getMinValue(inputTypes[inputTypeNdx]),
98 																	GLValue::getMaxValue(inputTypes[inputTypeNdx]));
99 
100 					MultiVertexArrayTest::Spec spec;
101 					spec.primitive	= Array::PRIMITIVE_TRIANGLES;
102 					spec.drawCount	= counts[countNdx];
103 					spec.first		= 0;
104 					spec.arrays.push_back(arraySpec);
105 
106 					std::string name = spec.getName();
107 
108 					if (!aligned)
109 						addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
110 				}
111 			}
112 		}
113 	}
114 }
115 
116 class SingleVertexArrayStrideTests : public TestCaseGroup
117 {
118 public:
119 									SingleVertexArrayStrideTests	(Context& context);
120 	virtual							~SingleVertexArrayStrideTests	(void);
121 
122 	virtual void					init							(void);
123 
124 private:
125 									SingleVertexArrayStrideTests	(const SingleVertexArrayStrideTests& other);
126 	SingleVertexArrayStrideTests&	operator=						(const SingleVertexArrayStrideTests& other);
127 };
128 
SingleVertexArrayStrideTests(Context & context)129 SingleVertexArrayStrideTests::SingleVertexArrayStrideTests (Context& context)
130 	: TestCaseGroup(context, "strides", "Single stride vertex atribute")
131 {
132 }
133 
~SingleVertexArrayStrideTests(void)134 SingleVertexArrayStrideTests::~SingleVertexArrayStrideTests (void)
135 {
136 }
137 
init(void)138 void SingleVertexArrayStrideTests::init (void)
139 {
140 	// Test strides with different input types, component counts and storage, Usage(?)
141 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE, /*Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE,*/ Array::INPUTTYPE_FIXED};
142 	Array::Storage		storages[]		= {Array::STORAGE_BUFFER};
143 	int					counts[]		= {1, 256};
144 	int					strides[]		= {17};
145 
146 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
147 	{
148 		for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
149 		{
150 			for (int componentCount = 2; componentCount < 5; componentCount++)
151 			{
152 				for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
153 				{
154 					for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
155 					{
156 						const int	stride			= (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * componentCount : strides[strideNdx]);
157 						const bool	bufferUnaligned	= (storages[storageNdx] == Array::STORAGE_BUFFER) && (stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) != 0;
158 
159 						MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
160 																		Array::OUTPUTTYPE_VEC4,
161 																		storages[storageNdx],
162 																		Array::USAGE_DYNAMIC_DRAW,
163 																		componentCount,
164 																		0,
165 																		stride,
166 																		false,
167 																		GLValue::getMinValue(inputTypes[inputTypeNdx]),
168 																		GLValue::getMaxValue(inputTypes[inputTypeNdx]));
169 
170 						MultiVertexArrayTest::Spec spec;
171 						spec.primitive	= Array::PRIMITIVE_TRIANGLES;
172 						spec.drawCount	= counts[countNdx];
173 						spec.first		= 0;
174 						spec.arrays.push_back(arraySpec);
175 
176 						std::string name = spec.getName();
177 						if (bufferUnaligned)
178 							addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
179 					}
180 				}
181 			}
182 		}
183 	}
184 }
185 
186 class SingleVertexArrayFirstTests : public TestCaseGroup
187 {
188 public:
189 									SingleVertexArrayFirstTests	(Context& context);
190 	virtual							~SingleVertexArrayFirstTests	(void);
191 
192 	virtual void					init							(void);
193 
194 private:
195 									SingleVertexArrayFirstTests	(const SingleVertexArrayFirstTests& other);
196 	SingleVertexArrayFirstTests&	operator=						(const SingleVertexArrayFirstTests& other);
197 };
198 
SingleVertexArrayFirstTests(Context & context)199 SingleVertexArrayFirstTests::SingleVertexArrayFirstTests (Context& context)
200 	: TestCaseGroup(context, "first", "Single vertex atribute different first values")
201 {
202 }
203 
~SingleVertexArrayFirstTests(void)204 SingleVertexArrayFirstTests::~SingleVertexArrayFirstTests (void)
205 {
206 }
207 
init(void)208 void SingleVertexArrayFirstTests::init (void)
209 {
210 	// Test strides with different input types, component counts and storage, Usage(?)
211 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_FIXED};
212 	int					counts[]		= {5, 256};
213 	int					firsts[]		= {6, 24};
214 	int					offsets[]		= {1, 17};
215 	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
216 
217 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
218 	{
219 		for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
220 		{
221 			for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
222 			{
223 				for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
224 				{
225 					for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); firstNdx++)
226 					{
227 						const int	stride	= (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]);
228 						const bool	aligned	= ((stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0) && (offsets[offsetNdx] % Array::inputTypeSize(inputTypes[inputTypeNdx]) == 0);
229 
230 						MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
231 																		Array::OUTPUTTYPE_VEC2,
232 																		Array::STORAGE_BUFFER,
233 																		Array::USAGE_DYNAMIC_DRAW,
234 																		2,
235 																		offsets[offsetNdx],
236 																		stride,
237 																		false,
238 																		GLValue::getMinValue(inputTypes[inputTypeNdx]),
239 																		GLValue::getMaxValue(inputTypes[inputTypeNdx]));
240 
241 						MultiVertexArrayTest::Spec spec;
242 						spec.primitive	= Array::PRIMITIVE_TRIANGLES;
243 						spec.drawCount	= counts[countNdx];
244 						spec.first		= firsts[firstNdx];
245 						spec.arrays.push_back(arraySpec);
246 
247 						std::string name = Array::inputTypeToString(inputTypes[inputTypeNdx]) + "_first" + typeToString(firsts[firstNdx]) + "_offset" + typeToString(offsets[offsetNdx]) + "_stride" + typeToString(stride) + "_quads" + typeToString(counts[countNdx]);
248 						if (!aligned)
249 							addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
250 					}
251 				}
252 			}
253 		}
254 	}
255 }
256 
257 class SingleVertexArrayOffsetTests : public TestCaseGroup
258 {
259 public:
260 									SingleVertexArrayOffsetTests	(Context& context);
261 	virtual							~SingleVertexArrayOffsetTests	(void);
262 
263 	virtual void					init							(void);
264 
265 private:
266 									SingleVertexArrayOffsetTests	(const SingleVertexArrayOffsetTests& other);
267 	SingleVertexArrayOffsetTests&	operator=						(const SingleVertexArrayOffsetTests& other);
268 };
269 
SingleVertexArrayOffsetTests(Context & context)270 SingleVertexArrayOffsetTests::SingleVertexArrayOffsetTests (Context& context)
271 	: TestCaseGroup(context, "offset", "Single vertex atribute offset element")
272 {
273 }
274 
~SingleVertexArrayOffsetTests(void)275 SingleVertexArrayOffsetTests::~SingleVertexArrayOffsetTests (void)
276 {
277 }
278 
init(void)279 void SingleVertexArrayOffsetTests::init (void)
280 {
281 	// Test strides with different input types, component counts and storage, Usage(?)
282 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_FIXED};
283 	int					counts[]		= {1, 256};
284 	int					offsets[]		= {1, 4, 17, 32};
285 	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
286 
287 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
288 	{
289 		for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
290 		{
291 			for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
292 			{
293 				for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
294 				{
295 					const int	stride	= (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]);
296 					const bool	aligned	= ((stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0) && ((offsets[offsetNdx] % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0);
297 
298 					MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
299 																	Array::OUTPUTTYPE_VEC2,
300 																	Array::STORAGE_BUFFER,
301 																	Array::USAGE_DYNAMIC_DRAW,
302 																	2,
303 																	offsets[offsetNdx],
304 																	stride,
305 																	false,
306 																	GLValue::getMinValue(inputTypes[inputTypeNdx]),
307 																	GLValue::getMaxValue(inputTypes[inputTypeNdx]));
308 
309 					MultiVertexArrayTest::Spec spec;
310 					spec.primitive	= Array::PRIMITIVE_TRIANGLES;
311 					spec.drawCount	= counts[countNdx];
312 					spec.first		= 0;
313 					spec.arrays.push_back(arraySpec);
314 
315 					std::string name = spec.getName();
316 					if (!aligned)
317 						addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
318 				}
319 			}
320 		}
321 	}
322 }
323 
324 } // anonymous
325 
VertexArrayTests(Context & context)326 VertexArrayTests::VertexArrayTests (Context& context)
327 	: TestCaseGroup(context, "vertex_arrays", "Vertex array and array tests")
328 {
329 }
330 
~VertexArrayTests(void)331 VertexArrayTests::~VertexArrayTests (void)
332 {
333 }
334 
init(void)335 void VertexArrayTests::init (void)
336 {
337 	tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "single_attribute", "Single attribute");
338 	addChild(group);
339 
340 	// .single_attribute
341 	{
342 		group->addChild(new SingleVertexArrayStrideTests(m_context));
343 		group->addChild(new SingleVertexArrayUsageTests(m_context));
344 		group->addChild(new SingleVertexArrayOffsetTests(m_context));
345 		group->addChild(new SingleVertexArrayFirstTests(m_context));
346 	}
347 }
348 
349 } // Stress
350 } // gles2
351 } // deqp
352