xref: /aosp_15_r20/external/deqp/modules/gles2/functional/es2fDrawTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Drawing tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es2fDrawTests.hpp"
25 #include "glsDrawTest.hpp"
26 #include "tcuRenderTarget.hpp"
27 #include "deRandom.hpp"
28 #include "deStringUtil.hpp"
29 #include "deUniquePtr.hpp"
30 #include "deSTLUtil.hpp"
31 
32 #include "glwEnums.hpp"
33 
34 #include <set>
35 
36 namespace deqp
37 {
38 namespace gles2
39 {
40 namespace Functional
41 {
42 namespace
43 {
44 
45 enum TestIterationType
46 {
47     TYPE_DRAW_COUNT, // !< test with 1, 5, and 25 primitives
48 
49     TYPE_LAST
50 };
51 
addTestIterations(gls::DrawTest * test,const gls::DrawTestSpec & baseSpec,TestIterationType type)52 static void addTestIterations(gls::DrawTest *test, const gls::DrawTestSpec &baseSpec, TestIterationType type)
53 {
54     gls::DrawTestSpec spec(baseSpec);
55 
56     if (type == TYPE_DRAW_COUNT)
57     {
58         spec.primitiveCount = 1;
59         test->addIteration(spec, "draw count = 1");
60 
61         spec.primitiveCount = 5;
62         test->addIteration(spec, "draw count = 5");
63 
64         spec.primitiveCount = 25;
65         test->addIteration(spec, "draw count = 25");
66     }
67     else
68         DE_ASSERT(false);
69 }
70 
genBasicSpec(gls::DrawTestSpec & spec,gls::DrawTestSpec::DrawMethod method)71 static void genBasicSpec(gls::DrawTestSpec &spec, gls::DrawTestSpec::DrawMethod method)
72 {
73     spec.apiType            = glu::ApiType::es(2, 0);
74     spec.primitive          = gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
75     spec.primitiveCount     = 5;
76     spec.drawMethod         = method;
77     spec.indexType          = gls::DrawTestSpec::INDEXTYPE_LAST;
78     spec.indexPointerOffset = 0;
79     spec.indexStorage       = gls::DrawTestSpec::STORAGE_LAST;
80     spec.first              = 0;
81     spec.indexMin           = 0;
82     spec.indexMax           = 0;
83     spec.instanceCount      = 1;
84 
85     spec.attribs.resize(2);
86 
87     spec.attribs[0].inputType           = gls::DrawTestSpec::INPUTTYPE_FLOAT;
88     spec.attribs[0].outputType          = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
89     spec.attribs[0].storage             = gls::DrawTestSpec::STORAGE_BUFFER;
90     spec.attribs[0].usage               = gls::DrawTestSpec::USAGE_STATIC_DRAW;
91     spec.attribs[0].componentCount      = 4;
92     spec.attribs[0].offset              = 0;
93     spec.attribs[0].stride              = 0;
94     spec.attribs[0].normalize           = false;
95     spec.attribs[0].instanceDivisor     = 0;
96     spec.attribs[0].useDefaultAttribute = false;
97 
98     spec.attribs[1].inputType           = gls::DrawTestSpec::INPUTTYPE_FLOAT;
99     spec.attribs[1].outputType          = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
100     spec.attribs[1].storage             = gls::DrawTestSpec::STORAGE_BUFFER;
101     spec.attribs[1].usage               = gls::DrawTestSpec::USAGE_STATIC_DRAW;
102     spec.attribs[1].componentCount      = 2;
103     spec.attribs[1].offset              = 0;
104     spec.attribs[1].stride              = 0;
105     spec.attribs[1].normalize           = false;
106     spec.attribs[1].instanceDivisor     = 0;
107     spec.attribs[1].useDefaultAttribute = false;
108 }
109 
110 class AttributeGroup : public TestCaseGroup
111 {
112 public:
113     AttributeGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod,
114                    gls::DrawTestSpec::Primitive primitive, gls::DrawTestSpec::IndexType indexType,
115                    gls::DrawTestSpec::Storage indexStorage);
116     ~AttributeGroup(void);
117 
118     void init(void);
119 
120 private:
121     gls::DrawTestSpec::DrawMethod m_method;
122     gls::DrawTestSpec::Primitive m_primitive;
123     gls::DrawTestSpec::IndexType m_indexType;
124     gls::DrawTestSpec::Storage m_indexStorage;
125 };
126 
AttributeGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod,gls::DrawTestSpec::Primitive primitive,gls::DrawTestSpec::IndexType indexType,gls::DrawTestSpec::Storage indexStorage)127 AttributeGroup::AttributeGroup(Context &context, const char *name, const char *descr,
128                                gls::DrawTestSpec::DrawMethod drawMethod, gls::DrawTestSpec::Primitive primitive,
129                                gls::DrawTestSpec::IndexType indexType, gls::DrawTestSpec::Storage indexStorage)
130     : TestCaseGroup(context, name, descr)
131     , m_method(drawMethod)
132     , m_primitive(primitive)
133     , m_indexType(indexType)
134     , m_indexStorage(indexStorage)
135 {
136 }
137 
~AttributeGroup(void)138 AttributeGroup::~AttributeGroup(void)
139 {
140 }
141 
init(void)142 void AttributeGroup::init(void)
143 {
144     // Single attribute
145     {
146         gls::DrawTest *test =
147             new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
148         gls::DrawTestSpec spec;
149 
150         spec.apiType            = glu::ApiType::es(2, 0);
151         spec.primitive          = m_primitive;
152         spec.primitiveCount     = 0;
153         spec.drawMethod         = m_method;
154         spec.indexType          = m_indexType;
155         spec.indexPointerOffset = 0;
156         spec.indexStorage       = m_indexStorage;
157         spec.first              = 0;
158         spec.indexMin           = 0;
159         spec.indexMax           = 0;
160         spec.instanceCount      = 1;
161 
162         spec.attribs.resize(1);
163 
164         spec.attribs[0].inputType           = gls::DrawTestSpec::INPUTTYPE_FLOAT;
165         spec.attribs[0].outputType          = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
166         spec.attribs[0].storage             = gls::DrawTestSpec::STORAGE_BUFFER;
167         spec.attribs[0].usage               = gls::DrawTestSpec::USAGE_STATIC_DRAW;
168         spec.attribs[0].componentCount      = 2;
169         spec.attribs[0].offset              = 0;
170         spec.attribs[0].stride              = 0;
171         spec.attribs[0].normalize           = false;
172         spec.attribs[0].instanceDivisor     = 0;
173         spec.attribs[0].useDefaultAttribute = false;
174 
175         addTestIterations(test, spec, TYPE_DRAW_COUNT);
176 
177         this->addChild(test);
178     }
179 
180     // Multiple attribute
181     {
182         gls::DrawTest *test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes",
183                                                 "Multiple attribute arrays");
184         gls::DrawTestSpec spec;
185 
186         spec.apiType            = glu::ApiType::es(2, 0);
187         spec.primitive          = m_primitive;
188         spec.primitiveCount     = 0;
189         spec.drawMethod         = m_method;
190         spec.indexType          = m_indexType;
191         spec.indexPointerOffset = 0;
192         spec.indexStorage       = m_indexStorage;
193         spec.first              = 0;
194         spec.indexMin           = 0;
195         spec.indexMax           = 0;
196         spec.instanceCount      = 1;
197 
198         spec.attribs.resize(2);
199 
200         spec.attribs[0].inputType           = gls::DrawTestSpec::INPUTTYPE_FLOAT;
201         spec.attribs[0].outputType          = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
202         spec.attribs[0].storage             = gls::DrawTestSpec::STORAGE_BUFFER;
203         spec.attribs[0].usage               = gls::DrawTestSpec::USAGE_STATIC_DRAW;
204         spec.attribs[0].componentCount      = 4;
205         spec.attribs[0].offset              = 0;
206         spec.attribs[0].stride              = 0;
207         spec.attribs[0].normalize           = false;
208         spec.attribs[0].instanceDivisor     = 0;
209         spec.attribs[0].useDefaultAttribute = false;
210 
211         spec.attribs[1].inputType           = gls::DrawTestSpec::INPUTTYPE_FLOAT;
212         spec.attribs[1].outputType          = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
213         spec.attribs[1].storage             = gls::DrawTestSpec::STORAGE_BUFFER;
214         spec.attribs[1].usage               = gls::DrawTestSpec::USAGE_STATIC_DRAW;
215         spec.attribs[1].componentCount      = 2;
216         spec.attribs[1].offset              = 0;
217         spec.attribs[1].stride              = 0;
218         spec.attribs[1].normalize           = false;
219         spec.attribs[1].instanceDivisor     = 0;
220         spec.attribs[1].useDefaultAttribute = false;
221 
222         addTestIterations(test, spec, TYPE_DRAW_COUNT);
223 
224         this->addChild(test);
225     }
226 
227     // Multiple attribute, second one default.
228     {
229         gls::DrawTest *test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute",
230                                                 "Attribute specified with glVertexAttrib*.");
231         gls::DrawTestSpec spec;
232 
233         spec.apiType            = glu::ApiType::es(2, 0);
234         spec.primitive          = m_primitive;
235         spec.primitiveCount     = 5;
236         spec.drawMethod         = m_method;
237         spec.indexType          = m_indexType;
238         spec.indexPointerOffset = 0;
239         spec.indexStorage       = m_indexStorage;
240         spec.first              = 0;
241         spec.indexMin           = 0;
242         spec.indexMax           = 0;
243         spec.instanceCount      = 1;
244 
245         spec.attribs.resize(2);
246 
247         spec.attribs[0].inputType           = gls::DrawTestSpec::INPUTTYPE_FLOAT;
248         spec.attribs[0].outputType          = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
249         spec.attribs[0].storage             = gls::DrawTestSpec::STORAGE_BUFFER;
250         spec.attribs[0].usage               = gls::DrawTestSpec::USAGE_STATIC_DRAW;
251         spec.attribs[0].componentCount      = 2;
252         spec.attribs[0].offset              = 0;
253         spec.attribs[0].stride              = 0;
254         spec.attribs[0].normalize           = false;
255         spec.attribs[0].instanceDivisor     = 0;
256         spec.attribs[0].useDefaultAttribute = false;
257 
258         struct IOPair
259         {
260             gls::DrawTestSpec::InputType input;
261             gls::DrawTestSpec::OutputType output;
262             int componentCount;
263         } iopairs[] = {
264             {gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC2, 4},
265             {gls::DrawTestSpec::INPUTTYPE_FLOAT, gls::DrawTestSpec::OUTPUTTYPE_VEC4, 2},
266         };
267 
268         for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
269         {
270             const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) +
271                                      de::toString(iopairs[ioNdx].componentCount) + " to " +
272                                      gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
273 
274             spec.attribs[1].inputType           = iopairs[ioNdx].input;
275             spec.attribs[1].outputType          = iopairs[ioNdx].output;
276             spec.attribs[1].storage             = gls::DrawTestSpec::STORAGE_BUFFER;
277             spec.attribs[1].usage               = gls::DrawTestSpec::USAGE_STATIC_DRAW;
278             spec.attribs[1].componentCount      = iopairs[ioNdx].componentCount;
279             spec.attribs[1].offset              = 0;
280             spec.attribs[1].stride              = 0;
281             spec.attribs[1].normalize           = false;
282             spec.attribs[1].instanceDivisor     = 0;
283             spec.attribs[1].useDefaultAttribute = true;
284 
285             test->addIteration(spec, desc.c_str());
286         }
287 
288         this->addChild(test);
289     }
290 }
291 
292 class IndexGroup : public TestCaseGroup
293 {
294 public:
295     IndexGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod);
296     ~IndexGroup(void);
297 
298     void init(void);
299 
300 private:
301     gls::DrawTestSpec::DrawMethod m_method;
302 };
303 
IndexGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)304 IndexGroup::IndexGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod)
305     : TestCaseGroup(context, name, descr)
306     , m_method(drawMethod)
307 {
308 }
309 
~IndexGroup(void)310 IndexGroup::~IndexGroup(void)
311 {
312 }
313 
init(void)314 void IndexGroup::init(void)
315 {
316     struct IndexTest
317     {
318         gls::DrawTestSpec::Storage storage;
319         gls::DrawTestSpec::IndexType type;
320         bool aligned;
321         int offsets[3];
322     };
323 
324     const IndexTest tests[] = {
325         {gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, {0, 1, -1}},
326         {gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, {0, 2, -1}},
327 
328         {gls::DrawTestSpec::STORAGE_USER, gls::DrawTestSpec::INDEXTYPE_SHORT, false, {1, 3, -1}},
329 
330         {gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_BYTE, true, {0, 1, -1}},
331         {gls::DrawTestSpec::STORAGE_BUFFER, gls::DrawTestSpec::INDEXTYPE_SHORT, true, {0, 2, -1}},
332     };
333 
334     gls::DrawTestSpec spec;
335 
336     tcu::TestCaseGroup *userPtrGroup = new tcu::TestCaseGroup(m_testCtx, "user_ptr", "user pointer");
337     tcu::TestCaseGroup *unalignedUserPtrGroup =
338         new tcu::TestCaseGroup(m_testCtx, "unaligned_user_ptr", "unaligned user pointer");
339     tcu::TestCaseGroup *bufferGroup = new tcu::TestCaseGroup(m_testCtx, "buffer", "buffer");
340 
341     genBasicSpec(spec, m_method);
342 
343     this->addChild(userPtrGroup);
344     this->addChild(unalignedUserPtrGroup);
345     this->addChild(bufferGroup);
346 
347     for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
348     {
349         const IndexTest &indexTest = tests[testNdx];
350         tcu::TestCaseGroup *group  = (indexTest.storage == gls::DrawTestSpec::STORAGE_USER) ?
351                                          ((indexTest.aligned) ? (userPtrGroup) : (unalignedUserPtrGroup)) :
352                                          ((indexTest.aligned) ? (bufferGroup) : (DE_NULL));
353 
354         const std::string name = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
355         const std::string desc = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " +
356                                  gls::DrawTestSpec::storageToString(indexTest.storage);
357         de::MovePtr<gls::DrawTest> test(
358             new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()));
359 
360         spec.indexType    = indexTest.type;
361         spec.indexStorage = indexTest.storage;
362 
363         for (int iterationNdx = 0;
364              iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1;
365              ++iterationNdx)
366         {
367             const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]);
368             spec.indexPointerOffset         = indexTest.offsets[iterationNdx];
369             test->addIteration(spec, iterationDesc.c_str());
370         }
371 
372         DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET);
373         DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE);
374         group->addChild(test.release());
375     }
376 }
377 
378 class FirstGroup : public TestCaseGroup
379 {
380 public:
381     FirstGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod);
382     ~FirstGroup(void);
383 
384     void init(void);
385 
386 private:
387     gls::DrawTestSpec::DrawMethod m_method;
388 };
389 
FirstGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)390 FirstGroup::FirstGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod)
391     : TestCaseGroup(context, name, descr)
392     , m_method(drawMethod)
393 {
394 }
395 
~FirstGroup(void)396 FirstGroup::~FirstGroup(void)
397 {
398 }
399 
init(void)400 void FirstGroup::init(void)
401 {
402     const int firsts[] = {0, 1, 17};
403 
404     gls::DrawTestSpec spec;
405     genBasicSpec(spec, m_method);
406 
407     for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); ++firstNdx)
408     {
409         const std::string name = std::string("first_") + de::toString(firsts[firstNdx]);
410         const std::string desc = std::string("first ") + de::toString(firsts[firstNdx]);
411         gls::DrawTest *test    = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
412 
413         spec.first = firsts[firstNdx];
414 
415         addTestIterations(test, spec, TYPE_DRAW_COUNT);
416 
417         this->addChild(test);
418     }
419 }
420 
421 class MethodGroup : public TestCaseGroup
422 {
423 public:
424     MethodGroup(Context &context, const char *name, const char *descr, gls::DrawTestSpec::DrawMethod drawMethod);
425     ~MethodGroup(void);
426 
427     void init(void);
428 
429 private:
430     gls::DrawTestSpec::DrawMethod m_method;
431 };
432 
MethodGroup(Context & context,const char * name,const char * descr,gls::DrawTestSpec::DrawMethod drawMethod)433 MethodGroup::MethodGroup(Context &context, const char *name, const char *descr,
434                          gls::DrawTestSpec::DrawMethod drawMethod)
435     : TestCaseGroup(context, name, descr)
436     , m_method(drawMethod)
437 {
438 }
439 
~MethodGroup(void)440 MethodGroup::~MethodGroup(void)
441 {
442 }
443 
init(void)444 void MethodGroup::init(void)
445 {
446     const bool indexed = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) ||
447                          (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) ||
448                          (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
449     const bool hasFirst = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS) ||
450                           (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED);
451 
452     const gls::DrawTestSpec::Primitive primitive[] = {
453         gls::DrawTestSpec::PRIMITIVE_POINTS,       gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
454         gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN, gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
455         gls::DrawTestSpec::PRIMITIVE_LINES,        gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
456         gls::DrawTestSpec::PRIMITIVE_LINE_LOOP};
457 
458     if (hasFirst)
459     {
460         // First-tests
461         this->addChild(new FirstGroup(m_context, "first", "First tests", m_method));
462     }
463 
464     if (indexed)
465     {
466         // Index-tests
467         if (m_method != gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED)
468             this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
469     }
470 
471     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
472     {
473         const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
474         const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
475 
476         this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx],
477                                           gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
478     }
479 }
480 
481 class RandomGroup : public TestCaseGroup
482 {
483 public:
484     RandomGroup(Context &context, const char *name, const char *descr);
485     ~RandomGroup(void);
486 
487     void init(void);
488 };
489 
490 template <int SIZE>
491 struct UniformWeightArray
492 {
493     float weights[SIZE];
494 
UniformWeightArraydeqp::gles2::Functional::__anon5cf4d8b80111::UniformWeightArray495     UniformWeightArray(void)
496     {
497         for (int i = 0; i < SIZE; ++i)
498             weights[i] = 1.0f;
499     }
500 };
501 
RandomGroup(Context & context,const char * name,const char * descr)502 RandomGroup::RandomGroup(Context &context, const char *name, const char *descr) : TestCaseGroup(context, name, descr)
503 {
504 }
505 
~RandomGroup(void)506 RandomGroup::~RandomGroup(void)
507 {
508 }
509 
init(void)510 void RandomGroup::init(void)
511 {
512     const int numAttempts = 100;
513 
514     static const int attribCounts[]            = {1, 2, 5};
515     static const float attribWeights[]         = {30, 10, 1};
516     static const int primitiveCounts[]         = {1, 5, 64};
517     static const float primitiveCountWeights[] = {20, 10, 1};
518     static const int indexOffsets[]            = {0, 7, 13};
519     static const float indexOffsetWeights[]    = {20, 20, 1};
520     static const int firsts[]                  = {0, 7, 13};
521     static const float firstWeights[]          = {20, 20, 1};
522     static const int offsets[]                 = {0, 1, 5, 12};
523     static const float offsetWeights[]         = {50, 10, 10, 10};
524     static const int strides[]                 = {0, 7, 16, 17};
525     static const float strideWeights[]         = {50, 10, 10, 10};
526 
527     static const gls::DrawTestSpec::Primitive primitives[] = {
528         gls::DrawTestSpec::PRIMITIVE_POINTS,       gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
529         gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN, gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
530         gls::DrawTestSpec::PRIMITIVE_LINES,        gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
531         gls::DrawTestSpec::PRIMITIVE_LINE_LOOP};
532     const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
533 
534     static const gls::DrawTestSpec::DrawMethod drawMethods[] = {
535         gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
536         gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
537     };
538     const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
539 
540     static const gls::DrawTestSpec::IndexType indexTypes[] = {
541         gls::DrawTestSpec::INDEXTYPE_BYTE,
542         gls::DrawTestSpec::INDEXTYPE_SHORT,
543     };
544     const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
545 
546     static const gls::DrawTestSpec::Storage storages[] = {
547         gls::DrawTestSpec::STORAGE_USER,
548         gls::DrawTestSpec::STORAGE_BUFFER,
549     };
550     const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights;
551 
552     static const gls::DrawTestSpec::InputType inputTypes[] = {
553         gls::DrawTestSpec::INPUTTYPE_FLOAT,         gls::DrawTestSpec::INPUTTYPE_FIXED,
554         gls::DrawTestSpec::INPUTTYPE_BYTE,          gls::DrawTestSpec::INPUTTYPE_SHORT,
555         gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE, gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT};
556     const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
557 
558     static const gls::DrawTestSpec::OutputType outputTypes[] = {
559         gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
560         gls::DrawTestSpec::OUTPUTTYPE_VEC2,
561         gls::DrawTestSpec::OUTPUTTYPE_VEC3,
562         gls::DrawTestSpec::OUTPUTTYPE_VEC4,
563     };
564     const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
565 
566     static const gls::DrawTestSpec::Usage usages[] = {
567         gls::DrawTestSpec::USAGE_STATIC_DRAW,
568         gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
569         gls::DrawTestSpec::USAGE_STREAM_DRAW,
570     };
571     const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
572 
573     static const uint32_t disallowedCases[] = {
574         3153, //!< extremely narrow triangle, results depend on sample positions
575     };
576 
577     std::set<uint32_t> insertedHashes;
578     size_t insertedCount = 0;
579 
580     for (int ndx = 0; ndx < numAttempts; ++ndx)
581     {
582         de::Random random(0xc551393 + ndx); // random does not depend on previous cases
583 
584         int attributeCount = random.chooseWeighted<int, const int *, const float *>(
585             DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
586         gls::DrawTestSpec spec;
587 
588         spec.apiType   = glu::ApiType::es(2, 0);
589         spec.primitive = random.chooseWeighted<gls::DrawTestSpec::Primitive>(
590             DE_ARRAY_BEGIN(primitives), DE_ARRAY_END(primitives), primitiveWeights.weights);
591         spec.primitiveCount = random.chooseWeighted<int, const int *, const float *>(
592             DE_ARRAY_BEGIN(primitiveCounts), DE_ARRAY_END(primitiveCounts), primitiveCountWeights);
593         spec.drawMethod = random.chooseWeighted<gls::DrawTestSpec::DrawMethod>(
594             DE_ARRAY_BEGIN(drawMethods), DE_ARRAY_END(drawMethods), drawMethodWeights.weights);
595         spec.indexType = random.chooseWeighted<gls::DrawTestSpec::IndexType>(
596             DE_ARRAY_BEGIN(indexTypes), DE_ARRAY_END(indexTypes), indexTypeWeights.weights);
597         spec.indexPointerOffset = random.chooseWeighted<int, const int *, const float *>(
598             DE_ARRAY_BEGIN(indexOffsets), DE_ARRAY_END(indexOffsets), indexOffsetWeights);
599         spec.indexStorage = random.chooseWeighted<gls::DrawTestSpec::Storage>(
600             DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights);
601         spec.first         = random.chooseWeighted<int, const int *, const float *>(DE_ARRAY_BEGIN(firsts),
602                                                                             DE_ARRAY_END(firsts), firstWeights);
603         spec.indexMin      = 0;
604         spec.indexMax      = 0;
605         spec.instanceCount = 0;
606 
607         // check spec is legal
608         if (!spec.valid())
609             continue;
610 
611         for (int attrNdx = 0; attrNdx < attributeCount;)
612         {
613             bool valid;
614             gls::DrawTestSpec::AttributeSpec attribSpec;
615 
616             attribSpec.inputType = random.chooseWeighted<gls::DrawTestSpec::InputType>(
617                 DE_ARRAY_BEGIN(inputTypes), DE_ARRAY_END(inputTypes), inputTypeWeights.weights);
618             attribSpec.outputType = random.chooseWeighted<gls::DrawTestSpec::OutputType>(
619                 DE_ARRAY_BEGIN(outputTypes), DE_ARRAY_END(outputTypes), outputTypeWeights.weights);
620             attribSpec.storage = random.chooseWeighted<gls::DrawTestSpec::Storage>(
621                 DE_ARRAY_BEGIN(storages), DE_ARRAY_END(storages), storageWeights.weights);
622             attribSpec.usage = random.chooseWeighted<gls::DrawTestSpec::Usage>(
623                 DE_ARRAY_BEGIN(usages), DE_ARRAY_END(usages), usageWeights.weights);
624             attribSpec.componentCount = random.getInt(1, 4);
625             attribSpec.offset         = random.chooseWeighted<int, const int *, const float *>(
626                 DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
627             attribSpec.stride = random.chooseWeighted<int, const int *, const float *>(
628                 DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
629             attribSpec.normalize           = random.getBool();
630             attribSpec.instanceDivisor     = 0;
631             attribSpec.useDefaultAttribute = random.getBool();
632 
633             // check spec is legal
634             valid = attribSpec.valid(spec.apiType);
635 
636             // we do not want interleaved elements. (Might result in some weird floating point values)
637             if (attribSpec.stride &&
638                 attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
639                 valid = false;
640 
641             // try again if not valid
642             if (valid)
643             {
644                 spec.attribs.push_back(attribSpec);
645                 ++attrNdx;
646             }
647         }
648 
649         // Do not collapse all vertex positions to a single positions
650         if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
651             spec.attribs[0].instanceDivisor = 0;
652 
653         // Is render result meaningful?
654         {
655             // Only one vertex
656             if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED &&
657                 spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
658                 continue;
659             if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
660                 continue;
661 
662             // Triangle only on one axis
663             if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES ||
664                 spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN ||
665                 spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
666             {
667                 if (spec.attribs[0].componentCount == 1)
668                     continue;
669                 if (spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_FLOAT ||
670                     spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_INT ||
671                     spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_UINT)
672                     continue;
673                 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED &&
674                     (spec.indexMax - spec.indexMin) < 2)
675                     continue;
676             }
677         }
678 
679         // Add case
680         {
681             uint32_t hash = spec.hash();
682             for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
683                 hash = (hash << 2) ^ (uint32_t)spec.attribs[attrNdx].hash();
684 
685             if (insertedHashes.find(hash) == insertedHashes.end() &&
686                 !de::contains(DE_ARRAY_BEGIN(disallowedCases), DE_ARRAY_END(disallowedCases), hash))
687             {
688                 // Only aligned cases
689                 if (spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET &&
690                     spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
691                     this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec,
692                                                      de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
693                 insertedHashes.insert(hash);
694 
695                 ++insertedCount;
696             }
697         }
698     }
699 }
700 
701 } // namespace
702 
DrawTests(Context & context)703 DrawTests::DrawTests(Context &context) : TestCaseGroup(context, "draw", "Drawing tests")
704 {
705 }
706 
~DrawTests(void)707 DrawTests::~DrawTests(void)
708 {
709 }
710 
init(void)711 void DrawTests::init(void)
712 {
713     // Basic
714     {
715         const gls::DrawTestSpec::DrawMethod basicMethods[] = {
716             gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
717             gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
718         };
719 
720         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
721         {
722             std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
723             std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
724 
725             this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
726         }
727     }
728 
729     // Random
730 
731     this->addChild(new RandomGroup(m_context, "random", "random draw commands."));
732 }
733 
734 } // namespace Functional
735 } // namespace gles2
736 } // namespace deqp
737