1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.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 "es3sVertexArrayTests.hpp"
25 #include "glsVertexArrayTests.hpp"
26 
27 #include <sstream>
28 
29 using namespace deqp::gls;
30 
31 namespace deqp
32 {
33 namespace gles3
34 {
35 namespace Stress
36 {
37 namespace
38 {
39 
40 
41 class SingleVertexArrayUsageGroup : public TestCaseGroup
42 {
43 public:
44 									SingleVertexArrayUsageGroup		(Context& context, Array::Usage usage);
45 	virtual							~SingleVertexArrayUsageGroup	(void);
46 
47 	virtual void					init							(void);
48 
49 private:
50 									SingleVertexArrayUsageGroup		(const SingleVertexArrayUsageGroup& other);
51 	SingleVertexArrayUsageGroup&	operator=						(const SingleVertexArrayUsageGroup& other);
52 
53 	Array::Usage					m_usage;
54 };
55 
SingleVertexArrayUsageGroup(Context & context,Array::Usage usage)56 SingleVertexArrayUsageGroup::SingleVertexArrayUsageGroup (Context& context, Array::Usage usage)
57 	: TestCaseGroup	(context, Array::usageTypeToString(usage).c_str(), Array::usageTypeToString(usage).c_str())
58 	, m_usage		(usage)
59 {
60 }
61 
~SingleVertexArrayUsageGroup(void)62 SingleVertexArrayUsageGroup::~SingleVertexArrayUsageGroup (void)
63 {
64 }
65 
66 template<class T>
typeToString(T t)67 static std::string typeToString (T t)
68 {
69 	std::stringstream strm;
70 	strm << t;
71 	return strm.str();
72 }
73 
init(void)74 void SingleVertexArrayUsageGroup::init (void)
75 {
76 	int					counts[]		= {1, 256};
77 	int					strides[]		= {0, -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
78 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE};
79 
80 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
81 	{
82 		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
83 		{
84 			for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
85 			{
86 				const int			stride	= (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]);
87 				const bool			aligned	= (stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0;
88 				const std::string	name	= "stride" + typeToString(stride) + "_" + Array::inputTypeToString(inputTypes[inputTypeNdx]) + "_quads" + typeToString(counts[countNdx]);
89 
90 				MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
91 																Array::OUTPUTTYPE_VEC2,
92 																Array::STORAGE_BUFFER,
93 																m_usage,
94 																2,
95 																0,
96 																stride,
97 																false,
98 																GLValue::getMinValue(inputTypes[inputTypeNdx]),
99 																GLValue::getMaxValue(inputTypes[inputTypeNdx]));
100 
101 				MultiVertexArrayTest::Spec spec;
102 				spec.primitive	= Array::PRIMITIVE_TRIANGLES;
103 				spec.drawCount	= counts[countNdx];
104 				spec.first		= 0;
105 				spec.arrays.push_back(arraySpec);
106 
107 				if (!aligned)
108 					addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
109 			}
110 		}
111 	}
112 }
113 
114 class SingleVertexArrayUsageTests : public TestCaseGroup
115 {
116 public:
117 									SingleVertexArrayUsageTests		(Context& context);
118 	virtual							~SingleVertexArrayUsageTests	(void);
119 
120 	virtual void					init							(void);
121 
122 private:
123 									SingleVertexArrayUsageTests		(const SingleVertexArrayUsageTests& other);
124 	SingleVertexArrayUsageTests&	operator=						(const SingleVertexArrayUsageTests& other);
125 };
126 
SingleVertexArrayUsageTests(Context & context)127 SingleVertexArrayUsageTests::SingleVertexArrayUsageTests (Context& context)
128 	: TestCaseGroup(context, "usages", "Single vertex atribute, usage")
129 {
130 }
131 
~SingleVertexArrayUsageTests(void)132 SingleVertexArrayUsageTests::~SingleVertexArrayUsageTests (void)
133 {
134 }
135 
init(void)136 void SingleVertexArrayUsageTests::init (void)
137 {
138 	// Test usage
139 	Array::Usage		usages[]		= { Array::USAGE_STATIC_DRAW, Array::USAGE_STREAM_DRAW, Array::USAGE_DYNAMIC_DRAW, Array::USAGE_STATIC_COPY, Array::USAGE_STREAM_COPY, Array::USAGE_DYNAMIC_COPY, Array::USAGE_STATIC_READ, Array::USAGE_STREAM_READ, Array::USAGE_DYNAMIC_READ };
140 	for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++)
141 	{
142 		addChild(new SingleVertexArrayUsageGroup(m_context, usages[usageNdx]));
143 	}
144 }
145 
146 class SingleVertexArrayStrideGroup : public TestCaseGroup
147 {
148 public:
149 									SingleVertexArrayStrideGroup	(Context& context, Array::InputType type);
150 	virtual							~SingleVertexArrayStrideGroup	(void);
151 
152 	virtual void					init							(void);
153 
154 private:
155 									SingleVertexArrayStrideGroup	(const SingleVertexArrayStrideGroup& other);
156 	SingleVertexArrayStrideGroup&	operator=						(const SingleVertexArrayStrideGroup& other);
157 
158 	Array::InputType				m_type;
159 };
160 
SingleVertexArrayStrideGroup(Context & context,Array::InputType type)161 SingleVertexArrayStrideGroup::SingleVertexArrayStrideGroup (Context& context, Array::InputType type)
162 	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
163 	, m_type		(type)
164 {
165 }
166 
~SingleVertexArrayStrideGroup(void)167 SingleVertexArrayStrideGroup::~SingleVertexArrayStrideGroup (void)
168 {
169 }
170 
init(void)171 void SingleVertexArrayStrideGroup::init (void)
172 {
173 	Array::Storage		storages[]		= {Array::STORAGE_USER, Array::STORAGE_BUFFER};
174 	int					counts[]		= {1, 256};
175 	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
176 
177 	for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
178 	{
179 		for (int componentCount = 2; componentCount < 5; componentCount++)
180 		{
181 			for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
182 			{
183 				for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
184 				{
185 					const bool	packed			= m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
186 					const int	stride			= (strides[strideNdx] < 0) ? ((packed) ? (16) : (Array::inputTypeSize(m_type) * componentCount)) : (strides[strideNdx]);
187 					const int	alignment		= (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
188 					const bool	bufferUnaligned	= (storages[storageNdx] == Array::STORAGE_BUFFER) && (stride % alignment) != 0;
189 
190 					std::string name = Array::storageToString(storages[storageNdx]) + "_stride" + typeToString(stride) + "_components" + typeToString(componentCount) + "_quads" + typeToString(counts[countNdx]);
191 
192 					if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && componentCount != 4)
193 						continue;
194 
195 					MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
196 																	Array::OUTPUTTYPE_VEC4,
197 																	storages[storageNdx],
198 																	Array::USAGE_DYNAMIC_DRAW,
199 																	componentCount,
200 																	0,
201 																	stride,
202 																	false,
203 																	GLValue::getMinValue(m_type),
204 																	GLValue::getMaxValue(m_type));
205 
206 					MultiVertexArrayTest::Spec spec;
207 					spec.primitive	= Array::PRIMITIVE_TRIANGLES;
208 					spec.drawCount	= counts[countNdx];
209 					spec.first		= 0;
210 					spec.arrays.push_back(arraySpec);
211 
212 					if (bufferUnaligned)
213 						addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
214 				}
215 			}
216 		}
217 	}
218 }
219 
220 class SingleVertexArrayStrideTests : public TestCaseGroup
221 {
222 public:
223 									SingleVertexArrayStrideTests	(Context& context);
224 	virtual							~SingleVertexArrayStrideTests	(void);
225 
226 	virtual void					init							(void);
227 
228 private:
229 									SingleVertexArrayStrideTests	(const SingleVertexArrayStrideTests& other);
230 	SingleVertexArrayStrideTests&	operator=						(const SingleVertexArrayStrideTests& other);
231 };
232 
SingleVertexArrayStrideTests(Context & context)233 SingleVertexArrayStrideTests::SingleVertexArrayStrideTests (Context& context)
234 	: TestCaseGroup(context, "strides", "Single stride vertex atribute")
235 {
236 }
237 
~SingleVertexArrayStrideTests(void)238 SingleVertexArrayStrideTests::~SingleVertexArrayStrideTests (void)
239 {
240 }
241 
init(void)242 void SingleVertexArrayStrideTests::init (void)
243 {
244 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, /*Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE,*/ Array::INPUTTYPE_FIXED, Array::INPUTTYPE_INT_2_10_10_10 };
245 
246 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
247 	{
248 		addChild(new SingleVertexArrayStrideGroup(m_context, inputTypes[inputTypeNdx]));
249 	}
250 }
251 
252 class SingleVertexArrayFirstGroup : public TestCaseGroup
253 {
254 public:
255 									SingleVertexArrayFirstGroup	(Context& context, Array::InputType type);
256 	virtual							~SingleVertexArrayFirstGroup	(void);
257 
258 	virtual void					init							(void);
259 
260 private:
261 									SingleVertexArrayFirstGroup	(const SingleVertexArrayFirstGroup& other);
262 	SingleVertexArrayFirstGroup&	operator=						(const SingleVertexArrayFirstGroup& other);
263 	Array::InputType				m_type;
264 };
265 
SingleVertexArrayFirstGroup(Context & context,Array::InputType type)266 SingleVertexArrayFirstGroup::SingleVertexArrayFirstGroup (Context& context, Array::InputType type)
267 	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
268 	, m_type		(type)
269 {
270 }
271 
~SingleVertexArrayFirstGroup(void)272 SingleVertexArrayFirstGroup::~SingleVertexArrayFirstGroup (void)
273 {
274 }
275 
init(void)276 void SingleVertexArrayFirstGroup::init (void)
277 {
278 	int					counts[]		= {5, 256};
279 	int					firsts[]		= {6, 24};
280 	int					offsets[]		= {1, 17};
281 	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
282 
283 	for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
284 	{
285 		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
286 		{
287 			for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
288 			{
289 				for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); firstNdx++)
290 				{
291 					const bool	packed			= m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
292 					const int	componentCount	= (packed) ? (4) : (2);
293 					const int	stride			= (strides[strideNdx] < 0) ? ((packed) ? (8) : (Array::inputTypeSize(m_type) * componentCount)) : (strides[strideNdx]);
294 					const int	alignment		= (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
295 					const bool	aligned			= ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0);
296 					std::string name			= "first" + typeToString(firsts[firstNdx]) + "_offset" + typeToString(offsets[offsetNdx]) + "_stride" + typeToString(stride) + "_quads" + typeToString(counts[countNdx]);
297 
298 					MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
299 																	Array::OUTPUTTYPE_VEC2,
300 																	Array::STORAGE_BUFFER,
301 																	Array::USAGE_DYNAMIC_DRAW,
302 																	componentCount,
303 																	offsets[offsetNdx],
304 																	stride,
305 																	false,
306 																	GLValue::getMinValue(m_type),
307 																	GLValue::getMaxValue(m_type));
308 
309 					MultiVertexArrayTest::Spec spec;
310 					spec.primitive	= Array::PRIMITIVE_TRIANGLES;
311 					spec.drawCount	= counts[countNdx];
312 					spec.first		= firsts[firstNdx];
313 					spec.arrays.push_back(arraySpec);
314 
315 					if (!aligned)
316 						addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
317 				}
318 			}
319 		}
320 	}
321 }
322 
323 class SingleVertexArrayFirstTests : public TestCaseGroup
324 {
325 public:
326 									SingleVertexArrayFirstTests	(Context& context);
327 	virtual							~SingleVertexArrayFirstTests	(void);
328 
329 	virtual void					init							(void);
330 
331 private:
332 									SingleVertexArrayFirstTests	(const SingleVertexArrayFirstTests& other);
333 	SingleVertexArrayFirstTests&	operator=						(const SingleVertexArrayFirstTests& other);
334 };
335 
SingleVertexArrayFirstTests(Context & context)336 SingleVertexArrayFirstTests::SingleVertexArrayFirstTests (Context& context)
337 	: TestCaseGroup(context, "first", "Single vertex attribute, different first values to drawArrays")
338 {
339 }
340 
~SingleVertexArrayFirstTests(void)341 SingleVertexArrayFirstTests::~SingleVertexArrayFirstTests (void)
342 {
343 }
344 
init(void)345 void SingleVertexArrayFirstTests::init (void)
346 {
347 	// Test offset with different input types, component counts and storage, Usage(?)
348 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_INT_2_10_10_10 };
349 
350 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
351 	{
352 		addChild(new SingleVertexArrayFirstGroup(m_context, inputTypes[inputTypeNdx]));
353 	}
354 }
355 
356 class SingleVertexArrayOffsetGroup : public TestCaseGroup
357 {
358 public:
359 									SingleVertexArrayOffsetGroup	(Context& context, Array::InputType type);
360 	virtual							~SingleVertexArrayOffsetGroup	(void);
361 
362 	virtual void					init							(void);
363 
364 private:
365 									SingleVertexArrayOffsetGroup	(const SingleVertexArrayOffsetGroup& other);
366 	SingleVertexArrayOffsetGroup&	operator=						(const SingleVertexArrayOffsetGroup& other);
367 	Array::InputType				m_type;
368 };
369 
SingleVertexArrayOffsetGroup(Context & context,Array::InputType type)370 SingleVertexArrayOffsetGroup::SingleVertexArrayOffsetGroup (Context& context, Array::InputType type)
371 	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
372 	, m_type		(type)
373 {
374 }
375 
~SingleVertexArrayOffsetGroup(void)376 SingleVertexArrayOffsetGroup::~SingleVertexArrayOffsetGroup (void)
377 {
378 }
379 
init(void)380 void SingleVertexArrayOffsetGroup::init (void)
381 {
382 	int					counts[]		= {1, 256};
383 	int					offsets[]		= {1, 4, 17, 32};
384 	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
385 
386 	for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
387 	{
388 		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
389 		{
390 			for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
391 			{
392 				const bool			packed			= m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
393 				const int			componentCount	= (packed) ? (4) : (2);
394 				const int			stride			= (strides[strideNdx] < 0 ? Array::inputTypeSize(m_type) * componentCount : strides[strideNdx]);
395 				const int			alignment		= (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
396 				const bool			aligned			= ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0);
397 				const std::string	name			= "offset" + typeToString(offsets[offsetNdx]) + "_stride" + typeToString(strides[strideNdx]) + "_quads" + typeToString(counts[countNdx]);
398 
399 				MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
400 																Array::OUTPUTTYPE_VEC2,
401 																Array::STORAGE_BUFFER,
402 																Array::USAGE_DYNAMIC_DRAW,
403 																componentCount,
404 																offsets[offsetNdx],
405 																stride,
406 																false,
407 																GLValue::getMinValue(m_type),
408 																GLValue::getMaxValue(m_type));
409 
410 				MultiVertexArrayTest::Spec spec;
411 				spec.primitive	= Array::PRIMITIVE_TRIANGLES;
412 				spec.drawCount	= counts[countNdx];
413 				spec.first		= 0;
414 				spec.arrays.push_back(arraySpec);
415 
416 				if (!aligned)
417 					addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
418 			}
419 		}
420 	}
421 }
422 
423 class SingleVertexArrayOffsetTests : public TestCaseGroup
424 {
425 public:
426 									SingleVertexArrayOffsetTests	(Context& context);
427 	virtual							~SingleVertexArrayOffsetTests	(void);
428 
429 	virtual void					init							(void);
430 
431 private:
432 									SingleVertexArrayOffsetTests	(const SingleVertexArrayOffsetTests& other);
433 	SingleVertexArrayOffsetTests&	operator=						(const SingleVertexArrayOffsetTests& other);
434 };
435 
SingleVertexArrayOffsetTests(Context & context)436 SingleVertexArrayOffsetTests::SingleVertexArrayOffsetTests (Context& context)
437 	: TestCaseGroup(context, "offset", "Single vertex atribute offset element")
438 {
439 }
440 
~SingleVertexArrayOffsetTests(void)441 SingleVertexArrayOffsetTests::~SingleVertexArrayOffsetTests (void)
442 {
443 }
444 
init(void)445 void SingleVertexArrayOffsetTests::init (void)
446 {
447 	// Test offset with different input types, component counts and storage, Usage(?)
448 	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_INT_2_10_10_10 };
449 
450 	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
451 	{
452 		addChild(new SingleVertexArrayOffsetGroup(m_context, inputTypes[inputTypeNdx]));
453 	}
454 }
455 
456 } // anonymous
457 
VertexArrayTests(Context & context)458 VertexArrayTests::VertexArrayTests (Context& context)
459 	: TestCaseGroup(context, "vertex_arrays", "Vertex array and array tests")
460 {
461 }
462 
~VertexArrayTests(void)463 VertexArrayTests::~VertexArrayTests (void)
464 {
465 }
466 
init(void)467 void VertexArrayTests::init (void)
468 {
469 	tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "single_attribute", "Single attribute");
470 	addChild(group);
471 
472 	// .single_attribute
473 	{
474 		group->addChild(new SingleVertexArrayStrideTests(m_context));
475 		group->addChild(new SingleVertexArrayUsageTests(m_context));
476 		group->addChild(new SingleVertexArrayOffsetTests(m_context));
477 		group->addChild(new SingleVertexArrayFirstTests(m_context));
478 	}
479 }
480 
481 } // Stress
482 } // gles3
483 } // deqp
484