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