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
29using namespace deqp::gls;
30
31namespace deqp
32{
33namespace gles3
34{
35namespace Stress
36{
37namespace
38{
39
40
41class SingleVertexArrayUsageGroup : public TestCaseGroup
42{
43public:
44									SingleVertexArrayUsageGroup		(Context& context, Array::Usage usage);
45	virtual							~SingleVertexArrayUsageGroup	(void);
46
47	virtual void					init							(void);
48
49private:
50									SingleVertexArrayUsageGroup		(const SingleVertexArrayUsageGroup& other);
51	SingleVertexArrayUsageGroup&	operator=						(const SingleVertexArrayUsageGroup& other);
52
53	Array::Usage					m_usage;
54};
55
56SingleVertexArrayUsageGroup::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
62SingleVertexArrayUsageGroup::~SingleVertexArrayUsageGroup (void)
63{
64}
65
66template<class T>
67static std::string typeToString (T t)
68{
69	std::stringstream strm;
70	strm << t;
71	return strm.str();
72}
73
74void 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
114class SingleVertexArrayUsageTests : public TestCaseGroup
115{
116public:
117									SingleVertexArrayUsageTests		(Context& context);
118	virtual							~SingleVertexArrayUsageTests	(void);
119
120	virtual void					init							(void);
121
122private:
123									SingleVertexArrayUsageTests		(const SingleVertexArrayUsageTests& other);
124	SingleVertexArrayUsageTests&	operator=						(const SingleVertexArrayUsageTests& other);
125};
126
127SingleVertexArrayUsageTests::SingleVertexArrayUsageTests (Context& context)
128	: TestCaseGroup(context, "usages", "Single vertex atribute, usage")
129{
130}
131
132SingleVertexArrayUsageTests::~SingleVertexArrayUsageTests (void)
133{
134}
135
136void 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
146class SingleVertexArrayStrideGroup : public TestCaseGroup
147{
148public:
149									SingleVertexArrayStrideGroup	(Context& context, Array::InputType type);
150	virtual							~SingleVertexArrayStrideGroup	(void);
151
152	virtual void					init							(void);
153
154private:
155									SingleVertexArrayStrideGroup	(const SingleVertexArrayStrideGroup& other);
156	SingleVertexArrayStrideGroup&	operator=						(const SingleVertexArrayStrideGroup& other);
157
158	Array::InputType				m_type;
159};
160
161SingleVertexArrayStrideGroup::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
167SingleVertexArrayStrideGroup::~SingleVertexArrayStrideGroup (void)
168{
169}
170
171void 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
220class SingleVertexArrayStrideTests : public TestCaseGroup
221{
222public:
223									SingleVertexArrayStrideTests	(Context& context);
224	virtual							~SingleVertexArrayStrideTests	(void);
225
226	virtual void					init							(void);
227
228private:
229									SingleVertexArrayStrideTests	(const SingleVertexArrayStrideTests& other);
230	SingleVertexArrayStrideTests&	operator=						(const SingleVertexArrayStrideTests& other);
231};
232
233SingleVertexArrayStrideTests::SingleVertexArrayStrideTests (Context& context)
234	: TestCaseGroup(context, "strides", "Single stride vertex atribute")
235{
236}
237
238SingleVertexArrayStrideTests::~SingleVertexArrayStrideTests (void)
239{
240}
241
242void 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
252class SingleVertexArrayFirstGroup : public TestCaseGroup
253{
254public:
255									SingleVertexArrayFirstGroup	(Context& context, Array::InputType type);
256	virtual							~SingleVertexArrayFirstGroup	(void);
257
258	virtual void					init							(void);
259
260private:
261									SingleVertexArrayFirstGroup	(const SingleVertexArrayFirstGroup& other);
262	SingleVertexArrayFirstGroup&	operator=						(const SingleVertexArrayFirstGroup& other);
263	Array::InputType				m_type;
264};
265
266SingleVertexArrayFirstGroup::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
272SingleVertexArrayFirstGroup::~SingleVertexArrayFirstGroup (void)
273{
274}
275
276void 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
323class SingleVertexArrayFirstTests : public TestCaseGroup
324{
325public:
326									SingleVertexArrayFirstTests	(Context& context);
327	virtual							~SingleVertexArrayFirstTests	(void);
328
329	virtual void					init							(void);
330
331private:
332									SingleVertexArrayFirstTests	(const SingleVertexArrayFirstTests& other);
333	SingleVertexArrayFirstTests&	operator=						(const SingleVertexArrayFirstTests& other);
334};
335
336SingleVertexArrayFirstTests::SingleVertexArrayFirstTests (Context& context)
337	: TestCaseGroup(context, "first", "Single vertex attribute, different first values to drawArrays")
338{
339}
340
341SingleVertexArrayFirstTests::~SingleVertexArrayFirstTests (void)
342{
343}
344
345void 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
356class SingleVertexArrayOffsetGroup : public TestCaseGroup
357{
358public:
359									SingleVertexArrayOffsetGroup	(Context& context, Array::InputType type);
360	virtual							~SingleVertexArrayOffsetGroup	(void);
361
362	virtual void					init							(void);
363
364private:
365									SingleVertexArrayOffsetGroup	(const SingleVertexArrayOffsetGroup& other);
366	SingleVertexArrayOffsetGroup&	operator=						(const SingleVertexArrayOffsetGroup& other);
367	Array::InputType				m_type;
368};
369
370SingleVertexArrayOffsetGroup::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
376SingleVertexArrayOffsetGroup::~SingleVertexArrayOffsetGroup (void)
377{
378}
379
380void 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
423class SingleVertexArrayOffsetTests : public TestCaseGroup
424{
425public:
426									SingleVertexArrayOffsetTests	(Context& context);
427	virtual							~SingleVertexArrayOffsetTests	(void);
428
429	virtual void					init							(void);
430
431private:
432									SingleVertexArrayOffsetTests	(const SingleVertexArrayOffsetTests& other);
433	SingleVertexArrayOffsetTests&	operator=						(const SingleVertexArrayOffsetTests& other);
434};
435
436SingleVertexArrayOffsetTests::SingleVertexArrayOffsetTests (Context& context)
437	: TestCaseGroup(context, "offset", "Single vertex atribute offset element")
438{
439}
440
441SingleVertexArrayOffsetTests::~SingleVertexArrayOffsetTests (void)
442{
443}
444
445void 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
458VertexArrayTests::VertexArrayTests (Context& context)
459	: TestCaseGroup(context, "vertex_arrays", "Vertex array and array tests")
460{
461}
462
463VertexArrayTests::~VertexArrayTests (void)
464{
465}
466
467void 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