xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fVertexArrayTest.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fVertexArrayTest.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 Functional
36 {
37 
38 class SingleVertexArrayUsageGroup : public TestCaseGroup
39 {
40 public:
41     SingleVertexArrayUsageGroup(Context &context, Array::Usage usage);
42     virtual ~SingleVertexArrayUsageGroup(void);
43 
44     virtual void init(void);
45 
46 private:
47     SingleVertexArrayUsageGroup(const SingleVertexArrayUsageGroup &other);
48     SingleVertexArrayUsageGroup &operator=(const SingleVertexArrayUsageGroup &other);
49 
50     Array::Usage m_usage;
51 };
52 
SingleVertexArrayUsageGroup(Context & context,Array::Usage usage)53 SingleVertexArrayUsageGroup::SingleVertexArrayUsageGroup(Context &context, Array::Usage usage)
54     : TestCaseGroup(context, Array::usageTypeToString(usage).c_str(), Array::usageTypeToString(usage).c_str())
55     , m_usage(usage)
56 {
57 }
58 
~SingleVertexArrayUsageGroup(void)59 SingleVertexArrayUsageGroup::~SingleVertexArrayUsageGroup(void)
60 {
61 }
62 
63 template <class T>
typeToString(T t)64 static std::string typeToString(T t)
65 {
66     std::stringstream strm;
67     strm << t;
68     return strm.str();
69 }
70 
init(void)71 void SingleVertexArrayUsageGroup::init(void)
72 {
73     int counts[]  = {1, 256};
74     int strides[] = {0, -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
75     Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_SHORT,
76                                      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                 const int stride =
85                     (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]);
86                 const bool aligned     = (stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0;
87                 const std::string name = "stride" + typeToString(stride) + "_" +
88                                          Array::inputTypeToString(inputTypes[inputTypeNdx]) + "_quads" +
89                                          typeToString(counts[countNdx]);
90 
91                 MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx], Array::OUTPUTTYPE_VEC2,
92                                                                 Array::STORAGE_BUFFER, m_usage, 2, 0, stride, false,
93                                                                 GLValue::getMinValue(inputTypes[inputTypeNdx]),
94                                                                 GLValue::getMaxValue(inputTypes[inputTypeNdx]));
95 
96                 MultiVertexArrayTest::Spec spec;
97                 spec.primitive = Array::PRIMITIVE_TRIANGLES;
98                 spec.drawCount = counts[countNdx];
99                 spec.first     = 0;
100                 spec.arrays.push_back(arraySpec);
101 
102                 if (aligned)
103                     addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(),
104                                                       name.c_str()));
105             }
106         }
107     }
108 }
109 
110 class SingleVertexArrayUsageTests : public TestCaseGroup
111 {
112 public:
113     SingleVertexArrayUsageTests(Context &context);
114     virtual ~SingleVertexArrayUsageTests(void);
115 
116     virtual void init(void);
117 
118 private:
119     SingleVertexArrayUsageTests(const SingleVertexArrayUsageTests &other);
120     SingleVertexArrayUsageTests &operator=(const SingleVertexArrayUsageTests &other);
121 };
122 
SingleVertexArrayUsageTests(Context & context)123 SingleVertexArrayUsageTests::SingleVertexArrayUsageTests(Context &context)
124     : TestCaseGroup(context, "usages", "Single vertex atribute, usage")
125 {
126 }
127 
~SingleVertexArrayUsageTests(void)128 SingleVertexArrayUsageTests::~SingleVertexArrayUsageTests(void)
129 {
130 }
131 
init(void)132 void SingleVertexArrayUsageTests::init(void)
133 {
134     // Test usage
135     Array::Usage usages[] = {Array::USAGE_STATIC_DRAW, Array::USAGE_STREAM_DRAW, Array::USAGE_DYNAMIC_DRAW,
136                              Array::USAGE_STATIC_COPY, Array::USAGE_STREAM_COPY, Array::USAGE_DYNAMIC_COPY,
137                              Array::USAGE_STATIC_READ, Array::USAGE_STREAM_READ, Array::USAGE_DYNAMIC_READ};
138     for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++)
139     {
140         addChild(new SingleVertexArrayUsageGroup(m_context, usages[usageNdx]));
141     }
142 }
143 
144 class SingleVertexArrayStrideGroup : public TestCaseGroup
145 {
146 public:
147     SingleVertexArrayStrideGroup(Context &context, Array::InputType type);
148     virtual ~SingleVertexArrayStrideGroup(void);
149 
150     virtual void init(void);
151 
152 private:
153     SingleVertexArrayStrideGroup(const SingleVertexArrayStrideGroup &other);
154     SingleVertexArrayStrideGroup &operator=(const SingleVertexArrayStrideGroup &other);
155 
156     Array::InputType m_type;
157 };
158 
SingleVertexArrayStrideGroup(Context & context,Array::InputType type)159 SingleVertexArrayStrideGroup::SingleVertexArrayStrideGroup(Context &context, Array::InputType type)
160     : TestCaseGroup(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
161     , m_type(type)
162 {
163 }
164 
~SingleVertexArrayStrideGroup(void)165 SingleVertexArrayStrideGroup::~SingleVertexArrayStrideGroup(void)
166 {
167 }
168 
init(void)169 void SingleVertexArrayStrideGroup::init(void)
170 {
171     Array::Storage storages[] = {Array::STORAGE_USER, Array::STORAGE_BUFFER};
172     int counts[]              = {1, 256};
173     int strides[] = {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
174 
175     for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
176     {
177         for (int componentCount = 2; componentCount < 5; componentCount++)
178         {
179             for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
180             {
181                 for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
182                 {
183                     const bool packed =
184                         m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
185                     const int stride = (strides[strideNdx] < 0) ?
186                                            ((packed) ? (16) : (Array::inputTypeSize(m_type) * componentCount)) :
187                                            (strides[strideNdx]);
188                     const int alignment =
189                         (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
190                     const bool bufferUnaligned =
191                         (storages[storageNdx] == Array::STORAGE_BUFFER) && (stride % alignment) != 0;
192 
193                     std::string name = Array::storageToString(storages[storageNdx]) + "_stride" + typeToString(stride) +
194                                        "_components" + typeToString(componentCount) + "_quads" +
195                                        typeToString(counts[countNdx]);
196 
197                     if ((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 ||
198                          m_type == Array::INPUTTYPE_INT_2_10_10_10) &&
199                         componentCount != 4)
200                         continue;
201 
202                     MultiVertexArrayTest::Spec::ArraySpec arraySpec(
203                         m_type, Array::OUTPUTTYPE_VEC4, storages[storageNdx], Array::USAGE_DYNAMIC_DRAW, componentCount,
204                         0, stride, false, GLValue::getMinValue(m_type), 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(),
214                                                           name.c_str()));
215                 }
216             }
217         }
218     }
219 }
220 
221 class SingleVertexArrayStrideTests : public TestCaseGroup
222 {
223 public:
224     SingleVertexArrayStrideTests(Context &context);
225     virtual ~SingleVertexArrayStrideTests(void);
226 
227     virtual void init(void);
228 
229 private:
230     SingleVertexArrayStrideTests(const SingleVertexArrayStrideTests &other);
231     SingleVertexArrayStrideTests &operator=(const SingleVertexArrayStrideTests &other);
232 };
233 
SingleVertexArrayStrideTests(Context & context)234 SingleVertexArrayStrideTests::SingleVertexArrayStrideTests(Context &context)
235     : TestCaseGroup(context, "strides", "Single stride vertex atribute")
236 {
237 }
238 
~SingleVertexArrayStrideTests(void)239 SingleVertexArrayStrideTests::~SingleVertexArrayStrideTests(void)
240 {
241 }
242 
init(void)243 void SingleVertexArrayStrideTests::init(void)
244 {
245     Array::InputType inputTypes[] = {
246         Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE,
247         /*Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE,*/ Array::INPUTTYPE_FIXED,
248         Array::INPUTTYPE_INT_2_10_10_10};
249 
250     for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
251     {
252         addChild(new SingleVertexArrayStrideGroup(m_context, inputTypes[inputTypeNdx]));
253     }
254 }
255 
256 class SingleVertexArrayFirstGroup : public TestCaseGroup
257 {
258 public:
259     SingleVertexArrayFirstGroup(Context &context, Array::InputType type);
260     virtual ~SingleVertexArrayFirstGroup(void);
261 
262     virtual void init(void);
263 
264 private:
265     SingleVertexArrayFirstGroup(const SingleVertexArrayFirstGroup &other);
266     SingleVertexArrayFirstGroup &operator=(const SingleVertexArrayFirstGroup &other);
267     Array::InputType m_type;
268 };
269 
SingleVertexArrayFirstGroup(Context & context,Array::InputType type)270 SingleVertexArrayFirstGroup::SingleVertexArrayFirstGroup(Context &context, Array::InputType type)
271     : TestCaseGroup(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
272     , m_type(type)
273 {
274 }
275 
~SingleVertexArrayFirstGroup(void)276 SingleVertexArrayFirstGroup::~SingleVertexArrayFirstGroup(void)
277 {
278 }
279 
init(void)280 void SingleVertexArrayFirstGroup::init(void)
281 {
282     int counts[]  = {5, 256};
283     int firsts[]  = {6, 24};
284     int offsets[] = {1, 16, 17};
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 offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
288     {
289         for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
290         {
291             for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
292             {
293                 for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); firstNdx++)
294                 {
295                     const bool packed =
296                         m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
297                     const int componentCount = (packed) ? (4) : (2);
298                     const int stride         = (strides[strideNdx] < 0) ?
299                                                    ((packed) ? (8) : (Array::inputTypeSize(m_type) * componentCount)) :
300                                                    (strides[strideNdx]);
301                     const int alignment =
302                         (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
303                     const bool aligned = ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0);
304                     std::string name   = "first" + typeToString(firsts[firstNdx]) + "_offset" +
305                                        typeToString(offsets[offsetNdx]) + "_stride" + typeToString(stride) + "_quads" +
306                                        typeToString(counts[countNdx]);
307 
308                     MultiVertexArrayTest::Spec::ArraySpec arraySpec(
309                         m_type, Array::OUTPUTTYPE_VEC2, Array::STORAGE_BUFFER, Array::USAGE_DYNAMIC_DRAW,
310                         componentCount, offsets[offsetNdx], stride, false, GLValue::getMinValue(m_type),
311                         GLValue::getMaxValue(m_type));
312 
313                     MultiVertexArrayTest::Spec spec;
314                     spec.primitive = Array::PRIMITIVE_TRIANGLES;
315                     spec.drawCount = counts[countNdx];
316                     spec.first     = firsts[firstNdx];
317                     spec.arrays.push_back(arraySpec);
318 
319                     if (aligned)
320                         addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(),
321                                                           name.c_str()));
322                 }
323             }
324         }
325     }
326 }
327 
328 class SingleVertexArrayFirstTests : public TestCaseGroup
329 {
330 public:
331     SingleVertexArrayFirstTests(Context &context);
332     virtual ~SingleVertexArrayFirstTests(void);
333 
334     virtual void init(void);
335 
336 private:
337     SingleVertexArrayFirstTests(const SingleVertexArrayFirstTests &other);
338     SingleVertexArrayFirstTests &operator=(const SingleVertexArrayFirstTests &other);
339 };
340 
SingleVertexArrayFirstTests(Context & context)341 SingleVertexArrayFirstTests::SingleVertexArrayFirstTests(Context &context)
342     : TestCaseGroup(context, "first", "Single vertex attribute, different first values to drawArrays")
343 {
344 }
345 
~SingleVertexArrayFirstTests(void)346 SingleVertexArrayFirstTests::~SingleVertexArrayFirstTests(void)
347 {
348 }
349 
init(void)350 void SingleVertexArrayFirstTests::init(void)
351 {
352     // Test offset with different input types, component counts and storage, Usage(?)
353     Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_INT_2_10_10_10};
354 
355     for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
356     {
357         addChild(new SingleVertexArrayFirstGroup(m_context, inputTypes[inputTypeNdx]));
358     }
359 }
360 
361 class SingleVertexArrayOffsetGroup : public TestCaseGroup
362 {
363 public:
364     SingleVertexArrayOffsetGroup(Context &context, Array::InputType type);
365     virtual ~SingleVertexArrayOffsetGroup(void);
366 
367     virtual void init(void);
368 
369 private:
370     SingleVertexArrayOffsetGroup(const SingleVertexArrayOffsetGroup &other);
371     SingleVertexArrayOffsetGroup &operator=(const SingleVertexArrayOffsetGroup &other);
372     Array::InputType m_type;
373 };
374 
SingleVertexArrayOffsetGroup(Context & context,Array::InputType type)375 SingleVertexArrayOffsetGroup::SingleVertexArrayOffsetGroup(Context &context, Array::InputType type)
376     : TestCaseGroup(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
377     , m_type(type)
378 {
379 }
380 
~SingleVertexArrayOffsetGroup(void)381 SingleVertexArrayOffsetGroup::~SingleVertexArrayOffsetGroup(void)
382 {
383 }
384 
init(void)385 void SingleVertexArrayOffsetGroup::init(void)
386 {
387     int counts[]  = {1, 256};
388     int offsets[] = {1, 4, 17, 32};
389     int strides[] = {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
390 
391     for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
392     {
393         for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
394         {
395             for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
396             {
397                 const bool packed =
398                     m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
399                 const int componentCount = (packed) ? (4) : (2);
400                 const int stride =
401                     (strides[strideNdx] < 0 ? Array::inputTypeSize(m_type) * componentCount : strides[strideNdx]);
402                 const int alignment =
403                     (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
404                 const bool aligned     = ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0);
405                 const std::string name = "offset" + typeToString(offsets[offsetNdx]) + "_stride" +
406                                          typeToString(stride) + "_quads" + typeToString(counts[countNdx]);
407 
408                 MultiVertexArrayTest::Spec::ArraySpec arraySpec(
409                     m_type, Array::OUTPUTTYPE_VEC2, Array::STORAGE_BUFFER, Array::USAGE_DYNAMIC_DRAW, componentCount,
410                     offsets[offsetNdx], stride, false, GLValue::getMinValue(m_type), GLValue::getMaxValue(m_type));
411 
412                 MultiVertexArrayTest::Spec spec;
413                 spec.primitive = Array::PRIMITIVE_TRIANGLES;
414                 spec.drawCount = counts[countNdx];
415                 spec.first     = 0;
416                 spec.arrays.push_back(arraySpec);
417 
418                 if (aligned)
419                     addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(),
420                                                       name.c_str()));
421             }
422         }
423     }
424 }
425 
426 class SingleVertexArrayOffsetTests : public TestCaseGroup
427 {
428 public:
429     SingleVertexArrayOffsetTests(Context &context);
430     virtual ~SingleVertexArrayOffsetTests(void);
431 
432     virtual void init(void);
433 
434 private:
435     SingleVertexArrayOffsetTests(const SingleVertexArrayOffsetTests &other);
436     SingleVertexArrayOffsetTests &operator=(const SingleVertexArrayOffsetTests &other);
437 };
438 
SingleVertexArrayOffsetTests(Context & context)439 SingleVertexArrayOffsetTests::SingleVertexArrayOffsetTests(Context &context)
440     : TestCaseGroup(context, "offset", "Single vertex atribute offset element")
441 {
442 }
443 
~SingleVertexArrayOffsetTests(void)444 SingleVertexArrayOffsetTests::~SingleVertexArrayOffsetTests(void)
445 {
446 }
447 
init(void)448 void SingleVertexArrayOffsetTests::init(void)
449 {
450     // Test offset with different input types, component counts and storage, Usage(?)
451     Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_INT_2_10_10_10};
452 
453     for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
454     {
455         addChild(new SingleVertexArrayOffsetGroup(m_context, inputTypes[inputTypeNdx]));
456     }
457 }
458 
459 class SingleVertexArrayNormalizeGroup : public TestCaseGroup
460 {
461 public:
462     SingleVertexArrayNormalizeGroup(Context &context, Array::InputType type);
463     virtual ~SingleVertexArrayNormalizeGroup(void);
464 
465     virtual void init(void);
466 
467 private:
468     SingleVertexArrayNormalizeGroup(const SingleVertexArrayNormalizeGroup &other);
469     SingleVertexArrayNormalizeGroup &operator=(const SingleVertexArrayNormalizeGroup &other);
470     Array::InputType m_type;
471 };
472 
SingleVertexArrayNormalizeGroup(Context & context,Array::InputType type)473 SingleVertexArrayNormalizeGroup::SingleVertexArrayNormalizeGroup(Context &context, Array::InputType type)
474     : TestCaseGroup(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
475     , m_type(type)
476 {
477 }
478 
~SingleVertexArrayNormalizeGroup(void)479 SingleVertexArrayNormalizeGroup::~SingleVertexArrayNormalizeGroup(void)
480 {
481 }
482 
init(void)483 void SingleVertexArrayNormalizeGroup::init(void)
484 {
485     int counts[] = {1, 256};
486 
487     for (int componentCount = 2; componentCount < 5; componentCount++)
488     {
489         for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
490         {
491             if ((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) &&
492                 componentCount != 4)
493                 continue;
494 
495             std::string name = "components" + typeToString(componentCount) + "_quads" + typeToString(counts[countNdx]);
496 
497             MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type, Array::OUTPUTTYPE_VEC4, Array::STORAGE_USER,
498                                                             Array::USAGE_DYNAMIC_DRAW, componentCount, 0, 0, true,
499                                                             GLValue::getMinValue(m_type), GLValue::getMaxValue(m_type));
500 
501             MultiVertexArrayTest::Spec spec;
502             spec.primitive = Array::PRIMITIVE_TRIANGLES;
503             spec.drawCount = counts[countNdx];
504             spec.first     = 0;
505             spec.arrays.push_back(arraySpec);
506 
507             addChild(
508                 new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
509         }
510     }
511 }
512 
513 class SingleVertexArrayNormalizeTests : public TestCaseGroup
514 {
515 public:
516     SingleVertexArrayNormalizeTests(Context &context);
517     virtual ~SingleVertexArrayNormalizeTests(void);
518 
519     virtual void init(void);
520 
521 private:
522     SingleVertexArrayNormalizeTests(const SingleVertexArrayNormalizeTests &other);
523     SingleVertexArrayNormalizeTests &operator=(const SingleVertexArrayNormalizeTests &other);
524 };
525 
SingleVertexArrayNormalizeTests(Context & context)526 SingleVertexArrayNormalizeTests::SingleVertexArrayNormalizeTests(Context &context)
527     : TestCaseGroup(context, "normalize", "Single normalize vertex atribute")
528 {
529 }
530 
~SingleVertexArrayNormalizeTests(void)531 SingleVertexArrayNormalizeTests::~SingleVertexArrayNormalizeTests(void)
532 {
533 }
534 
init(void)535 void SingleVertexArrayNormalizeTests::init(void)
536 {
537     // Test normalization with different input types, component counts and storage
538     Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT,         Array::INPUTTYPE_SHORT,
539                                      Array::INPUTTYPE_BYTE,          Array::INPUTTYPE_UNSIGNED_SHORT,
540                                      Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_FIXED,
541                                      Array::INPUTTYPE_UNSIGNED_INT,  Array::INPUTTYPE_INT,
542                                      Array::INPUTTYPE_HALF,          Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10,
543                                      Array::INPUTTYPE_INT_2_10_10_10};
544 
545     for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
546     {
547         addChild(new SingleVertexArrayNormalizeGroup(m_context, inputTypes[inputTypeNdx]));
548     }
549 }
550 
551 class SingleVertexArrayOutputTypeGroup : public TestCaseGroup
552 {
553 public:
554     SingleVertexArrayOutputTypeGroup(Context &context, Array::InputType type);
555     virtual ~SingleVertexArrayOutputTypeGroup(void);
556 
557     virtual void init(void);
558 
559 private:
560     SingleVertexArrayOutputTypeGroup(const SingleVertexArrayOutputTypeGroup &other);
561     SingleVertexArrayOutputTypeGroup &operator=(const SingleVertexArrayOutputTypeGroup &other);
562     Array::InputType m_type;
563 };
564 
SingleVertexArrayOutputTypeGroup(Context & context,Array::InputType type)565 SingleVertexArrayOutputTypeGroup::SingleVertexArrayOutputTypeGroup(Context &context, Array::InputType type)
566     : TestCaseGroup(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
567     , m_type(type)
568 {
569 }
570 
~SingleVertexArrayOutputTypeGroup(void)571 SingleVertexArrayOutputTypeGroup::~SingleVertexArrayOutputTypeGroup(void)
572 {
573 }
574 
init(void)575 void SingleVertexArrayOutputTypeGroup::init(void)
576 {
577     Array::OutputType outputTypes[] = {Array::OUTPUTTYPE_VEC2,  Array::OUTPUTTYPE_VEC3,  Array::OUTPUTTYPE_VEC4,
578                                        Array::OUTPUTTYPE_IVEC2, Array::OUTPUTTYPE_IVEC3, Array::OUTPUTTYPE_IVEC4,
579                                        Array::OUTPUTTYPE_UVEC2, Array::OUTPUTTYPE_UVEC3, Array::OUTPUTTYPE_UVEC4};
580     Array::Storage storages[]       = {Array::STORAGE_USER};
581     int counts[]                    = {1, 256};
582 
583     for (int outputTypeNdx = 0; outputTypeNdx < DE_LENGTH_OF_ARRAY(outputTypes); outputTypeNdx++)
584     {
585         for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
586         {
587             for (int componentCount = 2; componentCount < 5; componentCount++)
588             {
589                 for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
590                 {
591                     std::string name = "components" + typeToString(componentCount) + "_" +
592                                        Array::outputTypeToString(outputTypes[outputTypeNdx]) + "_quads" +
593                                        typeToString(counts[countNdx]);
594 
595                     const bool inputIsSignedInteger = m_type == Array::INPUTTYPE_INT ||
596                                                       m_type == Array::INPUTTYPE_SHORT ||
597                                                       m_type == Array::INPUTTYPE_BYTE;
598                     const bool inputIsUnignedInteger = m_type == Array::INPUTTYPE_UNSIGNED_INT ||
599                                                        m_type == Array::INPUTTYPE_UNSIGNED_SHORT ||
600                                                        m_type == Array::INPUTTYPE_UNSIGNED_BYTE;
601                     const bool outputIsSignedInteger = outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC2 ||
602                                                        outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC3 ||
603                                                        outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC4;
604                     const bool outputIsUnsignedInteger = outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC2 ||
605                                                          outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC3 ||
606                                                          outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC4;
607 
608                     // If input type is float type and output type is int type skip
609                     if ((m_type == Array::INPUTTYPE_FLOAT || m_type == Array::INPUTTYPE_HALF ||
610                          m_type == Array::INPUTTYPE_FIXED) &&
611                         (outputTypes[outputTypeNdx] >= Array::OUTPUTTYPE_INT))
612                         continue;
613 
614                     if ((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 ||
615                          m_type == Array::INPUTTYPE_INT_2_10_10_10) &&
616                         (outputTypes[outputTypeNdx] >= Array::OUTPUTTYPE_INT))
617                         continue;
618 
619                     if ((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 ||
620                          m_type == Array::INPUTTYPE_INT_2_10_10_10) &&
621                         componentCount != 4)
622                         continue;
623 
624                     // Loading signed data as unsigned causes undefined values and vice versa
625                     if (inputIsSignedInteger && outputIsUnsignedInteger)
626                         continue;
627                     if (inputIsUnignedInteger && outputIsSignedInteger)
628                         continue;
629 
630                     MultiVertexArrayTest::Spec::ArraySpec arraySpec(
631                         m_type, outputTypes[outputTypeNdx], storages[storageNdx], Array::USAGE_DYNAMIC_DRAW,
632                         componentCount, 0, 0, false, GLValue::getMinValue(m_type), GLValue::getMaxValue(m_type));
633 
634                     MultiVertexArrayTest::Spec spec;
635                     spec.primitive = Array::PRIMITIVE_TRIANGLES;
636                     spec.drawCount = counts[countNdx];
637                     spec.first     = 0;
638                     spec.arrays.push_back(arraySpec);
639 
640                     addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(),
641                                                       name.c_str()));
642                 }
643             }
644         }
645     }
646 }
647 
648 class SingleVertexArrayOutputTypeTests : public TestCaseGroup
649 {
650 public:
651     SingleVertexArrayOutputTypeTests(Context &context);
652     virtual ~SingleVertexArrayOutputTypeTests(void);
653 
654     virtual void init(void);
655 
656 private:
657     SingleVertexArrayOutputTypeTests(const SingleVertexArrayOutputTypeTests &other);
658     SingleVertexArrayOutputTypeTests &operator=(const SingleVertexArrayOutputTypeTests &other);
659 };
660 
SingleVertexArrayOutputTypeTests(Context & context)661 SingleVertexArrayOutputTypeTests::SingleVertexArrayOutputTypeTests(Context &context)
662     : TestCaseGroup(context, "output_types", "Single output type vertex atribute")
663 {
664 }
665 
~SingleVertexArrayOutputTypeTests(void)666 SingleVertexArrayOutputTypeTests::~SingleVertexArrayOutputTypeTests(void)
667 {
668 }
669 
init(void)670 void SingleVertexArrayOutputTypeTests::init(void)
671 {
672     // Test output types with different input types, component counts and storage, Usage?, Precision?, float?
673     Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT,         Array::INPUTTYPE_SHORT,
674                                      Array::INPUTTYPE_BYTE,          Array::INPUTTYPE_UNSIGNED_SHORT,
675                                      Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_FIXED,
676                                      Array::INPUTTYPE_UNSIGNED_INT,  Array::INPUTTYPE_INT,
677                                      Array::INPUTTYPE_HALF,          Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10,
678                                      Array::INPUTTYPE_INT_2_10_10_10};
679 
680     for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
681     {
682         addChild(new SingleVertexArrayOutputTypeGroup(m_context, inputTypes[inputTypeNdx]));
683     }
684 }
685 
686 class SingleVertexArrayTestGroup : public TestCaseGroup
687 {
688 public:
689     SingleVertexArrayTestGroup(Context &context);
690     virtual ~SingleVertexArrayTestGroup(void);
691 
692     virtual void init(void);
693 
694 private:
695     SingleVertexArrayTestGroup(const SingleVertexArrayTestGroup &other);
696     SingleVertexArrayTestGroup &operator=(const SingleVertexArrayTestGroup &other);
697 };
698 
SingleVertexArrayTestGroup(Context & context)699 SingleVertexArrayTestGroup::SingleVertexArrayTestGroup(Context &context)
700     : TestCaseGroup(context, "single_attribute", "Single vertex atribute")
701 {
702 }
703 
~SingleVertexArrayTestGroup(void)704 SingleVertexArrayTestGroup::~SingleVertexArrayTestGroup(void)
705 {
706 }
707 
init(void)708 void SingleVertexArrayTestGroup::init(void)
709 {
710     addChild(new SingleVertexArrayStrideTests(m_context));
711     addChild(new SingleVertexArrayNormalizeTests(m_context));
712     addChild(new SingleVertexArrayOutputTypeTests(m_context));
713     addChild(new SingleVertexArrayUsageTests(m_context));
714     addChild(new SingleVertexArrayOffsetTests(m_context));
715     addChild(new SingleVertexArrayFirstTests(m_context));
716 }
717 
718 class MultiVertexArrayCountTests : public TestCaseGroup
719 {
720 public:
721     MultiVertexArrayCountTests(Context &context);
722     virtual ~MultiVertexArrayCountTests(void);
723 
724     virtual void init(void);
725 
726 private:
727     MultiVertexArrayCountTests(const MultiVertexArrayCountTests &other);
728     MultiVertexArrayCountTests &operator=(const MultiVertexArrayCountTests &other);
729 
730     std::string getTestName(const MultiVertexArrayTest::Spec &spec);
731 };
732 
MultiVertexArrayCountTests(Context & context)733 MultiVertexArrayCountTests::MultiVertexArrayCountTests(Context &context)
734     : TestCaseGroup(context, "attribute_count", "Attribute counts")
735 {
736 }
737 
~MultiVertexArrayCountTests(void)738 MultiVertexArrayCountTests::~MultiVertexArrayCountTests(void)
739 {
740 }
741 
getTestName(const MultiVertexArrayTest::Spec & spec)742 std::string MultiVertexArrayCountTests::getTestName(const MultiVertexArrayTest::Spec &spec)
743 {
744     std::stringstream name;
745     name << spec.arrays.size();
746 
747     return name.str();
748 }
749 
init(void)750 void MultiVertexArrayCountTests::init(void)
751 {
752     // Test attribute counts
753     int arrayCounts[] = {2, 3, 4, 5, 6, 7, 8};
754 
755     for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
756     {
757         MultiVertexArrayTest::Spec spec;
758 
759         spec.primitive = Array::PRIMITIVE_TRIANGLES;
760         spec.drawCount = 256;
761         spec.first     = 0;
762 
763         for (int arrayNdx = 0; arrayNdx < arrayCounts[arrayCountNdx]; arrayNdx++)
764         {
765             MultiVertexArrayTest::Spec::ArraySpec arraySpec(
766                 Array::INPUTTYPE_FLOAT, Array::OUTPUTTYPE_VEC2, Array::STORAGE_USER, Array::USAGE_DYNAMIC_DRAW, 2, 0, 0,
767                 false, GLValue::getMinValue(Array::INPUTTYPE_FLOAT), GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));
768 
769             spec.arrays.push_back(arraySpec);
770         }
771 
772         std::string name = getTestName(spec);
773         std::string desc = getTestName(spec);
774 
775         addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
776     }
777 }
778 
779 class MultiVertexArrayStorageTests : public TestCaseGroup
780 {
781 public:
782     MultiVertexArrayStorageTests(Context &context);
783     virtual ~MultiVertexArrayStorageTests(void);
784 
785     virtual void init(void);
786 
787 private:
788     MultiVertexArrayStorageTests(const MultiVertexArrayStorageTests &other);
789     MultiVertexArrayStorageTests &operator=(const MultiVertexArrayStorageTests &other);
790 
791     void addStorageCases(MultiVertexArrayTest::Spec spec, int depth);
792     std::string getTestName(const MultiVertexArrayTest::Spec &spec);
793 };
794 
MultiVertexArrayStorageTests(Context & context)795 MultiVertexArrayStorageTests::MultiVertexArrayStorageTests(Context &context)
796     : TestCaseGroup(context, "storage", "Attribute storages")
797 {
798 }
799 
~MultiVertexArrayStorageTests(void)800 MultiVertexArrayStorageTests::~MultiVertexArrayStorageTests(void)
801 {
802 }
803 
getTestName(const MultiVertexArrayTest::Spec & spec)804 std::string MultiVertexArrayStorageTests::getTestName(const MultiVertexArrayTest::Spec &spec)
805 {
806     std::stringstream name;
807     name << spec.arrays.size();
808 
809     for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
810     {
811         name << "_" << Array::storageToString(spec.arrays[arrayNdx].storage);
812     }
813 
814     return name.str();
815 }
816 
addStorageCases(MultiVertexArrayTest::Spec spec,int depth)817 void MultiVertexArrayStorageTests::addStorageCases(MultiVertexArrayTest::Spec spec, int depth)
818 {
819     if (depth == 0)
820     {
821         // Skip trivial case, used elsewhere
822         bool ok = false;
823         for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
824         {
825             if (spec.arrays[arrayNdx].storage != Array::STORAGE_USER)
826             {
827                 ok = true;
828                 break;
829             }
830         }
831 
832         if (!ok)
833             return;
834 
835         std::string name = getTestName(spec);
836         std::string desc = getTestName(spec);
837 
838         addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
839         return;
840     }
841 
842     Array::Storage storages[] = {Array::STORAGE_USER, Array::STORAGE_BUFFER};
843     for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
844     {
845         MultiVertexArrayTest::Spec::ArraySpec arraySpec(
846             Array::INPUTTYPE_FLOAT, Array::OUTPUTTYPE_VEC2, storages[storageNdx], Array::USAGE_DYNAMIC_DRAW, 2, 0, 0,
847             false, GLValue::getMinValue(Array::INPUTTYPE_FLOAT), GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));
848 
849         MultiVertexArrayTest::Spec _spec = spec;
850         _spec.arrays.push_back(arraySpec);
851         addStorageCases(_spec, depth - 1);
852     }
853 }
854 
init(void)855 void MultiVertexArrayStorageTests::init(void)
856 {
857     // Test different storages
858     int arrayCounts[] = {3};
859 
860     MultiVertexArrayTest::Spec spec;
861 
862     spec.primitive = Array::PRIMITIVE_TRIANGLES;
863     spec.drawCount = 256;
864     spec.first     = 0;
865 
866     for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
867         addStorageCases(spec, arrayCounts[arrayCountNdx]);
868 }
869 
870 class MultiVertexArrayStrideTests : public TestCaseGroup
871 {
872 public:
873     MultiVertexArrayStrideTests(Context &context);
874     virtual ~MultiVertexArrayStrideTests(void);
875 
876     virtual void init(void);
877 
878 private:
879     MultiVertexArrayStrideTests(const MultiVertexArrayStrideTests &other);
880     MultiVertexArrayStrideTests &operator=(const MultiVertexArrayStrideTests &other);
881 
882     void addStrideCases(MultiVertexArrayTest::Spec spec, int depth);
883     std::string getTestName(const MultiVertexArrayTest::Spec &spec);
884 };
885 
MultiVertexArrayStrideTests(Context & context)886 MultiVertexArrayStrideTests::MultiVertexArrayStrideTests(Context &context) : TestCaseGroup(context, "stride", "Strides")
887 {
888 }
889 
~MultiVertexArrayStrideTests(void)890 MultiVertexArrayStrideTests::~MultiVertexArrayStrideTests(void)
891 {
892 }
893 
getTestName(const MultiVertexArrayTest::Spec & spec)894 std::string MultiVertexArrayStrideTests::getTestName(const MultiVertexArrayTest::Spec &spec)
895 {
896     std::stringstream name;
897 
898     name << spec.arrays.size();
899 
900     for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
901     {
902         name << "_" << Array::inputTypeToString(spec.arrays[arrayNdx].inputType) << spec.arrays[arrayNdx].componentCount
903              << "_" << spec.arrays[arrayNdx].stride;
904     }
905 
906     return name.str();
907 }
908 
init(void)909 void MultiVertexArrayStrideTests::init(void)
910 {
911     // Test different strides, with multiple arrays, input types??
912     int arrayCounts[] = {3};
913 
914     MultiVertexArrayTest::Spec spec;
915 
916     spec.primitive = Array::PRIMITIVE_TRIANGLES;
917     spec.drawCount = 256;
918     spec.first     = 0;
919 
920     for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
921         addStrideCases(spec, arrayCounts[arrayCountNdx]);
922 }
923 
addStrideCases(MultiVertexArrayTest::Spec spec,int depth)924 void MultiVertexArrayStrideTests::addStrideCases(MultiVertexArrayTest::Spec spec, int depth)
925 {
926     if (depth == 0)
927     {
928         std::string name = getTestName(spec);
929         std::string desc = getTestName(spec);
930         addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
931         return;
932     }
933 
934     int strides[] = {0, -1, 17, 32};
935 
936     for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
937     {
938         const int componentCount = 2;
939         MultiVertexArrayTest::Spec::ArraySpec arraySpec(
940             Array::INPUTTYPE_FLOAT, Array::OUTPUTTYPE_VEC2, Array::STORAGE_USER, Array::USAGE_DYNAMIC_DRAW,
941             componentCount, 0,
942             (strides[strideNdx] >= 0 ? strides[strideNdx] :
943                                        componentCount * Array::inputTypeSize(Array::INPUTTYPE_FLOAT)),
944             false, GLValue::getMinValue(Array::INPUTTYPE_FLOAT), GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));
945 
946         MultiVertexArrayTest::Spec _spec = spec;
947         _spec.arrays.push_back(arraySpec);
948         addStrideCases(_spec, depth - 1);
949     }
950 }
951 
952 class MultiVertexArrayOutputTests : public TestCaseGroup
953 {
954 public:
955     MultiVertexArrayOutputTests(Context &context);
956     virtual ~MultiVertexArrayOutputTests(void);
957 
958     virtual void init(void);
959 
960 private:
961     MultiVertexArrayOutputTests(const MultiVertexArrayOutputTests &other);
962     MultiVertexArrayOutputTests &operator=(const MultiVertexArrayOutputTests &other);
963 
964     void addInputTypeCases(MultiVertexArrayTest::Spec spec, int depth);
965     std::string getTestName(const MultiVertexArrayTest::Spec &spec);
966 };
967 
MultiVertexArrayOutputTests(Context & context)968 MultiVertexArrayOutputTests::MultiVertexArrayOutputTests(Context &context)
969     : TestCaseGroup(context, "input_types", "input types")
970 {
971 }
972 
~MultiVertexArrayOutputTests(void)973 MultiVertexArrayOutputTests::~MultiVertexArrayOutputTests(void)
974 {
975 }
976 
getTestName(const MultiVertexArrayTest::Spec & spec)977 std::string MultiVertexArrayOutputTests::getTestName(const MultiVertexArrayTest::Spec &spec)
978 {
979     std::stringstream name;
980 
981     name << spec.arrays.size();
982 
983     for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
984     {
985         name << "_" << Array::inputTypeToString(spec.arrays[arrayNdx].inputType) << spec.arrays[arrayNdx].componentCount
986              << "_" << Array::outputTypeToString(spec.arrays[arrayNdx].outputType);
987     }
988 
989     return name.str();
990 }
991 
init(void)992 void MultiVertexArrayOutputTests::init(void)
993 {
994     // Test different input types, with multiple arrays
995     int arrayCounts[] = {3};
996 
997     MultiVertexArrayTest::Spec spec;
998 
999     spec.primitive = Array::PRIMITIVE_TRIANGLES;
1000     spec.drawCount = 256;
1001     spec.first     = 0;
1002 
1003     for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
1004         addInputTypeCases(spec, arrayCounts[arrayCountNdx]);
1005 }
1006 
addInputTypeCases(MultiVertexArrayTest::Spec spec,int depth)1007 void MultiVertexArrayOutputTests::addInputTypeCases(MultiVertexArrayTest::Spec spec, int depth)
1008 {
1009     if (depth == 0)
1010     {
1011         std::string name = getTestName(spec);
1012         std::string desc = getTestName(spec);
1013         addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
1014         return;
1015     }
1016 
1017     Array::InputType inputTypes[] = {Array::INPUTTYPE_FIXED, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_SHORT,
1018                                      Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_UNSIGNED_SHORT};
1019     for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
1020     {
1021         MultiVertexArrayTest::Spec::ArraySpec arraySpec(
1022             inputTypes[inputTypeNdx], Array::OUTPUTTYPE_VEC2, Array::STORAGE_USER, Array::USAGE_DYNAMIC_DRAW, 2, 0, 0,
1023             false, GLValue::getMinValue(inputTypes[inputTypeNdx]), GLValue::getMaxValue(inputTypes[inputTypeNdx]));
1024 
1025         MultiVertexArrayTest::Spec _spec = spec;
1026         _spec.arrays.push_back(arraySpec);
1027         addInputTypeCases(_spec, depth - 1);
1028     }
1029 }
1030 
1031 class MultiVertexArrayTestGroup : public TestCaseGroup
1032 {
1033 public:
1034     MultiVertexArrayTestGroup(Context &context);
1035     virtual ~MultiVertexArrayTestGroup(void);
1036 
1037     virtual void init(void);
1038 
1039 private:
1040     MultiVertexArrayTestGroup(const MultiVertexArrayTestGroup &other);
1041     MultiVertexArrayTestGroup &operator=(const MultiVertexArrayTestGroup &other);
1042 };
1043 
MultiVertexArrayTestGroup(Context & context)1044 MultiVertexArrayTestGroup::MultiVertexArrayTestGroup(Context &context)
1045     : TestCaseGroup(context, "multiple_attributes", "Multiple vertex atributes")
1046 {
1047 }
1048 
~MultiVertexArrayTestGroup(void)1049 MultiVertexArrayTestGroup::~MultiVertexArrayTestGroup(void)
1050 {
1051 }
1052 
init(void)1053 void MultiVertexArrayTestGroup::init(void)
1054 {
1055     addChild(new MultiVertexArrayCountTests(m_context));
1056     addChild(new MultiVertexArrayStorageTests(m_context));
1057     addChild(new MultiVertexArrayStrideTests(m_context));
1058     addChild(new MultiVertexArrayOutputTests(m_context));
1059 }
1060 
VertexArrayTestGroup(Context & context)1061 VertexArrayTestGroup::VertexArrayTestGroup(Context &context)
1062     : TestCaseGroup(context, "vertex_arrays", "Vertex array and array tests")
1063 {
1064 }
1065 
~VertexArrayTestGroup(void)1066 VertexArrayTestGroup::~VertexArrayTestGroup(void)
1067 {
1068 }
1069 
init(void)1070 void VertexArrayTestGroup::init(void)
1071 {
1072     addChild(new SingleVertexArrayTestGroup(m_context));
1073     addChild(new MultiVertexArrayTestGroup(m_context));
1074 }
1075 
1076 } // namespace Functional
1077 } // namespace gles3
1078 } // namespace deqp
1079