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
29using namespace deqp::gls;
30
31namespace deqp
32{
33namespace gles2
34{
35namespace Stress
36{
37namespace
38{
39
40template<class T>
41static std::string typeToString (T t)
42{
43	std::stringstream strm;
44	strm << t;
45	return strm.str();
46}
47
48class SingleVertexArrayUsageTests : public TestCaseGroup
49{
50public:
51									SingleVertexArrayUsageTests		(Context& context);
52	virtual							~SingleVertexArrayUsageTests	(void);
53
54	virtual void					init							(void);
55
56private:
57									SingleVertexArrayUsageTests		(const SingleVertexArrayUsageTests& other);
58	SingleVertexArrayUsageTests&	operator=						(const SingleVertexArrayUsageTests& other);
59};
60
61SingleVertexArrayUsageTests::SingleVertexArrayUsageTests (Context& context)
62	: TestCaseGroup(context, "usages", "Single vertex atribute, usage")
63{
64}
65
66SingleVertexArrayUsageTests::~SingleVertexArrayUsageTests (void)
67{
68}
69
70void 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
116class SingleVertexArrayStrideTests : public TestCaseGroup
117{
118public:
119									SingleVertexArrayStrideTests	(Context& context);
120	virtual							~SingleVertexArrayStrideTests	(void);
121
122	virtual void					init							(void);
123
124private:
125									SingleVertexArrayStrideTests	(const SingleVertexArrayStrideTests& other);
126	SingleVertexArrayStrideTests&	operator=						(const SingleVertexArrayStrideTests& other);
127};
128
129SingleVertexArrayStrideTests::SingleVertexArrayStrideTests (Context& context)
130	: TestCaseGroup(context, "strides", "Single stride vertex atribute")
131{
132}
133
134SingleVertexArrayStrideTests::~SingleVertexArrayStrideTests (void)
135{
136}
137
138void 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
186class SingleVertexArrayFirstTests : public TestCaseGroup
187{
188public:
189									SingleVertexArrayFirstTests	(Context& context);
190	virtual							~SingleVertexArrayFirstTests	(void);
191
192	virtual void					init							(void);
193
194private:
195									SingleVertexArrayFirstTests	(const SingleVertexArrayFirstTests& other);
196	SingleVertexArrayFirstTests&	operator=						(const SingleVertexArrayFirstTests& other);
197};
198
199SingleVertexArrayFirstTests::SingleVertexArrayFirstTests (Context& context)
200	: TestCaseGroup(context, "first", "Single vertex atribute different first values")
201{
202}
203
204SingleVertexArrayFirstTests::~SingleVertexArrayFirstTests (void)
205{
206}
207
208void 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
257class SingleVertexArrayOffsetTests : public TestCaseGroup
258{
259public:
260									SingleVertexArrayOffsetTests	(Context& context);
261	virtual							~SingleVertexArrayOffsetTests	(void);
262
263	virtual void					init							(void);
264
265private:
266									SingleVertexArrayOffsetTests	(const SingleVertexArrayOffsetTests& other);
267	SingleVertexArrayOffsetTests&	operator=						(const SingleVertexArrayOffsetTests& other);
268};
269
270SingleVertexArrayOffsetTests::SingleVertexArrayOffsetTests (Context& context)
271	: TestCaseGroup(context, "offset", "Single vertex atribute offset element")
272{
273}
274
275SingleVertexArrayOffsetTests::~SingleVertexArrayOffsetTests (void)
276{
277}
278
279void 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
326VertexArrayTests::VertexArrayTests (Context& context)
327	: TestCaseGroup(context, "vertex_arrays", "Vertex array and array tests")
328{
329}
330
331VertexArrayTests::~VertexArrayTests (void)
332{
333}
334
335void 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