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