xref: /aosp_15_r20/external/deqp/modules/gles3/stress/es3sVertexArrayTests.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 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