am 57fda38b: am b00d353a: am 1b179ac7: am 220337ad: am 01516433: am 9252e819: Remove...
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fDrawTests.cpp
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 Drawing tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es3fDrawTests.hpp"
25 #include "glsDrawTest.hpp"
26 #include "tcuRenderTarget.hpp"
27 #include "sglrGLContext.hpp"
28 #include "glwEnums.hpp"
29 #include "deRandom.hpp"
30 #include "deStringUtil.hpp"
31 #include "deUniquePtr.hpp"
32 #include "deSTLUtil.hpp"
33
34 #include <set>
35
36 namespace deqp
37 {
38 namespace gles3
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         TYPE_INSTANCE_COUNT,    // !< test with 1, 4, and 11 instances
49         TYPE_INDEX_RANGE,               // !< test with index range of [0, 23], [23, 40], and [5, 5]
50
51         TYPE_LAST
52 };
53
54 static void addTestIterations (gls::DrawTest* test, const gls::DrawTestSpec& baseSpec, TestIterationType type)
55 {
56         gls::DrawTestSpec spec(baseSpec);
57
58         if (type == TYPE_DRAW_COUNT)
59         {
60                 spec.primitiveCount = 1;
61                 test->addIteration(spec, "draw count = 1");
62
63                 spec.primitiveCount = 5;
64                 test->addIteration(spec, "draw count = 5");
65
66                 spec.primitiveCount = 25;
67                 test->addIteration(spec, "draw count = 25");
68         }
69         else if (type == TYPE_INSTANCE_COUNT)
70         {
71                 spec.instanceCount = 1;
72                 test->addIteration(spec, "instance count = 1");
73
74                 spec.instanceCount = 4;
75                 test->addIteration(spec, "instance count = 4");
76
77                 spec.instanceCount = 11;
78                 test->addIteration(spec, "instance count = 11");
79         }
80         else if (type == TYPE_INDEX_RANGE)
81         {
82                 spec.indexMin = 0;
83                 spec.indexMax = 23;
84                 test->addIteration(spec, "index range = [0, 23]");
85
86                 spec.indexMin = 23;
87                 spec.indexMax = 40;
88                 test->addIteration(spec, "index range = [23, 40]");
89
90                 // Only makes sense with points
91                 if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_POINTS)
92                 {
93                         spec.indexMin = 5;
94                         spec.indexMax = 5;
95                         test->addIteration(spec, "index range = [5, 5]");
96                 }
97         }
98         else
99                 DE_ASSERT(false);
100 }
101
102 static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method)
103 {
104         spec.apiType                            = glu::ApiType::es(3,0);
105         spec.primitive                          = gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
106         spec.primitiveCount                     = 5;
107         spec.drawMethod                         = method;
108         spec.indexType                          = gls::DrawTestSpec::INDEXTYPE_LAST;
109         spec.indexPointerOffset         = 0;
110         spec.indexStorage                       = gls::DrawTestSpec::STORAGE_LAST;
111         spec.first                                      = 0;
112         spec.indexMin                           = 0;
113         spec.indexMax                           = 0;
114         spec.instanceCount                      = 1;
115
116         spec.attribs.resize(2);
117
118         spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
119         spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
120         spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
121         spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
122         spec.attribs[0].componentCount                  = 4;
123         spec.attribs[0].offset                                  = 0;
124         spec.attribs[0].stride                                  = 0;
125         spec.attribs[0].normalize                               = false;
126         spec.attribs[0].instanceDivisor                 = 0;
127         spec.attribs[0].useDefaultAttribute             = false;
128
129         spec.attribs[1].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
130         spec.attribs[1].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
131         spec.attribs[1].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
132         spec.attribs[1].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
133         spec.attribs[1].componentCount                  = 2;
134         spec.attribs[1].offset                                  = 0;
135         spec.attribs[1].stride                                  = 0;
136         spec.attribs[1].normalize                               = false;
137         spec.attribs[1].instanceDivisor                 = 0;
138         spec.attribs[1].useDefaultAttribute             = false;
139 }
140
141 class AttributeGroup : public TestCaseGroup
142 {
143 public:
144                                                                         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);
145                                                                         ~AttributeGroup (void);
146
147         void                                                    init                    (void);
148
149 private:
150         gls::DrawTestSpec::DrawMethod   m_method;
151         gls::DrawTestSpec::Primitive    m_primitive;
152         gls::DrawTestSpec::IndexType    m_indexType;
153         gls::DrawTestSpec::Storage              m_indexStorage;
154 };
155
156 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)
157         : TestCaseGroup         (context, name, descr)
158         , m_method                      (drawMethod)
159         , m_primitive           (primitive)
160         , m_indexType           (indexType)
161         , m_indexStorage        (indexStorage)
162 {
163 }
164
165 AttributeGroup::~AttributeGroup (void)
166 {
167 }
168
169 void AttributeGroup::init (void)
170 {
171         // select test type
172         const bool                              instanced                       = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED) ||
173                                                                                                   (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED);
174         const bool                              ranged                          = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
175         const TestIterationType testType                        = (instanced) ? (TYPE_INSTANCE_COUNT) : ((ranged) ? (TYPE_INDEX_RANGE) : (TYPE_DRAW_COUNT));
176
177         // Single attribute
178         {
179                 gls::DrawTest*          test                            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
180                 gls::DrawTestSpec       spec;
181
182                 spec.apiType                                                    = glu::ApiType::es(3,0);
183                 spec.primitive                                                  = m_primitive;
184                 spec.primitiveCount                                             = 5;
185                 spec.drawMethod                                                 = m_method;
186                 spec.indexType                                                  = m_indexType;
187                 spec.indexPointerOffset                                 = 0;
188                 spec.indexStorage                                               = m_indexStorage;
189                 spec.first                                                              = 0;
190                 spec.indexMin                                                   = 0;
191                 spec.indexMax                                                   = 0;
192                 spec.instanceCount                                              = 1;
193
194                 spec.attribs.resize(1);
195
196                 spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
197                 spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
198                 spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
199                 spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
200                 spec.attribs[0].componentCount                  = 2;
201                 spec.attribs[0].offset                                  = 0;
202                 spec.attribs[0].stride                                  = 0;
203                 spec.attribs[0].normalize                               = false;
204                 spec.attribs[0].instanceDivisor                 = 0;
205                 spec.attribs[0].useDefaultAttribute             = false;
206
207                 addTestIterations(test, spec, testType);
208
209                 this->addChild(test);
210         }
211
212         // Multiple attribute
213         {
214                 gls::DrawTest*          test                            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays.");
215                 gls::DrawTestSpec       spec;
216
217                 spec.apiType                                                    = glu::ApiType::es(3,0);
218                 spec.primitive                                                  = m_primitive;
219                 spec.primitiveCount                                             = 5;
220                 spec.drawMethod                                                 = m_method;
221                 spec.indexType                                                  = m_indexType;
222                 spec.indexPointerOffset                                 = 0;
223                 spec.indexStorage                                               = m_indexStorage;
224                 spec.first                                                              = 0;
225                 spec.indexMin                                                   = 0;
226                 spec.indexMax                                                   = 0;
227                 spec.instanceCount                                              = 1;
228
229                 spec.attribs.resize(2);
230
231                 spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
232                 spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
233                 spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
234                 spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
235                 spec.attribs[0].componentCount                  = 4;
236                 spec.attribs[0].offset                                  = 0;
237                 spec.attribs[0].stride                                  = 0;
238                 spec.attribs[0].normalize                               = false;
239                 spec.attribs[0].instanceDivisor                 = 0;
240                 spec.attribs[0].useDefaultAttribute             = false;
241
242                 spec.attribs[1].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
243                 spec.attribs[1].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
244                 spec.attribs[1].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
245                 spec.attribs[1].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
246                 spec.attribs[1].componentCount                  = 2;
247                 spec.attribs[1].offset                                  = 0;
248                 spec.attribs[1].stride                                  = 0;
249                 spec.attribs[1].normalize                               = false;
250                 spec.attribs[1].instanceDivisor                 = 0;
251                 spec.attribs[1].useDefaultAttribute             = false;
252
253                 addTestIterations(test, spec, testType);
254
255                 this->addChild(test);
256         }
257
258         // Multiple attribute, second one divided
259         {
260                 gls::DrawTest*          test                                    = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "instanced_attributes", "Instanced attribute array.");
261                 gls::DrawTestSpec       spec;
262
263                 spec.apiType                                                            = glu::ApiType::es(3,0);
264                 spec.primitive                                                          = m_primitive;
265                 spec.primitiveCount                                                     = 5;
266                 spec.drawMethod                                                         = m_method;
267                 spec.indexType                                                          = m_indexType;
268                 spec.indexPointerOffset                                         = 0;
269                 spec.indexStorage                                                       = m_indexStorage;
270                 spec.first                                                                      = 0;
271                 spec.indexMin                                                           = 0;
272                 spec.indexMax                                                           = 0;
273                 spec.instanceCount                                                      = 1;
274
275                 spec.attribs.resize(3);
276
277                 spec.attribs[0].inputType                                       = gls::DrawTestSpec::INPUTTYPE_FLOAT;
278                 spec.attribs[0].outputType                                      = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
279                 spec.attribs[0].storage                                         = gls::DrawTestSpec::STORAGE_BUFFER;
280                 spec.attribs[0].usage                                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
281                 spec.attribs[0].componentCount                          = 4;
282                 spec.attribs[0].offset                                          = 0;
283                 spec.attribs[0].stride                                          = 0;
284                 spec.attribs[0].normalize                                       = false;
285                 spec.attribs[0].instanceDivisor                         = 0;
286                 spec.attribs[0].useDefaultAttribute                     = false;
287
288                 // Add another position component so the instances wont be drawn on each other
289                 spec.attribs[1].inputType                                       = gls::DrawTestSpec::INPUTTYPE_FLOAT;
290                 spec.attribs[1].outputType                                      = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
291                 spec.attribs[1].storage                                         = gls::DrawTestSpec::STORAGE_BUFFER;
292                 spec.attribs[1].usage                                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
293                 spec.attribs[1].componentCount                          = 2;
294                 spec.attribs[1].offset                                          = 0;
295                 spec.attribs[1].stride                                          = 0;
296                 spec.attribs[1].normalize                                       = false;
297                 spec.attribs[1].instanceDivisor                         = 1;
298                 spec.attribs[1].useDefaultAttribute                     = false;
299                 spec.attribs[1].additionalPositionAttribute     = true;
300
301                 // Instanced color
302                 spec.attribs[2].inputType                                       = gls::DrawTestSpec::INPUTTYPE_FLOAT;
303                 spec.attribs[2].outputType                                      = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
304                 spec.attribs[2].storage                                         = gls::DrawTestSpec::STORAGE_BUFFER;
305                 spec.attribs[2].usage                                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
306                 spec.attribs[2].componentCount                          = 3;
307                 spec.attribs[2].offset                                          = 0;
308                 spec.attribs[2].stride                                          = 0;
309                 spec.attribs[2].normalize                                       = false;
310                 spec.attribs[2].instanceDivisor                         = 1;
311                 spec.attribs[2].useDefaultAttribute                     = false;
312
313                 addTestIterations(test, spec, testType);
314
315                 this->addChild(test);
316         }
317
318         // Multiple attribute, second one default
319         {
320                 gls::DrawTest*          test                            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*.");
321                 gls::DrawTestSpec       spec;
322
323                 spec.apiType                                                    = glu::ApiType::es(3,0);
324                 spec.primitive                                                  = m_primitive;
325                 spec.primitiveCount                                             = 5;
326                 spec.drawMethod                                                 = m_method;
327                 spec.indexType                                                  = m_indexType;
328                 spec.indexPointerOffset                                 = 0;
329                 spec.indexStorage                                               = m_indexStorage;
330                 spec.first                                                              = 0;
331                 spec.indexMin                                                   = 0;
332                 spec.indexMax                                                   = 20; // \note addTestIterations is not called for the spec, so we must ensure [indexMin, indexMax] is a good range
333                 spec.instanceCount                                              = 1;
334
335                 spec.attribs.resize(2);
336
337                 spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
338                 spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
339                 spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
340                 spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
341                 spec.attribs[0].componentCount                  = 2;
342                 spec.attribs[0].offset                                  = 0;
343                 spec.attribs[0].stride                                  = 0;
344                 spec.attribs[0].normalize                               = false;
345                 spec.attribs[0].instanceDivisor                 = 0;
346                 spec.attribs[0].useDefaultAttribute             = false;
347
348                 struct IOPair
349                 {
350                         gls::DrawTestSpec::InputType  input;
351                         gls::DrawTestSpec::OutputType output;
352                         int                                                       componentCount;
353                 } iopairs[] =
354                 {
355                         { gls::DrawTestSpec::INPUTTYPE_FLOAT,        gls::DrawTestSpec::OUTPUTTYPE_VEC2,  4 },
356                         { gls::DrawTestSpec::INPUTTYPE_FLOAT,        gls::DrawTestSpec::OUTPUTTYPE_VEC4,  2 },
357                         { gls::DrawTestSpec::INPUTTYPE_INT,          gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 4 },
358                         { gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 4 },
359                 };
360
361                 for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
362                 {
363                         const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
364
365                         spec.attribs[1].inputType                       = iopairs[ioNdx].input;
366                         spec.attribs[1].outputType                      = iopairs[ioNdx].output;
367                         spec.attribs[1].storage                         = gls::DrawTestSpec::STORAGE_BUFFER;
368                         spec.attribs[1].usage                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
369                         spec.attribs[1].componentCount          = iopairs[ioNdx].componentCount;
370                         spec.attribs[1].offset                          = 0;
371                         spec.attribs[1].stride                          = 0;
372                         spec.attribs[1].normalize                       = false;
373                         spec.attribs[1].instanceDivisor         = 0;
374                         spec.attribs[1].useDefaultAttribute     = true;
375
376                         test->addIteration(spec, desc.c_str());
377                 }
378
379                 this->addChild(test);
380         }
381 }
382
383 class IndexGroup : public TestCaseGroup
384 {
385 public:
386                                                                         IndexGroup              (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
387                                                                         ~IndexGroup             (void);
388
389         void                                                    init                    (void);
390
391 private:
392         gls::DrawTestSpec::DrawMethod   m_method;
393 };
394
395 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
396         : TestCaseGroup         (context, name, descr)
397         , m_method                      (drawMethod)
398 {
399 }
400
401 IndexGroup::~IndexGroup (void)
402 {
403 }
404
405 void IndexGroup::init (void)
406 {
407         struct IndexTest
408         {
409                 gls::DrawTestSpec::Storage              storage;
410                 gls::DrawTestSpec::IndexType    type;
411                 bool                                                    aligned;
412                 int                                                             offsets[3];
413         };
414
415         const IndexTest tests[] =
416         {
417                 { gls::DrawTestSpec::STORAGE_USER,              gls::DrawTestSpec::INDEXTYPE_BYTE,      true,   { 0, 1, -1 } },
418                 { gls::DrawTestSpec::STORAGE_USER,              gls::DrawTestSpec::INDEXTYPE_SHORT,     true,   { 0, 2, -1 } },
419                 { gls::DrawTestSpec::STORAGE_USER,              gls::DrawTestSpec::INDEXTYPE_INT,       true,   { 0, 4, -1 } },
420
421                 { gls::DrawTestSpec::STORAGE_USER,              gls::DrawTestSpec::INDEXTYPE_SHORT,     false,  { 1, 3, -1 } },
422                 { gls::DrawTestSpec::STORAGE_USER,              gls::DrawTestSpec::INDEXTYPE_INT,       false,  { 2, 3, -1 } },
423
424                 { gls::DrawTestSpec::STORAGE_BUFFER,    gls::DrawTestSpec::INDEXTYPE_BYTE,      true,   { 0, 1, -1 } },
425                 { gls::DrawTestSpec::STORAGE_BUFFER,    gls::DrawTestSpec::INDEXTYPE_SHORT,     true,   { 0, 2, -1 } },
426                 { gls::DrawTestSpec::STORAGE_BUFFER,    gls::DrawTestSpec::INDEXTYPE_INT,       true,   { 0, 4, -1 } },
427         };
428
429         gls::DrawTestSpec spec;
430
431         tcu::TestCaseGroup* userPtrGroup                        = new tcu::TestCaseGroup(m_testCtx, "user_ptr", "user pointer");
432         tcu::TestCaseGroup* unalignedUserPtrGroup       = new tcu::TestCaseGroup(m_testCtx, "unaligned_user_ptr", "unaligned user pointer");
433         tcu::TestCaseGroup* bufferGroup                         = new tcu::TestCaseGroup(m_testCtx, "buffer", "buffer");
434
435         genBasicSpec(spec, m_method);
436
437         this->addChild(userPtrGroup);
438         this->addChild(unalignedUserPtrGroup);
439         this->addChild(bufferGroup);
440
441         for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
442         {
443                 const IndexTest&                                indexTest       = tests[testNdx];
444                 tcu::TestCaseGroup*                             group           = (indexTest.storage == gls::DrawTestSpec::STORAGE_USER)
445                                                                                                         ? ((indexTest.aligned) ? (userPtrGroup) : (unalignedUserPtrGroup))
446                                                                                                         : ((indexTest.aligned) ? (bufferGroup) : (DE_NULL));
447
448                 const std::string                               name            = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
449                 const std::string                               desc            = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage);
450                 de::MovePtr<gls::DrawTest>              test            (new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()));
451
452                 spec.indexType                  = indexTest.type;
453                 spec.indexStorage               = indexTest.storage;
454
455                 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
456                 {
457                         const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]);
458                         spec.indexPointerOffset = indexTest.offsets[iterationNdx];
459                         test->addIteration(spec, iterationDesc.c_str());
460                 }
461
462                 DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET);
463                 DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE);
464                 group->addChild(test.release());
465         }
466 }
467
468
469 class FirstGroup : public TestCaseGroup
470 {
471 public:
472                                                                         FirstGroup              (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
473                                                                         ~FirstGroup             (void);
474
475         void                                                    init                    (void);
476
477 private:
478         gls::DrawTestSpec::DrawMethod   m_method;
479 };
480
481 FirstGroup::FirstGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
482         : TestCaseGroup         (context, name, descr)
483         , m_method                      (drawMethod)
484 {
485 }
486
487 FirstGroup::~FirstGroup (void)
488 {
489 }
490
491 void FirstGroup::init (void)
492 {
493         const int firsts[] =
494         {
495                 1, 3, 17
496         };
497
498         gls::DrawTestSpec spec;
499         genBasicSpec(spec, m_method);
500
501         for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); ++firstNdx)
502         {
503                 const std::string       name = std::string("first_") + de::toString(firsts[firstNdx]);
504                 const std::string       desc = std::string("first ") + de::toString(firsts[firstNdx]);
505                 gls::DrawTest*          test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
506
507                 spec.first = firsts[firstNdx];
508
509                 addTestIterations(test, spec, TYPE_DRAW_COUNT);
510
511                 this->addChild(test);
512         }
513 }
514
515 class MethodGroup : public TestCaseGroup
516 {
517 public:
518                                                                         MethodGroup                     (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
519                                                                         ~MethodGroup            (void);
520
521         void                                                    init                            (void);
522
523 private:
524         gls::DrawTestSpec::DrawMethod   m_method;
525 };
526
527 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
528         : TestCaseGroup         (context, name, descr)
529         , m_method                      (drawMethod)
530 {
531 }
532
533 MethodGroup::~MethodGroup (void)
534 {
535 }
536
537 void MethodGroup::init (void)
538 {
539         const bool indexed              = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
540         const bool hasFirst             = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED);
541
542         const gls::DrawTestSpec::Primitive primitive[] =
543         {
544                 gls::DrawTestSpec::PRIMITIVE_POINTS,
545                 gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
546                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
547                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
548                 gls::DrawTestSpec::PRIMITIVE_LINES,
549                 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
550                 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
551         };
552
553         if (hasFirst)
554         {
555                 // First-tests
556                 this->addChild(new FirstGroup(m_context, "first", "First tests", m_method));
557         }
558
559         if (indexed)
560         {
561                 // Index-tests
562                 if (m_method != gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED)
563                         this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
564         }
565
566         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
567         {
568                 const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
569                 const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
570
571                 this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
572         }
573 }
574
575 class GridProgram : public sglr::ShaderProgram
576 {
577 public:
578                         GridProgram             (void);
579
580         void    shadeVertices   (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
581         void    shadeFragments  (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
582 };
583
584 GridProgram::GridProgram (void)
585         : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
586                                                         << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
587                                                         << sglr::pdec::VertexAttribute("a_offset", rr::GENERICVECTYPE_FLOAT)
588                                                         << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT)
589                                                         << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
590                                                         << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
591                                                         << sglr::pdec::VertexSource("#version 300 es\n"
592                                                                                                                 "in highp vec4 a_position;\n"
593                                                                                                                 "in highp vec4 a_offset;\n"
594                                                                                                                 "in highp vec4 a_color;\n"
595                                                                                                                 "out mediump vec4 v_color;\n"
596                                                                                                                 "void main(void)\n"
597                                                                                                                 "{\n"
598                                                                                                                 "       gl_Position = a_position + a_offset;\n"
599                                                                                                                 "       v_color = a_color;\n"
600                                                                                                                 "}\n")
601                                                         << sglr::pdec::FragmentSource(
602                                                                                                                 "#version 300 es\n"
603                                                                                                                 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
604                                                                                                                 "in mediump vec4 v_color;\n"
605                                                                                                                 "void main(void)\n"
606                                                                                                                 "{\n"
607                                                                                                                 "       dEQP_FragColor = v_color;\n"
608                                                                                                                 "}\n"))
609 {
610 }
611
612 void GridProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
613 {
614         for (int ndx = 0; ndx < numPackets; ++ndx)
615         {
616                 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx) + rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
617                 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[2], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
618         }
619 }
620
621 void GridProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
622 {
623         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
624         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
625                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx));
626 }
627
628 class InstancedGridRenderTest : public TestCase
629 {
630 public:
631                                         InstancedGridRenderTest         (Context& context, const char* name, const char* desc, int gridSide, bool useIndices);
632                                         ~InstancedGridRenderTest        (void);
633
634         IterateResult   iterate                                         (void);
635
636 private:
637         void                    renderTo                                        (sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dst);
638         bool                    verifyImage                                     (const tcu::Surface& image);
639
640         const int               m_gridSide;
641         const bool              m_useIndices;
642 };
643
644 InstancedGridRenderTest::InstancedGridRenderTest (Context& context, const char* name, const char* desc, int gridSide, bool useIndices)
645         : TestCase              (context, name, desc)
646         , m_gridSide    (gridSide)
647         , m_useIndices  (useIndices)
648 {
649 }
650
651 InstancedGridRenderTest::~InstancedGridRenderTest (void)
652 {
653 }
654
655 InstancedGridRenderTest::IterateResult InstancedGridRenderTest::iterate (void)
656 {
657         const int renderTargetWidth  = de::min(1024, m_context.getRenderTarget().getWidth());
658         const int renderTargetHeight = de::min(1024, m_context.getRenderTarget().getHeight());
659
660         sglr::GLContext ctx             (m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(0, 0, renderTargetWidth, renderTargetHeight));
661         tcu::Surface    surface (renderTargetWidth, renderTargetHeight);
662         GridProgram             program;
663
664         // render
665
666         renderTo(ctx, program, surface);
667
668         // verify image
669
670         if (verifyImage(surface))
671                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
672         else
673                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rendering result");
674         return STOP;
675 }
676
677 void InstancedGridRenderTest::renderTo (sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dst)
678 {
679         const tcu::Vec4 green   (0, 1, 0, 1);
680         const tcu::Vec4 yellow  (1, 1, 0, 1);
681
682         deUint32 positionBuf    = 0;
683         deUint32 offsetBuf              = 0;
684         deUint32 colorBuf               = 0;
685         deUint32 indexBuf               = 0;
686         deUint32 programID              = ctx.createProgram(&program);
687         deInt32 posLocation             = ctx.getAttribLocation(programID, "a_position");
688         deInt32 offsetLocation  = ctx.getAttribLocation(programID, "a_offset");
689         deInt32 colorLocation   = ctx.getAttribLocation(programID, "a_color");
690
691         float cellW     = 2.0f / (float)m_gridSide;
692         float cellH     = 2.0f / (float)m_gridSide;
693         const tcu::Vec4 vertexPositions[] =
694         {
695                 tcu::Vec4(0,            0,              0, 1),
696                 tcu::Vec4(cellW,        0,              0, 1),
697                 tcu::Vec4(0,            cellH,  0, 1),
698
699                 tcu::Vec4(0,            cellH,  0, 1),
700                 tcu::Vec4(cellW,        0,              0, 1),
701                 tcu::Vec4(cellW,        cellH,  0, 1),
702         };
703
704         const deUint16 indices[] =
705         {
706                 0, 4, 3,
707                 2, 1, 5
708         };
709
710         std::vector<tcu::Vec4> offsets;
711         for (int x = 0; x < m_gridSide; ++x)
712         for (int y = 0; y < m_gridSide; ++y)
713                 offsets.push_back(tcu::Vec4((float)x * cellW - 1.0f, (float)y * cellW - 1.0f, 0, 0));
714
715         std::vector<tcu::Vec4> colors;
716         for (int x = 0; x < m_gridSide; ++x)
717         for (int y = 0; y < m_gridSide; ++y)
718                 colors.push_back(((x + y) % 2 == 0) ? (green) : (yellow));
719
720         ctx.genBuffers(1, &positionBuf);
721         ctx.bindBuffer(GL_ARRAY_BUFFER, positionBuf);
722         ctx.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
723         ctx.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
724         ctx.vertexAttribDivisor(posLocation, 0);
725         ctx.enableVertexAttribArray(posLocation);
726
727         ctx.genBuffers(1, &offsetBuf);
728         ctx.bindBuffer(GL_ARRAY_BUFFER, offsetBuf);
729         ctx.bufferData(GL_ARRAY_BUFFER, offsets.size() * sizeof(tcu::Vec4), &offsets[0], GL_STATIC_DRAW);
730         ctx.vertexAttribPointer(offsetLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
731         ctx.vertexAttribDivisor(offsetLocation, 1);
732         ctx.enableVertexAttribArray(offsetLocation);
733
734         ctx.genBuffers(1, &colorBuf);
735         ctx.bindBuffer(GL_ARRAY_BUFFER, colorBuf);
736         ctx.bufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(tcu::Vec4), &colors[0], GL_STATIC_DRAW);
737         ctx.vertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
738         ctx.vertexAttribDivisor(colorLocation, 1);
739         ctx.enableVertexAttribArray(colorLocation);
740
741         if (m_useIndices)
742         {
743                 ctx.genBuffers(1, &indexBuf);
744                 ctx.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
745                 ctx.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
746         }
747
748         ctx.clearColor(0, 0, 0, 1);
749         ctx.clear(GL_COLOR_BUFFER_BIT);
750
751         ctx.viewport(0, 0, dst.getWidth(), dst.getHeight());
752
753         ctx.useProgram(programID);
754         if (m_useIndices)
755                 ctx.drawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL, m_gridSide * m_gridSide);
756         else
757                 ctx.drawArraysInstanced(GL_TRIANGLES, 0, 6, m_gridSide * m_gridSide);
758         ctx.useProgram(0);
759
760         if (m_useIndices)
761                 ctx.deleteBuffers(1, &indexBuf);
762         ctx.deleteBuffers(1, &colorBuf);
763         ctx.deleteBuffers(1, &offsetBuf);
764         ctx.deleteBuffers(1, &positionBuf);
765         ctx.deleteProgram(programID);
766
767         ctx.finish();
768         ctx.readPixels(dst, 0, 0, dst.getWidth(), dst.getHeight());
769
770         glu::checkError(ctx.getError(), "", __FILE__, __LINE__);
771 }
772
773 bool InstancedGridRenderTest::verifyImage (const tcu::Surface& image)
774 {
775         // \note the green/yellow pattern is only for clarity. The test will only verify that all instances were drawn by looking for anything non-green/yellow.
776         using tcu::TestLog;
777
778         const int colorThreshold        = 20;
779
780         tcu::Surface error                      (image.getWidth(), image.getHeight());
781         bool isOk                                       = true;
782
783         for (int y = 0; y < image.getHeight(); y++)
784         for (int x = 0; x < image.getWidth(); x++)
785         {
786                 if (x == 0 || y == 0 || y + 1 == image.getHeight() || x + 1 == image.getWidth())
787                 {
788                         // Background color might bleed in at the borders with msaa
789                         error.setPixel(x, y, tcu::RGBA(0, 255, 0, 255));
790                 }
791                 else
792                 {
793                         const tcu::RGBA pixel = image.getPixel(x, y);
794                         bool pixelOk = true;
795
796                         // Any pixel with !(G ~= 255) is faulty (not a linear combinations of green and yellow)
797                         if (de::abs(pixel.getGreen() - 255) > colorThreshold)
798                                 pixelOk = false;
799
800                         // Any pixel with !(B ~= 0) is faulty (not a linear combinations of green and yellow)
801                         if (de::abs(pixel.getBlue() - 0) > colorThreshold)
802                                 pixelOk = false;
803
804                         error.setPixel(x, y, (pixelOk) ? (tcu::RGBA(0, 255, 0, 255)) : (tcu::RGBA(255, 0, 0, 255)));
805                         isOk = isOk && pixelOk;
806                 }
807         }
808
809         if (!isOk)
810         {
811                 tcu::TestLog& log = m_testCtx.getLog();
812
813                 log << TestLog::Message << "Image verification failed." << TestLog::EndMessage;
814                 log << TestLog::ImageSet("Verfication result", "Result of rendering")
815                         << TestLog::Image("Result",             "Result",               image)
816                         << TestLog::Image("ErrorMask",  "Error mask",   error)
817                         << TestLog::EndImageSet;
818         }
819         else
820         {
821                 tcu::TestLog& log = m_testCtx.getLog();
822
823                 log << TestLog::ImageSet("Verfication result", "Result of rendering")
824                         << TestLog::Image("Result", "Result", image)
825                         << TestLog::EndImageSet;
826         }
827
828         return isOk;
829 }
830
831 class InstancingGroup : public TestCaseGroup
832 {
833 public:
834                                                                         InstancingGroup         (Context& context, const char* name, const char* descr);
835                                                                         ~InstancingGroup        (void);
836
837         void                                                    init                            (void);
838 };
839
840 InstancingGroup::InstancingGroup (Context& context, const char* name, const char* descr)
841         : TestCaseGroup (context, name, descr)
842 {
843 }
844
845 InstancingGroup::~InstancingGroup (void)
846 {
847 }
848
849 void InstancingGroup::init (void)
850 {
851         const int gridWidths[] =
852         {
853                 2,
854                 5,
855                 10,
856                 32,
857                 100,
858         };
859
860         // drawArrays
861         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(gridWidths); ++ndx)
862         {
863                 const std::string name = std::string("draw_arrays_instanced_grid_") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
864                 const std::string desc = std::string("DrawArraysInstanced, Grid size ") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
865
866                 this->addChild(new InstancedGridRenderTest(m_context, name.c_str(), desc.c_str(), gridWidths[ndx], false));
867         }
868
869         // drawElements
870         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(gridWidths); ++ndx)
871         {
872                 const std::string name = std::string("draw_elements_instanced_grid_") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
873                 const std::string desc = std::string("DrawElementsInstanced, Grid size ") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
874
875                 this->addChild(new InstancedGridRenderTest(m_context, name.c_str(), desc.c_str(), gridWidths[ndx], true));
876         }
877 }
878
879 class RandomGroup : public TestCaseGroup
880 {
881 public:
882                                                                         RandomGroup             (Context& context, const char* name, const char* descr);
883                                                                         ~RandomGroup    (void);
884
885         void                                                    init                    (void);
886 };
887
888 template <int SIZE>
889 struct UniformWeightArray
890 {
891         float weights[SIZE];
892
893         UniformWeightArray (void)
894         {
895                 for (int i=0; i<SIZE; ++i)
896                         weights[i] = 1.0f;
897         }
898 };
899
900 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
901         : TestCaseGroup (context, name, descr)
902 {
903 }
904
905 RandomGroup::~RandomGroup (void)
906 {
907 }
908
909 void RandomGroup::init (void)
910 {
911         const int                       numAttempts                             = 300;
912
913         static const int        attribCounts[]                  = { 1, 2, 5 };
914         static const float      attribWeights[]                 = { 30, 10, 1 };
915         static const int        primitiveCounts[]               = { 1, 5, 64 };
916         static const float      primitiveCountWeights[] = { 20, 10, 1 };
917         static const int        indexOffsets[]                  = { 0, 7, 13 };
918         static const float      indexOffsetWeights[]    = { 20, 20, 1 };
919         static const int        firsts[]                                = { 0, 7, 13 };
920         static const float      firstWeights[]                  = { 20, 20, 1 };
921         static const int        instanceCounts[]                = { 1, 2, 16, 17 };
922         static const float      instanceWeights[]               = { 20, 10, 5, 1 };
923         static const int        indexMins[]                             = { 0, 1, 3, 8 };
924         static const int        indexMaxs[]                             = { 4, 8, 128, 257 };
925         static const float      indexWeights[]                  = { 50, 50, 50, 50 };
926         static const int        offsets[]                               = { 0, 1, 5, 12 };
927         static const float      offsetWeights[]                 = { 50, 10, 10, 10 };
928         static const int        strides[]                               = { 0, 7, 16, 17 };
929         static const float      strideWeights[]                 = { 50, 10, 10, 10 };
930         static const int        instanceDivisors[]              = { 0, 1, 3, 129 };
931         static const float      instanceDivisorWeights[]= { 70, 30, 10, 10 };
932
933         static const gls::DrawTestSpec::Primitive primitives[] =
934         {
935                 gls::DrawTestSpec::PRIMITIVE_POINTS,
936                 gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
937                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
938                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
939                 gls::DrawTestSpec::PRIMITIVE_LINES,
940                 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
941                 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
942         };
943         const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
944
945         static const gls::DrawTestSpec::DrawMethod drawMethods[] =
946         {
947                 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
948                 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED,
949                 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
950                 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED,
951                 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED
952         };
953         const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
954
955         static const gls::DrawTestSpec::IndexType indexTypes[] =
956         {
957                 gls::DrawTestSpec::INDEXTYPE_BYTE,
958                 gls::DrawTestSpec::INDEXTYPE_SHORT,
959                 gls::DrawTestSpec::INDEXTYPE_INT,
960         };
961         const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
962
963         static const gls::DrawTestSpec::Storage storages[] =
964         {
965                 gls::DrawTestSpec::STORAGE_USER,
966                 gls::DrawTestSpec::STORAGE_BUFFER,
967         };
968         const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights;
969
970         static const gls::DrawTestSpec::InputType inputTypes[] =
971         {
972                 gls::DrawTestSpec::INPUTTYPE_FLOAT,
973                 gls::DrawTestSpec::INPUTTYPE_FIXED,
974                 gls::DrawTestSpec::INPUTTYPE_BYTE,
975                 gls::DrawTestSpec::INPUTTYPE_SHORT,
976                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
977                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT,
978                 gls::DrawTestSpec::INPUTTYPE_INT,
979                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT,
980                 gls::DrawTestSpec::INPUTTYPE_HALF,
981                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10,
982                 gls::DrawTestSpec::INPUTTYPE_INT_2_10_10_10,
983         };
984         const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
985
986         static const gls::DrawTestSpec::OutputType outputTypes[] =
987         {
988                 gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
989                 gls::DrawTestSpec::OUTPUTTYPE_VEC2,
990                 gls::DrawTestSpec::OUTPUTTYPE_VEC3,
991                 gls::DrawTestSpec::OUTPUTTYPE_VEC4,
992                 gls::DrawTestSpec::OUTPUTTYPE_INT,
993                 gls::DrawTestSpec::OUTPUTTYPE_UINT,
994                 gls::DrawTestSpec::OUTPUTTYPE_IVEC2,
995                 gls::DrawTestSpec::OUTPUTTYPE_IVEC3,
996                 gls::DrawTestSpec::OUTPUTTYPE_IVEC4,
997                 gls::DrawTestSpec::OUTPUTTYPE_UVEC2,
998                 gls::DrawTestSpec::OUTPUTTYPE_UVEC3,
999                 gls::DrawTestSpec::OUTPUTTYPE_UVEC4,
1000         };
1001         const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
1002
1003         static const gls::DrawTestSpec::Usage usages[] =
1004         {
1005                 gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
1006                 gls::DrawTestSpec::USAGE_STATIC_DRAW,
1007                 gls::DrawTestSpec::USAGE_STREAM_DRAW,
1008                 gls::DrawTestSpec::USAGE_STREAM_READ,
1009                 gls::DrawTestSpec::USAGE_STREAM_COPY,
1010                 gls::DrawTestSpec::USAGE_STATIC_READ,
1011                 gls::DrawTestSpec::USAGE_STATIC_COPY,
1012                 gls::DrawTestSpec::USAGE_DYNAMIC_READ,
1013                 gls::DrawTestSpec::USAGE_DYNAMIC_COPY,
1014         };
1015         const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
1016
1017         static const deUint32 blacklistedCases[]=
1018         {
1019                 544,    //!< extremely narrow triangle
1020         };
1021
1022         std::set<deUint32>      insertedHashes;
1023         size_t                          insertedCount = 0;
1024
1025         for (int ndx = 0; ndx < numAttempts; ++ndx)
1026         {
1027                 de::Random random(0xc551393 + ndx); // random does not depend on previous cases
1028
1029                 int                                     attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
1030                 gls::DrawTestSpec       spec;
1031
1032                 spec.apiType                            = glu::ApiType::es(3,0);
1033                 spec.primitive                          = random.chooseWeighted<gls::DrawTestSpec::Primitive>   (DE_ARRAY_BEGIN(primitives),            DE_ARRAY_END(primitives),               primitiveWeights.weights);
1034                 spec.primitiveCount                     = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(primitiveCounts),       DE_ARRAY_END(primitiveCounts),  primitiveCountWeights);
1035                 spec.drawMethod                         = random.chooseWeighted<gls::DrawTestSpec::DrawMethod>  (DE_ARRAY_BEGIN(drawMethods),           DE_ARRAY_END(drawMethods),              drawMethodWeights.weights);
1036                 spec.indexType                          = random.chooseWeighted<gls::DrawTestSpec::IndexType>   (DE_ARRAY_BEGIN(indexTypes),            DE_ARRAY_END(indexTypes),               indexTypeWeights.weights);
1037                 spec.indexPointerOffset         = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(indexOffsets),          DE_ARRAY_END(indexOffsets),             indexOffsetWeights);
1038                 spec.indexStorage                       = random.chooseWeighted<gls::DrawTestSpec::Storage>             (DE_ARRAY_BEGIN(storages),                      DE_ARRAY_END(storages),                 storageWeights.weights);
1039                 spec.first                                      = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(firsts),                        DE_ARRAY_END(firsts),                   firstWeights);
1040                 spec.indexMin                           = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(indexMins),                     DE_ARRAY_END(indexMins),                indexWeights);
1041                 spec.indexMax                           = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(indexMaxs),                     DE_ARRAY_END(indexMaxs),                indexWeights);
1042                 spec.instanceCount                      = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(instanceCounts),        DE_ARRAY_END(instanceCounts),   instanceWeights);
1043
1044                 // check spec is legal
1045                 if (!spec.valid())
1046                         continue;
1047
1048                 for (int attrNdx = 0; attrNdx < attributeCount;)
1049                 {
1050                         bool valid;
1051                         gls::DrawTestSpec::AttributeSpec attribSpec;
1052
1053                         attribSpec.inputType                    = random.chooseWeighted<gls::DrawTestSpec::InputType>   (DE_ARRAY_BEGIN(inputTypes),            DE_ARRAY_END(inputTypes),               inputTypeWeights.weights);
1054                         attribSpec.outputType                   = random.chooseWeighted<gls::DrawTestSpec::OutputType>  (DE_ARRAY_BEGIN(outputTypes),           DE_ARRAY_END(outputTypes),              outputTypeWeights.weights);
1055                         attribSpec.storage                              = random.chooseWeighted<gls::DrawTestSpec::Storage>             (DE_ARRAY_BEGIN(storages),                      DE_ARRAY_END(storages),                 storageWeights.weights);
1056                         attribSpec.usage                                = random.chooseWeighted<gls::DrawTestSpec::Usage>               (DE_ARRAY_BEGIN(usages),                        DE_ARRAY_END(usages),                   usageWeights.weights);
1057                         attribSpec.componentCount               = random.getInt(1, 4);
1058                         attribSpec.offset                               = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
1059                         attribSpec.stride                               = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
1060                         attribSpec.normalize                    = random.getBool();
1061                         attribSpec.instanceDivisor              = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(instanceDivisors), DE_ARRAY_END(instanceDivisors), instanceDivisorWeights);
1062                         attribSpec.useDefaultAttribute  = random.getBool();
1063
1064                         // check spec is legal
1065                         valid = attribSpec.valid(spec.apiType);
1066
1067                         // we do not want interleaved elements. (Might result in some weird floating point values)
1068                         if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
1069                                 valid = false;
1070
1071                         // try again if not valid
1072                         if (valid)
1073                         {
1074                                 spec.attribs.push_back(attribSpec);
1075                                 ++attrNdx;
1076                         }
1077                 }
1078
1079                 // Do not collapse all vertex positions to a single positions
1080                 if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
1081                         spec.attribs[0].instanceDivisor = 0;
1082
1083                 // Is render result meaningful?
1084                 {
1085                         // Only one vertex
1086                         if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
1087                                 continue;
1088                         if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
1089                                 continue;
1090
1091                         // Triangle only on one axis
1092                         if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
1093                         {
1094                                 if (spec.attribs[0].componentCount == 1)
1095                                         continue;
1096                                 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)
1097                                         continue;
1098                                 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
1099                                         continue;
1100                         }
1101                 }
1102
1103                 // Add case
1104                 {
1105                         deUint32 hash = spec.hash();
1106                         for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
1107                                 hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash();
1108
1109                         if (insertedHashes.find(hash) == insertedHashes.end())
1110                         {
1111                                 // Only properly aligned and not blacklisted cases
1112                                 if (spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET                     &&
1113                                         spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE                 &&
1114                                         !de::contains(DE_ARRAY_BEGIN(blacklistedCases), DE_ARRAY_END(blacklistedCases), hash))
1115                                 {
1116                                         this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
1117                                 }
1118                                 insertedHashes.insert(hash);
1119
1120                                 ++insertedCount;
1121                         }
1122                 }
1123         }
1124 }
1125
1126 } // anonymous
1127
1128 DrawTests::DrawTests (Context& context)
1129         : TestCaseGroup(context, "draw", "Drawing tests")
1130 {
1131 }
1132
1133 DrawTests::~DrawTests (void)
1134 {
1135 }
1136
1137 void DrawTests::init (void)
1138 {
1139         // Basic
1140         {
1141                 const gls::DrawTestSpec::DrawMethod basicMethods[] =
1142                 {
1143                         gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
1144                         gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
1145                         gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED,
1146                         gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED,
1147                         gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED,
1148                 };
1149
1150                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
1151                 {
1152                         const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
1153                         const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
1154
1155                         this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
1156                 }
1157         }
1158
1159         // extreme instancing
1160
1161         this->addChild(new InstancingGroup(m_context, "instancing", "draw tests with a large instance count."));
1162
1163         // Random
1164
1165         this->addChild(new RandomGroup(m_context, "random", "random draw commands."));
1166 }
1167
1168 } // Functional
1169 } // gles3
1170 } // deqp