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